diff --git a/spec/std/isa/csr/cycle.yaml b/spec/std/isa/csr/cycle.yaml index 5f4de14d7d..32a5e55b75 100644 --- a/spec/std/isa/csr/cycle.yaml +++ b/spec/std/isa/csr/cycle.yaml @@ -45,7 +45,7 @@ sw_read(): | raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } } else if (mode() == PrivilegeMode::U) { - if (CSR[misa].S == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || 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) { diff --git a/spec/std/isa/csr/mip.yaml b/spec/std/isa/csr/mip.yaml index 189426667c..603cf05b60 100644 --- a/spec/std/isa/csr/mip.yaml +++ b/spec/std/isa/csr/mip.yaml @@ -411,6 +411,6 @@ sw_read(): | # OR in the hidden smode external interrupt return $bits(CSR[mip]) - | ((CSR[misa].S == 1'b1 && pending_smode_external_interrupt) + | (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && pending_smode_external_interrupt ? 10'h200 : 0); diff --git a/spec/std/isa/csr/misa.yaml b/spec/std/isa/csr/misa.yaml index c7a18ba819..f57ea9bf60 100644 --- a/spec/std/isa/csr/misa.yaml +++ b/spec/std/isa/csr/misa.yaml @@ -8,10 +8,14 @@ kind: csr name: misa long_name: Machine ISA Control address: 0x301 +# writable when misa CSR is implemented; read-only-0 otherwise writable: true priv_mode: M length: MXLEN -description: Reports the XLEN and "major" extensions supported by the ISA. +description: | + Reports the XLEN and "major" extensions supported by the ISA. + [when,"MISA_CSR_IMPLEMENTED == false"] + This CSR is read-only-0 (all bits hardwired to zero) and cannot be written. definedBy: Sm fields: MXL: @@ -20,7 +24,11 @@ fields: description: XLEN in M-mode. type: RO reset_value(): | - return (MXLEN == 32) ? 2'b01 : 2'b10; + if (MISA_CSR_IMPLEMENTED) { + return (MXLEN == 32) ? 2'b01 : 2'b10; + } else { + return 0; + } A: location: 0 description: | @@ -29,9 +37,17 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::A) && MUTABLE_MISA_A) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::A) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::A) ? 1 : 0; + } else { + return 0; + } definedBy: A B: location: 1 @@ -41,9 +57,17 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::B) && MUTABLE_MISA_B) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::B) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::B) ? 1 : 0; + } else { + return 0; + } definedBy: B C: location: 2 @@ -54,9 +78,17 @@ fields: 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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::C) && MUTABLE_MISA_C) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::C) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::C) ? 1 : 0; + } else { + return 0; + } definedBy: C D: location: 3 @@ -70,9 +102,17 @@ fields: 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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::D) && MUTABLE_MISA_D) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::D) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::D) ? 1 : 0; + } else { + return 0; + } definedBy: D F: location: 5 @@ -86,38 +126,51 @@ fields: 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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::F) && MUTABLE_MISA_F) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::F) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::F) ? 1 : 0; + } else { + return 0; + } definedBy: F 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; + if (MISA_CSR_IMPLEMENTED) { + 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; + } } else { return CsrFieldType::RO; } reset_value(): | - return ( - implemented?(ExtensionName::A) && - implemented?(ExtensionName::M) && - implemented?(ExtensionName::F) && - implemented?(ExtensionName::D)) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return ( + implemented?(ExtensionName::A) && + implemented?(ExtensionName::M) && + implemented?(ExtensionName::F) && + implemented?(ExtensionName::D)) ? 1 : 0; + } else { + return 0; + } H: location: 7 description: | @@ -126,17 +179,26 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H) && MUTABLE_MISA_H) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } definedBy: H reset_value(): | - return implemented?(ExtensionName::H) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::H) ? 1 : 0; + } else { + return 0; + } I: location: 8 description: | Indicates support for the `I` (base) extension. type: RO definedBy: I - reset_value: 1 + reset_value(): | + return MISA_CSR_IMPLEMENTED ? 1 : 0; M: location: 12 description: | @@ -145,9 +207,17 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED) { + return (implemented?(ExtensionName::M) && MUTABLE_MISA_M) ? CsrFieldType::RW : CsrFieldType::RO; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::M) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::M) ? 1 : 0; + } else { + return 0; + } definedBy: M cert_normative_rules: - id: csr_field.misa.M.disabled @@ -182,8 +252,13 @@ fields: Writing 0 to this field will cause all quad-precision floating point instructions to raise an `IllegalInstruction` exception. -- type(): | - return MUTABLE_MISA_Q ? CsrFieldType::RW : CsrFieldType::RO; - reset_value: 1 + if (MISA_CSR_IMPLEMENTED) { + return MUTABLE_MISA_Q ? CsrFieldType::RW : CsrFieldType::RO; + } else { + return CsrFieldType::RO; + } + reset_value(): | + return MISA_CSR_IMPLEMENTED ? 1 : 0; definedBy: Q sw_write(csr_value): | if ((csr_value.F == 0 || csr_value.D == 0) && csr_value.Q == 1) { @@ -192,8 +267,6 @@ fields: # fall-through; write the intended value return csr_value.Q; - legal?(csr_value): | - return !(csr_value.Q == 1 && csr_value.D == 0); S: location: 18 description: | @@ -202,9 +275,17 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S) && MUTABLE_MISA_S) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::S) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::S) ? 1 : 0; + } else { + return 0; + } definedBy: S U: location: 20 @@ -214,9 +295,17 @@ fields: [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; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::U) && MUTABLE_MISA_U) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::U) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::U) ? 1 : 0; + } else { + return 0; + } definedBy: U V: location: 21 @@ -226,11 +315,22 @@ fields: [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(): | - return (implemented?(ExtensionName::V) && MUTABLE_MISA_V) ? CsrFieldType::RW : CsrFieldType::RO; + if (MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::V) && MUTABLE_MISA_V) { + return CsrFieldType::RW; + } else { + return CsrFieldType::RO; + } reset_value(): | - return implemented?(ExtensionName::V) ? 1 : 0; + if (MISA_CSR_IMPLEMENTED) { + return implemented?(ExtensionName::V) ? 1 : 0; + } else { + return 0; + } definedBy: V sw_read(): | + if (!MISA_CSR_IMPLEMENTED) { + return 0; + } return ( (CSR[misa].MXL << (xlen() - 2)) | (CSR[misa].V << 21) | @@ -238,10 +338,10 @@ sw_read(): | (CSR[misa].S << 18) | (CSR[misa].Q << 16) | (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].I << 8) | + (CSR[misa].H << 7) | + ((CSR[misa].A & CSR[misa].M & CSR[misa].F & CSR[misa].D) << 6) | # 'G' + (CSR[misa].F << 5) | (CSR[misa].D << 3) | (CSR[misa].C << 2) | (CSR[misa].B << 1) | diff --git a/spec/std/isa/csr/mstatus.yaml b/spec/std/isa/csr/mstatus.yaml index 877d646e0a..8b00bcb8b7 100644 --- a/spec/std/isa/csr/mstatus.yaml +++ b/spec/std/isa/csr/mstatus.yaml @@ -282,14 +282,14 @@ fields: * Any additional traps in VS-mode (controlled via `hstatus.VTVM` instead). type(): | - if (CSR[misa].S == 1'b0) { + if ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) { return CsrFieldType::RO; } else { return CsrFieldType::RW; } definedBy: S reset_value(): | - if (CSR[misa].S == 1'b0) { + if ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) { return 0; } else if (MSTATUS_TVM_IMPLEMENTED) { return UNDEFINED_LEGAL; @@ -297,7 +297,7 @@ fields: return 0; } sw_write(csr_value): | - if (CSR[misa].S == 1'b0) { + if ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) { return 0; } else if (MSTATUS_TVM_IMPLEMENTED) { return csr_value.TVM; @@ -347,7 +347,7 @@ fields: `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; + return ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::U)) || (CSR[misa].U == 1'b1)) ? CsrFieldType::RWH : CsrFieldType::RO; reset_value: 0 XS: location: 16-15 @@ -370,9 +370,10 @@ fields: 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){ + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::F)) || (CSR[misa].F == 1'b1)) { return CsrFieldType::RWH; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { + } else if (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::F)) || (CSR[misa].F == 1'b0))) { # must be read-only-0 return CsrFieldType::RO; } else { @@ -382,9 +383,10 @@ fields: definedBy: anyOf: [F, S] reset_value(): | - if (CSR[misa].F == 1'b1){ + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::F)) || (CSR[misa].F == 1'b1)) { return UNDEFINED_LEGAL; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].F == 1'b0)) { + } else if (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::F)) || (CSR[misa].F == 1'b0))) { # must be read-only-0 return 0; } else { @@ -392,9 +394,10 @@ fields: return MSTATUS_FS_WRITABLE ? UNDEFINED_LEGAL : 0; } sw_write(csr_value): | - if (CSR[misa].F == 1'b1){ + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::F)) || (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)) { + } else if (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::F)) || (CSR[misa].F == 1'b0))) { # must be read-only-0 return 0; } else { @@ -455,9 +458,10 @@ fields: definedBy: anyOf: [V, S] type(): | - if (CSR[misa].V == 1'b1){ + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::V)) || (CSR[misa].V == 1'b1)) { return CsrFieldType::RWH; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + } else if (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::V)) || (CSR[misa].V == 1'b0))) { # must be read-only-0 return CsrFieldType::RO; } else { @@ -465,9 +469,10 @@ fields: return MSTATUS_VS_WRITABLE ? CsrFieldType::RW : CsrFieldType::RO; } reset_value(): | - if (CSR[misa].V == 1'b1){ + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::V)) || (CSR[misa].V == 1'b1)) { return UNDEFINED_LEGAL; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + } else if (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::V)) || (CSR[misa].V == 1'b0))) { # must be read-only-0 return 0; } else { @@ -475,9 +480,11 @@ fields: return MSTATUS_VS_WRITABLE ? 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.VS) ? csr_value.VS : UNDEFINED_LEGAL_DETERMINISTIC; - } else if ((CSR[misa].S == 1'b0) && (CSR[misa].V == 1'b0)) { + + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::V)) || (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 (((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) && + ((!MISA_CSR_IMPLEMENTED && !implemented?(ExtensionName::V)) || (CSR[misa].V == 1'b0))) { # must be read-only-0 return 0; } else { @@ -570,10 +577,10 @@ fields: 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; + return ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) ? CsrFieldType::RWH : CsrFieldType::RO; definedBy: S reset_value(): | - return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; + return ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) ? UNDEFINED_LEGAL : 0; MIE: location: 3 description: | @@ -607,7 +614,7 @@ fields: * 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; + return ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) ? CsrFieldType::RWH : CsrFieldType::RO; definedBy: S reset_value(): | - return (CSR[misa].S == 1'b1) ? UNDEFINED_LEGAL : 0; + return ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) ? UNDEFINED_LEGAL : 0; diff --git a/spec/std/isa/ext/A.yaml b/spec/std/isa/ext/A.yaml index 6b3b30e35e..7439d21885 100644 --- a/spec/std/isa/ext/A.yaml +++ b/spec/std/isa/ext/A.yaml @@ -128,3 +128,4 @@ params: the extension can be disabled in the `misa.A` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/B.yaml b/spec/std/isa/ext/B.yaml index 1bb642ba0f..f6036e24fe 100644 --- a/spec/std/isa/ext/B.yaml +++ b/spec/std/isa/ext/B.yaml @@ -43,3 +43,4 @@ params: Indicates whether or not the `B` extension can be disabled with the `misa.B` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/C.yaml b/spec/std/isa/ext/C.yaml index be6ccd2466..c820232be6 100644 --- a/spec/std/isa/ext/C.yaml +++ b/spec/std/isa/ext/C.yaml @@ -319,3 +319,4 @@ params: Indicates whether or not the `C` extension can be disabled with the `misa.C` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/D.yaml b/spec/std/isa/ext/D.yaml index 506bbaf7d1..6681e0aa48 100644 --- a/spec/std/isa/ext/D.yaml +++ b/spec/std/isa/ext/D.yaml @@ -112,3 +112,4 @@ params: Indicates whether or not the `D` extension can be disabled with the `misa.D` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/F.yaml b/spec/std/isa/ext/F.yaml index 6ef0052448..e304847348 100644 --- a/spec/std/isa/ext/F.yaml +++ b/spec/std/isa/ext/F.yaml @@ -245,6 +245,7 @@ params: Indicates whether or not the `F` extension can be disabled with the `misa.F` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true HW_MSTATUS_FS_DIRTY_UPDATE: description: | Indicates whether or not hardware will write to `mstatus.FS` diff --git a/spec/std/isa/ext/H.yaml b/spec/std/isa/ext/H.yaml index e66b54c4bc..472968371c 100644 --- a/spec/std/isa/ext/H.yaml +++ b/spec/std/isa/ext/H.yaml @@ -157,6 +157,7 @@ params: Indicates whether or not the `H` extension can be disabled with the `misa.H` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true 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 diff --git a/spec/std/isa/ext/M.yaml b/spec/std/isa/ext/M.yaml index 2791f4a46a..735a88e9af 100644 --- a/spec/std/isa/ext/M.yaml +++ b/spec/std/isa/ext/M.yaml @@ -30,3 +30,4 @@ params: Indicates whether or not the `M` extension can be disabled with the `misa.M` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/Q.yaml b/spec/std/isa/ext/Q.yaml index ccd6d607df..828226657f 100644 --- a/spec/std/isa/ext/Q.yaml +++ b/spec/std/isa/ext/Q.yaml @@ -27,3 +27,4 @@ params: Indicates whether or not the `Q` extension can be disabled with the `misa.Q` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true diff --git a/spec/std/isa/ext/S.yaml b/spec/std/isa/ext/S.yaml index 8a01206e54..05c5a1b658 100644 --- a/spec/std/isa/ext/S.yaml +++ b/spec/std/isa/ext/S.yaml @@ -50,6 +50,7 @@ params: Indicates whether or not the `S` extension can be disabled with the `misa.S` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true 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 diff --git a/spec/std/isa/ext/U.yaml b/spec/std/isa/ext/U.yaml index ba4bcc45b2..3b5aa7b948 100644 --- a/spec/std/isa/ext/U.yaml +++ b/spec/std/isa/ext/U.yaml @@ -21,6 +21,7 @@ params: Indicates whether or not the `U` extension can be disabled with the `misa.U` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true U_MODE_ENDIANNESS: description: | Endianness of data in U-mode. Can be one of: diff --git a/spec/std/isa/ext/V.yaml b/spec/std/isa/ext/V.yaml index ae1422fa05..90ececee6c 100644 --- a/spec/std/isa/ext/V.yaml +++ b/spec/std/isa/ext/V.yaml @@ -20,6 +20,7 @@ params: Indicates whether or not the `V` extension can be disabled with the `misa.V` bit. schema: type: boolean + extra_validation: assert MISA_CSR_IMPLEMENTED == true HW_MSTATUS_VS_DIRTY_UPDATE: description: | Indicates whether or not hardware will write to `mstatus.VS` diff --git a/spec/std/isa/ext/Zhinx.yaml b/spec/std/isa/ext/Zhinx.yaml index ab770bbe3f..ece18084c5 100644 --- a/spec/std/isa/ext/Zhinx.yaml +++ b/spec/std/isa/ext/Zhinx.yaml @@ -1,23 +1,23 @@ -# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. -# SPDX-License-Identifier: BSD-3-Clause-Clear - -# yaml-language-server: $schema=../../../schemas/ext_schema.json - -$schema: "ext_schema.json#" -kind: extension -name: Zhinx -long_name: Half-precision floating-point instructions using integer registers -description: | - The Zhinx extension provides analogous half-precision floating-point instructions. The Zhinx extension - depends upon the Zfinx extension. - The Zhinx extension adds all of the instructions that the Zfh extension adds, except for the transfer - instructions FLH, FSH, FMV.H.X, and FMV.X.H. - The Zhinx variants of these Zfh-extension instructions have the same semantics, except that whenever - such an instruction would have accessed an f register, it instead accesses the x register with the same - number. - -type: unprivileged -versions: - - version: "1.0.0" - state: ratified - ratification_date: 2021-11 +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Zhinx +long_name: Half-precision floating-point instructions using integer registers +description: | + The Zhinx extension provides analogous half-precision floating-point instructions. The Zhinx extension + depends upon the Zfinx extension. + The Zhinx extension adds all of the instructions that the Zfh extension adds, except for the transfer + instructions FLH, FSH, FMV.H.X, and FMV.X.H. + The Zhinx variants of these Zfh-extension instructions have the same semantics, except that whenever + such an instruction would have accessed an f register, it instead accesses the x register with the same + number. + +type: unprivileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2021-11 diff --git a/spec/std/isa/isa/fetch.idl b/spec/std/isa/isa/fetch.idl index 3291a5b709..5f3b860e9a 100644 --- a/spec/std/isa/isa/fetch.idl +++ b/spec/std/isa/isa/fetch.idl @@ -13,7 +13,7 @@ function fetch_memory_aligned_16 { body { TranslationResult result; - if (CSR[misa].S == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1)) { result = translate(virtual_address, MemoryOperation::Fetch, mode(), virtual_address); } else { result.paddr = virtual_address; @@ -36,7 +36,7 @@ function fetch_memory_aligned_32 { body { TranslationResult result; - if (CSR[misa].S == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1)) { result = translate(virtual_address, MemoryOperation::Fetch, mode(), virtual_address); } else { result.paddr = virtual_address; diff --git a/spec/std/isa/isa/globals.isa b/spec/std/isa/isa/globals.isa index 47a4e271a7..fa77d5218c 100644 --- a/spec/std/isa/isa/globals.isa +++ b/spec/std/isa/isa/globals.isa @@ -698,7 +698,7 @@ function raise_precise { $pc = {CSR[mtvec].BASE, 2'b00}; CSR[mcause].INT = 1'b0; CSR[mcause].CODE = $bits(exception_code); - if (CSR[misa].H == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1)) { # write zero into mtval2 and minst # (when these are non-zero values, raise_guest_page_fault should be callecd) CSR[mtval2].VALUE = 0; @@ -718,7 +718,7 @@ function raise_precise { } } CSR[mstatus].MPP = $bits(from_mode); - } else if (CSR[misa].S == 1 && (handling_mode == PrivilegeMode::S)) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1 )&& (handling_mode == PrivilegeMode::S)) { CSR[sepc].PC = $pc; if (!stval_readonly?()) { CSR[stval].VALUE = stval_for(exception_code, tval); @@ -727,7 +727,7 @@ function raise_precise { CSR[scause].INT = 1'b0; CSR[scause].CODE = $bits(exception_code); CSR[mstatus].SPP = $bits(from_mode)[0]; - if (CSR[misa].H == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1)) { # write zero into htval and hinst # (when these are non-zero values, raise_guest_page_fault should be callecd) CSR[htval].VALUE = 0; @@ -756,7 +756,7 @@ function raise_precise { CSR[hstatus].GVA = 0; } } - } else if (CSR[misa].H == 1 && (handling_mode == PrivilegeMode::VS)) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& (handling_mode == PrivilegeMode::VS)) { CSR[vsepc].PC = $pc; if (!vstval_readonly?()) { CSR[vstval].VALUE = vstval_for(exception_code, tval); @@ -779,7 +779,7 @@ function ialign { Returns IALIGN, the smallest instruction encoding size, in bits. } body { - if (implemented?(ExtensionName::C) && (CSR[misa].C == 0x1)) { + if (implemented?(ExtensionName::C) && ((!MISA_CSR_IMPLEMENTED) || (CSR[misa].C == 0x1))) { return 16; } else { return 32; @@ -876,39 +876,34 @@ function xlen { body { if (MXLEN == 32) { return 32; - } else { - if (mode() == PrivilegeMode::M) { - if (CSR[misa].MXL == $bits(XRegWidth::XLEN32)) { - return 32; - } else if (CSR[misa].MXL == $bits(XRegWidth::XLEN64)) { - return 64; - } - } else if (implemented?(ExtensionName::S) && mode() == PrivilegeMode::S) { - if (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32)) { - return 32; - } else if (CSR[mstatus].SXL == $bits(XRegWidth::XLEN64)) { - return 64; - } - } else if (implemented?(ExtensionName::U) && mode() == PrivilegeMode::U) { - if (CSR[mstatus].UXL == $bits(XRegWidth::XLEN32)) { - return 32; - } else if (CSR[mstatus].UXL == $bits(XRegWidth::XLEN64)) { - return 64; - } - } else if (implemented?(ExtensionName::H) && mode() == PrivilegeMode::VS) { - if (CSR[hstatus].VSXL == $bits(XRegWidth::XLEN32)) { - return 32; - } else if (CSR[hstatus].VSXL == $bits(XRegWidth::XLEN64)) { - return 64; - } - } else if (implemented?(ExtensionName::H) && mode() == PrivilegeMode::VU) { - if (CSR[vsstatus].UXL == $bits(XRegWidth::XLEN32)) { - return 32; - } else if (CSR[vsstatus].UXL == $bits(XRegWidth::XLEN64)) { - return 64; - } + } else if (mode() == PrivilegeMode::M) { + return MXLEN; + } else if (implemented?(ExtensionName::S) && mode() == PrivilegeMode::S) { + if (CSR[mstatus].SXL == $bits(XRegWidth::XLEN32)) { + return 32; + } else if (CSR[mstatus].SXL == $bits(XRegWidth::XLEN64)) { + return 64; + } + } else if (implemented?(ExtensionName::U) && mode() == PrivilegeMode::U) { + if (CSR[mstatus].UXL == $bits(XRegWidth::XLEN32)) { + return 32; + } else if (CSR[mstatus].UXL == $bits(XRegWidth::XLEN64)) { + return 64; + } + } else if (implemented?(ExtensionName::H) && mode() == PrivilegeMode::VS) { + if (CSR[hstatus].VSXL == $bits(XRegWidth::XLEN32)) { + return 32; + } else if (CSR[hstatus].VSXL == $bits(XRegWidth::XLEN64)) { + return 64; + } + } else if (implemented?(ExtensionName::H) && mode() == PrivilegeMode::VU) { + if (CSR[vsstatus].UXL == $bits(XRegWidth::XLEN32)) { + return 32; + } else if (CSR[vsstatus].UXL == $bits(XRegWidth::XLEN64)) { + return 64; } } + } } @@ -1165,15 +1160,15 @@ function effective_ldst_mode { # when the mode is M, loads and stores can be executed as if they were done from any other mode # with the use of mstatus.MPRV if (mode() == PrivilegeMode::M) { - if (CSR[misa].U == 1 && CSR[mstatus].MPRV == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::U)) || (CSR[misa].U == 1 )&& CSR[mstatus].MPRV == 1) { if (CSR[mstatus].MPP == 0b00) { - if (CSR[misa].H == 1 && mpv() == 0b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& mpv() == 0b1) { return PrivilegeMode::VU; } else { return PrivilegeMode::U; } - } else if (CSR[misa].S == 1 && CSR[mstatus].MPP == 0b01) { - if (CSR[misa].H == 1 && mpv() == 0b1) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1 )&& CSR[mstatus].MPP == 0b01) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& mpv() == 0b1) { return PrivilegeMode::VS; } else { return PrivilegeMode::S; @@ -1273,7 +1268,7 @@ function base32? { } else { XRegWidth xlen32 = XRegWidth::XLEN32; if (mode() == PrivilegeMode::M) { - return CSR[misa].MXL == $bits(xlen32); + return (!MISA_CSR_IMPLEMENTED) || (CSR[misa].MXL == $bits(xlen32)); } else if (implemented?(ExtensionName::S) && mode() == PrivilegeMode::S) { return CSR[mstatus].SXL == $bits(xlen32); } else if (implemented?(ExtensionName::U) && mode() == PrivilegeMode::U) { @@ -1315,7 +1310,7 @@ function current_translation_mode { return SatpMode::Bare; } - if (CSR[misa].H == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) { if (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU) { Bits<4> mode_val = CSR[vsatp].MODE; if (mode_val == $bits(SatpMode::Sv32)) { @@ -1392,7 +1387,7 @@ function current_translation_mode { return SatpMode::Reserved; } } - } else if (CSR[misa].S == 1'b1) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) { # if we reach here, then the effective mode is S or U assert(effective_mode == PrivilegeMode::S || effective_mode == PrivilegeMode::U, "unexpected priv mode"); @@ -2028,13 +2023,13 @@ function stage1_page_walk { # shadow stacks enabled? Boolean sse = false; - # if (CSR[misa].H == 1 && effective_mode == PrivilegeMode::VS) { + # if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& effective_mode == PrivilegeMode::VS) { # sse = CSR[henvcfg].SSE == 1; - # } else if (CSR[misa].H == 1 && effective_mode == PrivilegeMode::VU) { + # } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& effective_mode == PrivilegeMode::VU) { # sse = CSR[senvcfg].SSE == 1; - # } else if (CSR[misa].U == 1 && effective_mode == PrivilegeMode::U) { + # } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::U)) || (CSR[misa].U == 1 )&& effective_mode == PrivilegeMode::U) { # sse = CSR[senvcfg].SSE == 1; - # } else if (CSR[misa].S == 1 && effective_mode == PrivilegeMode::S) { + # } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1 )&& effective_mode == PrivilegeMode::S) { # sse = CSR[menvcfg].SSE == 1; # } else { # # M-mode @@ -2043,7 +2038,7 @@ function stage1_page_walk { # access/dirty bit hardware update enable? Boolean adue; - if (CSR[misa].H == 1 && (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { adue = CSR[henvcfg].ADUE == 1; } else { adue = CSR[menvcfg].ADUE == 1; @@ -2055,7 +2050,7 @@ function stage1_page_walk { # not Sv32 (PBMT is not defined for Sv32) pbmte = false; } else { - if (CSR[misa].H == 1 && (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { + if ((!MISA_CSR_IMPLEMENTED) || (CSR[misa].H == 1 )&& (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { pbmte = CSR[henvcfg].PBMTE == 1; } else { pbmte = CSR[menvcfg].PBMTE == 1; @@ -2064,7 +2059,7 @@ function stage1_page_walk { # make execute readable? Boolean mxr; - if (CSR[misa].H == 1 && (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& (effective_mode == PrivilegeMode::VS || effective_mode == PrivilegeMode::VU)) { # HS-level sstatus.MXR makes execute-only pages readable for both stages of address translation # (VS-stage and G-stage), whereas vsstatus.MXR affects only the first translation stage (VS-stage) mxr = (CSR[mstatus].MXR == 1) || (CSR[vsstatus].MXR == 1); @@ -2074,7 +2069,7 @@ function stage1_page_walk { # Supervisor access user page? Boolean sum; - if (CSR[misa].H == 1 && (effective_mode == PrivilegeMode::VS)) { + if ((!MISA_CSR_IMPLEMENTED) || (CSR[misa].H == 1 )&& (effective_mode == PrivilegeMode::VS)) { sum = CSR[vsstatus].SUM == 1; } else { sum = CSR[mstatus].SUM == 1; @@ -2168,7 +2163,7 @@ function stage1_page_walk { if (effective_mode == PrivilegeMode::U && pte_flags.U == 0) { # U-mode can never access supervisor page raise (page_fault_code, effective_mode, vaddr); - } else if (CSR[misa].H == 1 && effective_mode == PrivilegeMode::VU && pte_flags.U == 0) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1 )&& effective_mode == PrivilegeMode::VU && pte_flags.U == 0) { # VU-mode can never access supervisor page raise (page_fault_code, effective_mode, vaddr); } else if (effective_mode == PrivilegeMode::S && pte_flags.U == 1 && !sum) { @@ -2404,7 +2399,7 @@ function canonical_vaddr? { the canonical address. } body { - if (CSR[misa].S == 1'b0) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b0)) { # there is no translation, any address is canonical return true; } @@ -2507,7 +2502,7 @@ function read_memory_aligned { body { TranslationResult result; - if (CSR[misa].S == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) { result = translate(virtual_address, MemoryOperation::Read, effective_ldst_mode(), encoding); } else { result.paddr = virtual_address; @@ -2546,7 +2541,7 @@ function read_memory { # before an access/page fault exception (that would be an invalid config) assert(MISALIGNED_LDST_EXCEPTION_PRIORITY == "low", "Invalid config: can't mix low-priority misaligned exceptions with large atomicity granule"); - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Read, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2562,7 +2557,7 @@ function read_memory { # a page/access fault exception, depending on the configuration if (MISALIGNED_LDST_EXCEPTION_PRIORITY == "low") { # do translation to trigger any access/page faults before raising misaligned - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Read, effective_ldst_mode(), encoding).paddr : virtual_address; access_check(physical_address, LEN, virtual_address, MemoryOperation::Read, ExceptionCode::LoadAccessFault, effective_ldst_mode()); @@ -2629,7 +2624,7 @@ function read_memory_xlen_aligned { body { TranslationResult result; - if (CSR[misa].S == 1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) { result = translate(virtual_address, MemoryOperation::Read, effective_ldst_mode(), encoding); } else { result.paddr = virtual_address; @@ -2721,7 +2716,7 @@ function load_reserved { } body { Bits physical_address = - (CSR[misa].S == 1) + ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Read, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2738,7 +2733,8 @@ function load_reserved { register_reservation_set(physical_address, N); - if (CSR[misa].S ==1 && LRSC_FAIL_ON_VA_SYNONYM) { + if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) && + LRSC_FAIL_ON_VA_SYNONYM) { # also need to remember the virtual address reservation_virtual_address = virtual_address; } @@ -2768,7 +2764,7 @@ function store_conditional { } body { Bits physical_address = - (CSR[misa].S == 1) + ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Write, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2846,7 +2842,7 @@ function amo { } Bits physical_address = - (CSR[misa].S == 1) + ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::ReadModifyWrite, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2896,7 +2892,7 @@ function write_memory_aligned { body { XReg physical_address; - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Write, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2933,7 +2929,7 @@ function write_memory { # before an access/page fault exception (that would be an invalid config) assert(MISALIGNED_LDST_EXCEPTION_PRIORITY == "low", "Invalid config: can't mix low-priority misaligned exceptions with large atomicity granule"); - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1) ? translate(virtual_address, MemoryOperation::Write, effective_ldst_mode(), encoding).paddr : virtual_address; @@ -2950,7 +2946,7 @@ function write_memory { # a page/access fault exception, depending on the configuration if (MISALIGNED_LDST_EXCEPTION_PRIORITY == "low") { # do translation to trigger any access/page faults before raising misaligned - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Write, effective_ldst_mode(), encoding).paddr : virtual_address; access_check(physical_address, LEN, virtual_address, MemoryOperation::Write, ExceptionCode::StoreAmoAccessFault, effective_ldst_mode()); @@ -2980,7 +2976,7 @@ function write_memory_xlen_aligned { body { XReg physical_address; - physical_address = (CSR[misa].S == 1) + physical_address = ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) ? translate(virtual_address, MemoryOperation::Write, effective_ldst_mode(), encoding).paddr : virtual_address; diff --git a/spec/std/isa/isa/interrupts.idl b/spec/std/isa/isa/interrupts.idl index 5bd8762613..101a3d07a1 100644 --- a/spec/std/isa/isa/interrupts.idl +++ b/spec/std/isa/isa/interrupts.idl @@ -24,10 +24,10 @@ external function set_external_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MEIP = 1'b1; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { # set the "hidden" bit, not the software-writable bit pending_smode_external_interrupt = true; - } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { CSR[mip].VSEIP = 1'b1; } else { assert(false, "Invalid target_mode"); @@ -45,10 +45,10 @@ external function clear_external_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MEIP = 1'b0; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (target_mode == PrivilegeMode::S)) { # clear the "hidden" bit, not the software-writable bit pending_smode_external_interrupt = false; - } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { CSR[mip].VSEIP = 1'b0; } else { assert(false, "Invalid target_mode"); @@ -66,10 +66,10 @@ external function set_software_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MSIP = 1'b1; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (target_mode == PrivilegeMode::S)) { # set the "hidden" bit, not the software-writable bit CSR[mip].SSIP = 1'b1; - # } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + # } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { # CSR[hvip].VSSIP = 1'b1; } else { assert(false, "Invalid target_mode"); @@ -87,10 +87,10 @@ external function clear_software_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MSIP = 1'b0; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (target_mode == PrivilegeMode::S)) { # set the "hidden" bit, not the software-writable bit CSR[mip].SSIP = 1'b0; - # } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + # } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { # CSR[hvip].VSSIP = 1'b0; } else { assert(false, "Invalid target_mode"); @@ -108,10 +108,10 @@ external function set_timer_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MTIP = 1'b1; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (target_mode == PrivilegeMode::S)) { # set the "hidden" bit, not the software-writable bit CSR[mip].STIP = 1'b1; - } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { pending_vsmode_timer_interrupt = true; } else { assert(false, "Invalid target_mode"); @@ -129,10 +129,10 @@ external function clear_timer_interrupt { body { if (target_mode == PrivilegeMode::M) { CSR[mip].MTIP = 1'b0; - } else if ((CSR[misa].S == 1'b1) && (target_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (target_mode == PrivilegeMode::S)) { # set the "hidden" bit, not the software-writable bit CSR[mip].STIP = 1'b0; - } else if ((CSR[misa].H == 1'b1) && (target_mode == PrivilegeMode::VS)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (target_mode == PrivilegeMode::VS)) { pending_vsmode_timer_interrupt = false; } else { assert(false, "Invalid target_mode"); @@ -183,7 +183,7 @@ function refresh_pending_interrupts { return; } - if (CSR[misa].S == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) { Bits smode_enabled_ints = ((mode() == PrivilegeMode::M) || (CSR[mstatus].SIE == 1'b0)) ? 0 @@ -195,7 +195,7 @@ function refresh_pending_interrupts { } } - # if (CSR[misa].H == 1'b1) { + # if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) { # Boolean sgei_pending_and_enabled = ($bits(CSR[hgeip]) & $bits(CSR[heie])) != 0; # if (sgei_pending_and_enabled) { @@ -235,7 +235,7 @@ function highest_priority_interrupt { } else if (int_mask[$bits(InterruptCode::MachineTimer)] == 1'b1) { return InterruptCode::MachineTimer; } - if (CSR[misa].S == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) { if (int_mask[$bits(InterruptCode::SupervisorExternal)] == 1'b1) { return InterruptCode::SupervisorExternal; } else if (int_mask[$bits(InterruptCode::SupervisorSoftware)] == 1'b1) { @@ -244,7 +244,7 @@ function highest_priority_interrupt { return InterruptCode::SupervisorTimer; } } - # if (CSR[misa].H == 1'b1) { + # if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) { # if (int_mask[$bits(InterruptCode::SupervisorGuestExternal)] == 1'b1) { # return InterruptCode::SupervisorGuestExternal; # } else if (int_mask[$bits(InterruptCode::VirtualSupervisorExternal)] == 1'b1) { @@ -288,10 +288,10 @@ function choose_interrupt { chosen = highest_priority_interrupt(mmode_pending_and_enabled); # check S-mode interrupts - } else if (CSR[misa].S == 1'b1) { + } else if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) { Bits smode_pending_and_enabled = (pending_and_enabled_interrupts & $bits(CSR[mideleg])) - # & ((CSR[misa].H == 1'b1) ? ~$bits(CSR[hideleg]) : ~MXLEN'0) + # & (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) ? ~$bits(CSR[hideleg]) : ~MXLEN'0) ; if (smode_pending_and_enabled != 0) { @@ -313,7 +313,7 @@ function choose_interrupt { to_mode = PrivilegeMode::M; } else { # delegated from M - if (CSR[misa].S == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) { to_mode = PrivilegeMode::S; } else { to_mode = PrivilegeMode::U; @@ -338,7 +338,7 @@ function take_interrupt { if (to_mode == PrivilegeMode::M) { CSR[mepc].PC = $pc; CSR[mstatus].MPP = $bits(mode())[1:0]; - if (CSR[misa].H == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) { if(MXLEN == 64) { CSR[mstatus].MPV = $bits(mode())[2]; } else { @@ -357,10 +357,10 @@ function take_interrupt { # vectored $pc = {CSR[mtvec].BASE, 2'b00} + ($bits(code)*4); } - } else if ((CSR[misa].S == 1'b1) && (to_mode == PrivilegeMode::S)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::S)) || (CSR[misa].S == 1'b1)) && (to_mode == PrivilegeMode::S)) { CSR[sepc].PC = $pc; CSR[mstatus].SPP = $bits(mode())[0]; - if (CSR[misa].H == 1'b1) { + if ((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) { CSR[hstatus].SPV = $bits(mode())[2]; } CSR[scause].CODE = $bits(code); @@ -373,7 +373,7 @@ function take_interrupt { # vectored $pc = {CSR[stvec].BASE, 2'b00} + ($bits(code)*4); } - } else if ((CSR[misa].H == 1'b1) && (to_mode == PrivilegeMode::VS)) { + } else if (((!MISA_CSR_IMPLEMENTED && implemented?(ExtensionName::H)) || (CSR[misa].H == 1'b1)) && (to_mode == PrivilegeMode::VS)) { CSR[vsepc].PC = $pc; CSR[vsstatus].SPP = $bits(mode())[0]; CSR[vscause].CODE = $bits(code); diff --git a/tools/ruby-gems/udb/lib/udb/obj/csr.rb b/tools/ruby-gems/udb/lib/udb/obj/csr.rb index 5cbc672c28..5e3ef3aea7 100644 --- a/tools/ruby-gems/udb/lib/udb/obj/csr.rb +++ b/tools/ruby-gems/udb/lib/udb/obj/csr.rb @@ -341,7 +341,7 @@ def length_cond32 def length_cond64 case @data["length"] when "MXLEN" - "CSR[misa].MXL == 1" + "(!MISA_CSR_IMPLEMENTED) || (CSR[misa].MXL == 1)" when "SXLEN" "CSR[mstatus].SXL == 1" when "VSXLEN" diff --git a/tools/ruby-gems/udb/lib/udb/obj/csr_field.rb b/tools/ruby-gems/udb/lib/udb/obj/csr_field.rb index 2e8d46a70f..bde302c4d4 100644 --- a/tools/ruby-gems/udb/lib/udb/obj/csr_field.rb +++ b/tools/ruby-gems/udb/lib/udb/obj/csr_field.rb @@ -732,7 +732,7 @@ def location_cond32 def location_cond64 case csr.priv_mode when "M" - "CSR[misa].MXL == 1" + "(!MISA_CSR_IMPLEMENTED) || (CSR[misa].MXL == 1)" when "S" "CSR[mstatus].SXL == 1" when "VS" @@ -756,7 +756,7 @@ def location_pretty(effective_xlen = nil) condition = case csr.priv_mode when "M" - "CSR[misa].MXL == %%" + "(!MISA_CSR_IMPLEMENTED) || (CSR[misa].MXL == %%)" when "S" "CSR[mstatus].SXL == %%" when "VS"