From 602c7e538083e247b6e1cb54300ae7f54fe65d0f Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Sun, 19 Oct 2025 22:38:12 -0400 Subject: [PATCH 1/8] feat: rv64 test configuration --- .vscode/launch.json | 4 +- cfgs/rv64-riscv-tests.yaml | 128 +++++++++++++++++++++++++++++++++++ spec/std/isa/isa/globals.isa | 31 ++++----- 3 files changed, 145 insertions(+), 18 deletions(-) create mode 100644 cfgs/rv64-riscv-tests.yaml diff --git a/.vscode/launch.json b/.vscode/launch.json index 7163deb3f..402aa3d66 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,8 @@ "name": "ISS debug Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/gen/cpp_hart_gen/rv32_Debug/build/iss", - "args": ["-m", "rv32", "-c", "${workspaceFolder}/cfgs/rv32-riscv-tests.yaml", "${workspaceFolder}/ext/riscv-tests/isa/rv32ui-p-addi"], + "program": "${workspaceFolder}/gen/cpp_hart_gen/rv64_Debug/build/iss", + "args": ["-m", "rv64", "-c", "${workspaceFolder}/cfgs/rv64-riscv-tests.yaml", "${workspaceFolder}/ext/riscv-tests/isa/rv64ui-p-addi"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/cfgs/rv64-riscv-tests.yaml b/cfgs/rv64-riscv-tests.yaml new file mode 100644 index 000000000..277d658fb --- /dev/null +++ b/cfgs/rv64-riscv-tests.yaml @@ -0,0 +1,128 @@ +# yaml-language-server: $schema=../schemas/config_schema.json +--- +$schema: https://riscv.org/udb/schemas/config_schema-0.1.0.json +kind: architecture configuration +type: fully configured +name: rv64-riscv-tests +description: A compliant full config for rv64 riscv-tests +implemented_extensions: + - [Sm, "1.11.0"] + - [I, "2.1"] + - [C, "2.0"] + - [M, "2.0"] + - [Zicsr, "2.0"] + - [Zicntr, "2.0"] + - [Smrnmi, "1.0"] + - [S, "1.11.0"] + - [Smpmp, "1.11.0"] + - [U, "1.0.0"] + - [Zifencei, "2.0.0"] + - [Sv32, "1.11.0"] + +params: + MXLEN: 64 + ARCH_ID: 0 + IMP_ID: 0 + VENDOR_ID_BANK: 1 + VENDOR_ID_OFFSET: 1 + MISALIGNED_LDST: true + MISALIGNED_LDST_EXCEPTION_PRIORITY: low + MISALIGNED_MAX_ATOMICITY_GRANULE_SIZE: 4 + MISALIGNED_SPLIT_STRATEGY: by_byte + PRECISE_SYNCHRONOUS_EXCEPTIONS: true + TRAP_ON_ECALL_FROM_M: true + TRAP_ON_EBREAK: true + M_MODE_ENDIANNESS: little + TRAP_ON_ILLEGAL_WLRL: true + TRAP_ON_UNIMPLEMENTED_INSTRUCTION: true + TRAP_ON_RESERVED_INSTRUCTION: true + TRAP_ON_UNIMPLEMENTED_CSR: true + REPORT_VA_IN_MTVAL_ON_BREAKPOINT: true + REPORT_VA_IN_MTVAL_ON_LOAD_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_MISALIGNED: true + REPORT_VA_IN_MTVAL_ON_LOAD_ACCESS_FAULT: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_ACCESS_FAULT: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_ACCESS_FAULT: true + REPORT_ENCODING_IN_MTVAL_ON_ILLEGAL_INSTRUCTION: true + MTVAL_WIDTH: 32 + PMA_GRANULARITY: 12 + PHYS_ADDR_WIDTH: 57 + MISA_CSR_IMPLEMENTED: true + MTVEC_MODES: [0, 1] + MTVEC_BASE_ALIGNMENT_DIRECT: 4 + MTVEC_BASE_ALIGNMENT_VECTORED: 4 + MUTABLE_MISA_C: false + MUTABLE_MISA_M: false + TIME_CSR_IMPLEMENTED: false + MUTABLE_MISA_S: false + ASID_WIDTH: 5 + S_MODE_ENDIANNESS: little + SXLEN: 64 + REPORT_VA_IN_MTVAL_ON_LOAD_PAGE_FAULT: true + REPORT_VA_IN_MTVAL_ON_STORE_AMO_PAGE_FAULT: true + REPORT_VA_IN_MTVAL_ON_INSTRUCTION_PAGE_FAULT: true + REPORT_VA_IN_STVAL_ON_BREAKPOINT: true + REPORT_VA_IN_STVAL_ON_LOAD_MISALIGNED: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_MISALIGNED: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_MISALIGNED: true + REPORT_VA_IN_STVAL_ON_LOAD_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_ACCESS_FAULT: true + REPORT_VA_IN_STVAL_ON_LOAD_PAGE_FAULT: true + REPORT_VA_IN_STVAL_ON_STORE_AMO_PAGE_FAULT: true + REPORT_VA_IN_STVAL_ON_INSTRUCTION_PAGE_FAULT: true + REPORT_ENCODING_IN_STVAL_ON_ILLEGAL_INSTRUCTION: true + STVAL_WIDTH: 32 + SCOUNTENABLE_EN: + [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + ] + STVEC_MODE_DIRECT: true + STVEC_MODE_VECTORED: true + SATP_MODE_BARE: true + TRAP_ON_ECALL_FROM_S: true + TRAP_ON_SFENCE_VMA_WHEN_SATP_MODE_IS_READ_ONLY: false + MSTATUS_FS_WRITABLE: false + MSTATUS_VS_WRITABLE: false + MSTATUS_VS_LEGAL_VALUES: [0] + MSTATUS_FS_LEGAL_VALUES: [0] + MSTATUS_TVM_IMPLEMENTED: false + NUM_PMP_ENTRIES: 16 + PMP_GRANULARITY: 12 + MUTABLE_MISA_U: false + U_MODE_ENDIANNESS: little + UXLEN: 64 + MSTATEEN_ENVCFG_TYPE: rw + HSTATEEN_ENVCFG_TYPE: rw diff --git a/spec/std/isa/isa/globals.isa b/spec/std/isa/isa/globals.isa index 9afd483a5..b2e611857 100644 --- a/spec/std/isa/isa/globals.isa +++ b/spec/std/isa/isa/globals.isa @@ -120,8 +120,8 @@ generated enum ExceptionCode; # XLEN encoding, as defined in CSR[mstatus].mxl, etc. enum XRegWidth { - XLEN32 0 - XLEN64 1 + XLEN32 1 + XLEN64 2 } # enum ExceptionCode { @@ -1003,19 +1003,19 @@ function pmp_match_64 { # set up the default range limits, which will result in NoMatch when # compared to the access - Bits range_hi = 0; - Bits range_lo = 0; + Bits range_base = 0; + Bits range_limit = 0; if (cfg.A == $bits(PmpCfg_A::TOR)) { if (i == 0) { # when entry zero is TOR, zero is the lower address bound - range_lo = 0; + range_base = 0; } else { # otherwise, it's the address in the next lowest pmpaddr register Csr tor_pmpaddr_csr = direct_csr_lookup(pmpaddr_idx - 1); - range_lo = (csr_sw_read(tor_pmpaddr_csr) << 2)[PHYS_ADDR_WIDTH-1:0]; + range_base = (csr_sw_read(tor_pmpaddr_csr))[PHYS_ADDR_WIDTH-1:0]; } - range_hi = (pmpaddr_csr_value << 2)[PHYS_ADDR_WIDTH-1:0]; + range_limit = (pmpaddr_csr_value)[PHYS_ADDR_WIDTH-1:0] - 1; } else if (cfg.A == $bits(PmpCfg_A::NAPOT)) { # Example pmpaddr: 0b00010101111 @@ -1024,21 +1024,20 @@ function pmp_match_64 { # mask: 0b00000011111 # ~mask: 0b11111100000 # len = mask + 1: 0b00000100000 - Bits pmpaddr_value = pmpaddr_csr_value[PHYS_ADDR_WIDTH-3:0]; - Bits mask = pmpaddr_value ^ (pmpaddr_value + 1); - range_lo = (pmpaddr_value & ~mask) << 2; - Bits len = mask + 1; - range_hi = ((pmpaddr_value & ~mask) + len) << 2; + Bits pmpaddr_value = pmpaddr_csr_value[PHYS_ADDR_WIDTH-1:0]; + Bits mask = pmpaddr_value ^ (pmpaddr_value + 1); + range_base = (pmpaddr_value & ~mask); + range_limit = range_base + mask; } else if (cfg.A == $bits(PmpCfg_A::NA4)) { - range_lo = (pmpaddr_csr_value << 2)[PHYS_ADDR_WIDTH-1:0]; - range_hi = range_lo + 4; + range_base = pmpaddr_csr_value[PHYS_ADDR_WIDTH-1:0]; + range_limit = range_base + 3; } - if ((paddr >= range_lo) && ((paddr + (access_size/8)) < range_hi)) { + if (((paddr >> 2) >= range_base) && (((paddr + (access_size/8) - 1) >> 2) <= range_limit)) { # full match return PmpMatchResult::FullMatch, cfg; - } else if (!(((paddr + (access_size/8) - 1) < range_lo) || (paddr >= range_hi))) { + } else if (!(((paddr + (access_size/8) - 1) < range_base) || (paddr >= range_limit))) { # this is a partial match. By definition, the access must fail, regardless # of the pmp cfg settings return PmpMatchResult::PartialMatch, -; From cfabfa567e0fd234e0ce9aedcf54799d6a308fc9 Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Mon, 20 Oct 2025 21:12:06 -0700 Subject: [PATCH 2/8] fix: corrected mstatus SXL and UXL encoding --- spec/std/isa/csr/mstatus.yaml | 62 ++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/spec/std/isa/csr/mstatus.yaml b/spec/std/isa/csr/mstatus.yaml index 877d646e0..257d4de1c 100644 --- a/spec/std/isa/csr/mstatus.yaml +++ b/spec/std/isa/csr/mstatus.yaml @@ -143,13 +143,13 @@ fields: description: | *S-mode XLEN* - Sets the effective XLEN for S-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). + Sets the effective XLEN for S-mode (1 = 32-bit, 2 = 64-bit, 3 = 128-bit [reserved]). [when,"SXLEN==32"] - Since the CPU only supports SXLEN==32, this is hardwired to 0. + Since the CPU only supports SXLEN==32, this is hardwired to 1. - [when,"SXLEN==32"] - Since the CPU only supports SXLEN==64, this is hardwired to 1. + [when,"SXLEN==64"] + Since the CPU only supports SXLEN==64, this is hardwired to 2. [when,"SXLEN=3264"] -- @@ -164,26 +164,34 @@ fields: 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 + # SXLEN == 32 is encoded as 1 return csr_value.SXL == 1; + } else if (SXLEN == 64) { + # SXLEN == 64 is encoded as 2 + return csr_value.SXL == 2; } else { # SXLEN could be 32 or 64 - return csr_value.SXL <= 1; + return (csr_value.SXL >= 1 && csr_value.SXL <= 2); } 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; + return CSR[mstatus].SXL; + } else if (csr_value.SXL < 1 || csr_value.SXL > 2) { + # SXL != [1, 2] is not defined (3 reserved for RV128, but that isn't ratified) + return CSR[mstatus].SXL; } else { return csr_value.SXL; } - reset_value: UNDEFINED_LEGAL + + reset_value(): | + if (SXLEN == 32) { + return 1; + } else if (SXLEN == 64) { + return 2; + } else { + return 2; + } UXL: location: 33-32 @@ -192,13 +200,13 @@ fields: description: | U-mode XLEN. - Sets the effective XLEN for U-mode (0 = 32-bit, 1 = 64-bit, 2 = 128-bit [reserved]). + Sets the effective XLEN for U-mode (1 = 32-bit, 2 = 64-bit, 3 = 128-bit [reserved]). [when,"UXLEN == 32"] - Since the CPU only supports UXLEN==32, this is hardwired to 0. + Since the CPU only supports UXLEN==32, this is hardwired to 1. [when,"UXLEN == 64"] - Since the CPU only supports UXLEN==64, this is hardwired to 1. + Since the CPU only supports UXLEN==64, this is hardwired to 2. [when,"UXLEN == 3264"] @@ -214,30 +222,30 @@ fields: 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; + return CSR[mstatus].UXL; + } else if (csr_value.UXL < 1 || csr_value.UXL > 2) { + # UXL != [1, 2] is not defined (3 reserved for RV128, but that isn't ratified) + return CSR[mstatus].UXL; } 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 if (UXLEN == 64) { + return csr_value.UXL == 2; } else { - return csr_value.UXL <= 1; + return (csr_value.UXL >= 1 && csr_value.UXL <= 2); } reset_value(): | if (UXLEN == 32) { - return 0; - } else if (UXLEN == 64) { return 1; + } else if (UXLEN == 64) { + return 2; } else { - return UNDEFINED_LEGAL; + return 2; } TSR: From 287dd92e3c68557417d2d9e929cde6a89f337dd7 Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Mon, 20 Oct 2025 21:14:15 -0700 Subject: [PATCH 3/8] fix: correcting sign extension for addiw and lui --- spec/std/isa/inst/I/addiw.yaml | 3 +-- spec/std/isa/inst/I/lui.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/std/isa/inst/I/addiw.yaml b/spec/std/isa/inst/I/addiw.yaml index 574af8e77..cb77f3db5 100644 --- a/spec/std/isa/inst/I/addiw.yaml +++ b/spec/std/isa/inst/I/addiw.yaml @@ -30,8 +30,7 @@ pseudoinstructions: - when: imm == 0 to: sext.w xd,xs1 operation(): | - XReg operand = sext(X[xs1], 31); - X[xd] = sext(operand + imm, 31); + X[xd] = $signed((X[xs1] + $signed(imm))[31:0]); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/lui.yaml b/spec/std/isa/inst/I/lui.yaml index a5c90e057..86b5bd70c 100644 --- a/spec/std/isa/inst/I/lui.yaml +++ b/spec/std/isa/inst/I/lui.yaml @@ -24,7 +24,7 @@ access: vs: always vu: always data_independent_timing: true -operation(): X[xd] = imm; +operation(): X[xd] = $signed(imm); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model From 39f1ca21cef2826c5147d596ae1c9f6b667c3c39 Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Thu, 6 Nov 2025 14:32:09 -0500 Subject: [PATCH 4/8] fix: correcting sign extension for lw --- backends/cpp_hart_gen/templates/hart.hxx.erb | 9 +++------ spec/std/isa/inst/I/lw.yaml | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/backends/cpp_hart_gen/templates/hart.hxx.erb b/backends/cpp_hart_gen/templates/hart.hxx.erb index 63502081d..d7a534383 100644 --- a/backends/cpp_hart_gen/templates/hart.hxx.erb +++ b/backends/cpp_hart_gen/templates/hart.hxx.erb @@ -402,12 +402,9 @@ namespace udb { _set_xreg(Bits<8>{num}, Bits{value}); } - template < - template class IdxType, unsigned IdxN, bool IdxSigned, - template class ValueType, unsigned ValueN, bool ValueSigned - > - requires (BitsType> && BitsType>) - void _set_xreg(const IdxType& num, const ValueType& value) { + template < template class IdxType, unsigned IdxN, bool IdxSigned > + requires (BitsType>) + void _set_xreg(const IdxType& num, const _PossiblyUnknownBits& value) { if (num != 0_b) { m_xregs[static_cast(num.get())] = value; } diff --git a/spec/std/isa/inst/I/lw.yaml b/spec/std/isa/inst/I/lw.yaml index a53f09d9b..bf3eb4598 100644 --- a/spec/std/isa/inst/I/lw.yaml +++ b/spec/std/isa/inst/I/lw.yaml @@ -30,7 +30,7 @@ access: operation(): | XReg virtual_address = X[xs1] + $signed(imm); - X[xd] = $signed(read_memory<32>(virtual_address, $encoding)); + X[xd] = sext(read_memory<32>(virtual_address, $encoding), 31); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model From ffe143df7485f7ea99b5923e4bfd25148fd73844 Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Sun, 9 Nov 2025 22:24:54 -0500 Subject: [PATCH 5/8] fix: corrected IDL instruction code pruning --- .../ruby-gems/udb/lib/udb/obj/instruction.rb | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/ruby-gems/udb/lib/udb/obj/instruction.rb b/tools/ruby-gems/udb/lib/udb/obj/instruction.rb index 9c38f3e6b..d2835ee79 100644 --- a/tools/ruby-gems/udb/lib/udb/obj/instruction.rb +++ b/tools/ruby-gems/udb/lib/udb/obj/instruction.rb @@ -418,20 +418,23 @@ def fill_symtab(effective_xlen, ast) symtab end - # @param global_symtab [Idl::SymbolTable] Symbol table with global scope populated and a configuration loaded + # @param global_symtab [Idl::SymbolTable] Symbol table with global scope populated and a configuration loaded # @return [Idl::FunctionBodyAst] A pruned abstract syntax tree def pruned_operation_ast(effective_xlen) - defer :pruned_operation_ast do - return nil unless @data.key?("operation()") + @pruned_operation_ast ||= {} + @pruned_operation_ast[effective_xlen] ||= + begin + if @data.key?("operation()") - type_checked_ast = type_checked_operation_ast(effective_xlen) - symtab = fill_symtab(effective_xlen, type_checked_ast) - pruned_ast = type_checked_ast.prune(symtab) - pruned_ast.freeze_tree(symtab) + type_checked_ast = type_checked_operation_ast(effective_xlen) + symtab = fill_symtab(effective_xlen, type_checked_ast) + pruned_ast = type_checked_ast.prune(symtab) + pruned_ast.freeze_tree(symtab) - symtab.release - pruned_ast - end + symtab.release + pruned_ast + end + end end # @param symtab [Idl::SymbolTable] Symbol table with global scope populated From 7166f8417d2f6080ae5f2558cfd014b475fba48f Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Mon, 10 Nov 2025 19:50:14 -0500 Subject: [PATCH 6/8] fix: correcting instruction sign extension --- spec/std/isa/inst/C/c.addiw.yaml | 2 +- spec/std/isa/inst/C/c.subw.yaml | 2 +- spec/std/isa/inst/I/addw.yaml | 6 +++--- spec/std/isa/inst/I/lw.yaml | 2 +- spec/std/isa/inst/I/slliw.yaml | 2 +- spec/std/isa/inst/I/sllw.yaml | 2 +- spec/std/isa/inst/I/sraiw.yaml | 4 ++-- spec/std/isa/inst/I/sraw.yaml | 4 ++-- spec/std/isa/inst/I/srliw.yaml | 2 +- spec/std/isa/inst/I/srlw.yaml | 2 +- spec/std/isa/inst/I/subw.yaml | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spec/std/isa/inst/C/c.addiw.yaml b/spec/std/isa/inst/C/c.addiw.yaml index ad4b743e3..52f5481b5 100644 --- a/spec/std/isa/inst/C/c.addiw.yaml +++ b/spec/std/isa/inst/C/c.addiw.yaml @@ -36,4 +36,4 @@ operation(): | raise(ExceptionCode::IllegalInstruction, mode(), $encoding); } - X[xd] = sext((X[xd] + imm), 32); + X[xd] = sext((X[xd] + sext(imm, 6)), 32); diff --git a/spec/std/isa/inst/C/c.subw.yaml b/spec/std/isa/inst/C/c.subw.yaml index d32df7fe4..b78441657 100644 --- a/spec/std/isa/inst/C/c.subw.yaml +++ b/spec/std/isa/inst/C/c.subw.yaml @@ -32,7 +32,7 @@ access: operation(): | Bits<32> t0 = X[creg2reg(xd)][31:0]; Bits<32> t1 = X[creg2reg(xs2)][31:0]; - X[creg2reg(xd)] = sext(t0 - t1, 31); + X[creg2reg(xd)] = sext(t0 - t1, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/addw.yaml b/spec/std/isa/inst/I/addw.yaml index d5511ac15..0dd5cec5e 100644 --- a/spec/std/isa/inst/I/addw.yaml +++ b/spec/std/isa/inst/I/addw.yaml @@ -29,9 +29,9 @@ access: vu: always data_independent_timing: true operation(): | - XReg operand1 = sext(X[xs1], 31); - XReg operand2 = sext(X[xs2], 31); - X[xd] = sext(operand1 + operand2, 31); + XReg operand1 = sext(X[xs1], 32); + XReg operand2 = sext(X[xs2], 32); + X[xd] = sext(operand1 + operand2, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/lw.yaml b/spec/std/isa/inst/I/lw.yaml index bf3eb4598..86bf2eab4 100644 --- a/spec/std/isa/inst/I/lw.yaml +++ b/spec/std/isa/inst/I/lw.yaml @@ -30,7 +30,7 @@ access: operation(): | XReg virtual_address = X[xs1] + $signed(imm); - X[xd] = sext(read_memory<32>(virtual_address, $encoding), 31); + X[xd] = sext(read_memory<32>(virtual_address, $encoding), 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/slliw.yaml b/spec/std/isa/inst/I/slliw.yaml index cea263865..94f5d51a8 100644 --- a/spec/std/isa/inst/I/slliw.yaml +++ b/spec/std/isa/inst/I/slliw.yaml @@ -28,7 +28,7 @@ access: data_independent_timing: true operation(): | # shamt is between 0-32 - X[xd] = sext(X[xs1] << shamt, 31); + X[xd] = sext(X[xs1] << shamt, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/sllw.yaml b/spec/std/isa/inst/I/sllw.yaml index 9624ae694..129c89496 100644 --- a/spec/std/isa/inst/I/sllw.yaml +++ b/spec/std/isa/inst/I/sllw.yaml @@ -27,7 +27,7 @@ access: vs: always vu: always data_independent_timing: true -operation(): X[xd] = sext(X[xs1] << X[xs2][4:0], 31); +operation(): X[xd] = sext(X[xs1] << X[xs2][4:0], 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/sraiw.yaml b/spec/std/isa/inst/I/sraiw.yaml index 5ad0b76be..d2ba8d239 100644 --- a/spec/std/isa/inst/I/sraiw.yaml +++ b/spec/std/isa/inst/I/sraiw.yaml @@ -30,8 +30,8 @@ access: data_independent_timing: true operation(): | # shamt is between 0-32 - XReg operand = sext(X[xs1], 31); - X[xd] = sext(operand >>> shamt, 31); + XReg operand = sext(X[xs1], 32); + X[xd] = sext(operand >>> shamt, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/sraw.yaml b/spec/std/isa/inst/I/sraw.yaml index fad49d844..df33b57e3 100644 --- a/spec/std/isa/inst/I/sraw.yaml +++ b/spec/std/isa/inst/I/sraw.yaml @@ -28,9 +28,9 @@ access: vu: always data_independent_timing: true operation(): | - XReg operand1 = sext(X[xs1], 31); + XReg operand1 = sext(X[xs1], 32); - X[xd] = sext(operand1 >>> X[xs2][4:0], 31); + X[xd] = sext(operand1 >>> X[xs2][4:0], 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/srliw.yaml b/spec/std/isa/inst/I/srliw.yaml index 48ea69ce3..94c238427 100644 --- a/spec/std/isa/inst/I/srliw.yaml +++ b/spec/std/isa/inst/I/srliw.yaml @@ -30,7 +30,7 @@ operation(): | # shamt is between 0-31 XReg operand = X[xs1][31:0]; - X[xd] = sext(operand >> shamt, 31); + X[xd] = sext(operand >> shamt, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/srlw.yaml b/spec/std/isa/inst/I/srlw.yaml index 471066bb7..382afbcb2 100644 --- a/spec/std/isa/inst/I/srlw.yaml +++ b/spec/std/isa/inst/I/srlw.yaml @@ -27,7 +27,7 @@ access: vs: always vu: always data_independent_timing: true -operation(): X[xd] = sext(X[xs1][31:0] >> X[xs2][4:0], 31); +operation(): X[xd] = sext(X[xs1][31:0] >> X[xs2][4:0], 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/I/subw.yaml b/spec/std/isa/inst/I/subw.yaml index d9de0207a..6163e570f 100644 --- a/spec/std/isa/inst/I/subw.yaml +++ b/spec/std/isa/inst/I/subw.yaml @@ -32,7 +32,7 @@ pseudoinstructions: operation(): | Bits<32> t0 = X[xs1][31:0]; Bits<32> t1 = X[xs2][31:0]; - X[xd] = sext(t0 - t1, 31); + X[xd] = sext(t0 - t1, 32); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model From c36d03890484c5c8ca4dfa1d1c31922ce0d6d56e Mon Sep 17 00:00:00 2001 From: Henrik Gustafsson Date: Tue, 11 Nov 2025 14:22:21 -0500 Subject: [PATCH 7/8] fix: csrs test fixes --- backends/cpp_hart_gen/cpp/include/udb/bits.hpp | 6 +++++- backends/cpp_hart_gen/templates/csrs.hxx.erb | 2 +- spec/std/isa/csr/sstatus.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/backends/cpp_hart_gen/cpp/include/udb/bits.hpp b/backends/cpp_hart_gen/cpp/include/udb/bits.hpp index 6f6b71aeb..19b5b1515 100644 --- a/backends/cpp_hart_gen/cpp/include/udb/bits.hpp +++ b/backends/cpp_hart_gen/cpp/include/udb/bits.hpp @@ -694,6 +694,10 @@ namespace udb { } } + constexpr std::conditional_t get_ignore_unknown() const { + return m_val; + } + constexpr const _Bits& to_defined() const { return *this; } // cast to other Bits types @@ -3467,7 +3471,7 @@ struct fmt::formatter> : formatter::StorageType> { template auto format(BitsClass value, CONTEXT_TYPE &ctx) const { - return fmt::formatter::StorageType>::format(value.get(), ctx); + return fmt::formatter::StorageType>::format(value.get_ignore_unknown(), ctx); } }; diff --git a/backends/cpp_hart_gen/templates/csrs.hxx.erb b/backends/cpp_hart_gen/templates/csrs.hxx.erb index 61f05f03c..a4ba44afa 100644 --- a/backends/cpp_hart_gen/templates/csrs.hxx.erb +++ b/backends/cpp_hart_gen/templates/csrs.hxx.erb @@ -254,7 +254,7 @@ namespace udb { } else { udb_assert(xlen == 64_b, "Bad xlen"); <%- - field_cpp = fields_for_xlen32.map do |field| + field_cpp = fields_for_xlen64.map do |field| if field.dynamic_location? "((m_#{field.name}._hw_read() & 0x#{((1 << field.location(64).size) - 1).to_s(16)}_b).template widening_sll<#{field.location(64).begin}>())" else diff --git a/spec/std/isa/csr/sstatus.yaml b/spec/std/isa/csr/sstatus.yaml index 5505be7a2..f634c7179 100644 --- a/spec/std/isa/csr/sstatus.yaml +++ b/spec/std/isa/csr/sstatus.yaml @@ -33,7 +33,7 @@ fields: UXL: location: 33-32 base: 64 - alias: mstatus.MXR + alias: mstatus.UXL description: | *U-mode XLEN* From a615c97a22d871984cd99c8659493c9bc5ceb8d9 Mon Sep 17 00:00:00 2001 From: Derek Hower Date: Tue, 11 Nov 2025 11:53:49 -0800 Subject: [PATCH 8/8] feat: support CSR[name].reset_value() in IDL --- backends/cpp_hart_gen/lib/gen_cpp.rb | 4 ++++ backends/cpp_hart_gen/templates/csrs.hxx.erb | 11 +++++++++++ spec/std/isa/csr/sstatus.yaml | 2 +- tools/ruby-gems/idlc/lib/idlc/ast.rb | 12 +++++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/backends/cpp_hart_gen/lib/gen_cpp.rb b/backends/cpp_hart_gen/lib/gen_cpp.rb index 9fb62c6b7..16bc493ca 100644 --- a/backends/cpp_hart_gen/lib/gen_cpp.rb +++ b/backends/cpp_hart_gen/lib/gen_cpp.rb @@ -270,6 +270,8 @@ def gen_cpp(symtab, indent = 2, indent_spaces: 2) if csr_obj.nil? if function_name == "sw_read" "#{' ' * indent}__UDB_CSR_BY_ADDR(#{csr.idx_expr.gen_cpp(symtab, 0, indent_spaces:)}).#{function_name}(__UDB_XLEN)" + elsif function_name == "reset_value" + "#{' ' * indent}__UDB_CSR_BY_ADDR(#{csr.idx_expr.gen_cpp(symtab, 0, indent_spaces:)})._#{function_name}()" else "#{' ' * indent}__UDB_CSR_BY_ADDR(#{csr.idx_expr.gen_cpp(symtab, 0, indent_spaces:)}).#{function_name.gsub('?', '_Q_')}(#{args_cpp.join(', ')})" end @@ -280,6 +282,8 @@ def gen_cpp(symtab, indent = 2, indent_spaces: 2) else "#{' ' * indent}__UDB_CSR_BY_NAME(#{csr_obj.name})._#{function_name}()" end + elsif function_name == "reset_value" + "#{' ' * indent}__UDB_CSR_BY_NAME(#{csr_obj.name})._#{function_name}()" else "#{' ' * indent}__UDB_CSR_BY_NAME(#{csr_obj.name}).#{function_name.gsub('?', '_Q_')}(#{args_cpp.join(', ')})" end diff --git a/backends/cpp_hart_gen/templates/csrs.hxx.erb b/backends/cpp_hart_gen/templates/csrs.hxx.erb index a4ba44afa..0fb5ec20f 100644 --- a/backends/cpp_hart_gen/templates/csrs.hxx.erb +++ b/backends/cpp_hart_gen/templates/csrs.hxx.erb @@ -213,6 +213,17 @@ namespace udb { const std::string name() const override { return "<%= csr.name %>"; } PrivilegeMode mode() const override { return PrivilegeMode::<%= csr.priv_mode %>; } bool writable() const override { return <%= csr.writable %>; } + ValueType _reset_value() const { + if (defined()) { + return 0_b + <%- fields_for_xlen.each do |field| -%> + | (m_<%= field.name %>.reset_value() << _Bits<64, false>(m_<%= field.name %>.location().lsb)) + <%- end -%> + ; + } else { + "x"_xb; + } + } bool defined() override { return <%= csr.defined_by_condition.to_cxx { |ext_name, ext_req| diff --git a/spec/std/isa/csr/sstatus.yaml b/spec/std/isa/csr/sstatus.yaml index f634c7179..e22a88cf8 100644 --- a/spec/std/isa/csr/sstatus.yaml +++ b/spec/std/isa/csr/sstatus.yaml @@ -28,7 +28,7 @@ fields: Alias of `mstatus.SD`. type: RO-H - reset_value: UNDEFINED_LEGAL + reset_value(): return CSR[mstatus].reset_value(); affectedBy: [F, D, V] UXL: location: 33-32 diff --git a/tools/ruby-gems/idlc/lib/idlc/ast.rb b/tools/ruby-gems/idlc/lib/idlc/ast.rb index ea179764b..5af63d647 100644 --- a/tools/ruby-gems/idlc/lib/idlc/ast.rb +++ b/tools/ruby-gems/idlc/lib/idlc/ast.rb @@ -7450,6 +7450,8 @@ def type_check(symtab) elsif ["implemented_without?"].include?(function_name) type_error "Expecting one argument" unless args.size == 1 type_error "Expecting an ExtensionName" unless args[0].type(symtab).kind == :enum_ref && args[0].class_name == "ExtensionName" + elsif function_name == "reset_value" + type_error "unexpected argument(s)" unless args.empty? else type_error "'#{function_name}' is not a supported CSR function call" end @@ -7458,7 +7460,7 @@ def type_check(symtab) def type(symtab) case function_name - when "sw_read" + when "sw_read", "reset_value" if csr_known?(symtab) l = symtab.csr(csr.csr_name).length Type.new(:bits, width: (l.nil? ? :unknown : l)) @@ -7506,6 +7508,14 @@ def value(symtab) ext_name = extension_name_enum_type.element_names[idx] cd.implemented_without?(ext_name) + when "reset_value" + value_error "CSR not knowable" unless csr_known?(symtab) + cd = csr_def(symtab) + v = cd.reset_value + if v == "UNDEFINED_LEGAL" + value_error "undefined reset value" + end + v else internal_error "TODO: #{function_name}" end