Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
602c7e5
feat: rv64 test configuration
henrikg-qc Oct 20, 2025
cfabfa5
fix: corrected mstatus SXL and UXL encoding
henrikg-qc Oct 21, 2025
287dd92
fix: correcting sign extension for addiw and lui
henrikg-qc Oct 21, 2025
39f1ca2
fix: correcting sign extension for lw
henrikg-qc Nov 6, 2025
ffe143d
fix: corrected IDL instruction code pruning
henrikg-qc Nov 10, 2025
7166f84
fix: correcting instruction sign extension
henrikg-qc Nov 11, 2025
c36d038
fix: csrs test fixes
henrikg-qc Nov 11, 2025
8c3f148
fix: added Sv39 to config for RV64 tests
henrikg-qc Nov 21, 2025
e1429e8
feat: added build define to ignore undefined/unknown bits
henrikg-qc Nov 21, 2025
2fc75a2
fix: corrected sign extension for divw and remw instructions
henrikg-qc Nov 21, 2025
0df2f91
fix: defining sstatus(64).UXL reset value to 64bit
henrikg-qc Nov 21, 2025
0eca59d
fix: corrected virtual memory page walker
henrikg-qc Nov 21, 2025
a31ec24
feat: updating benchmark gem version
henrikg-qc Nov 21, 2025
2a11f65
feat: added 64 bit riscv-tests suite in regression.
henrikg-qc Nov 21, 2025
ebe609e
Merge branch 'main' into rv64tests
henrikg-qc Nov 21, 2025
b345c5c
fix: corrected typo in regression arguments
henrikg-qc Nov 21, 2025
ee306c4
fix: removed Sv32 from RV64 test configuration
henrikg-qc Nov 21, 2025
69ee06b
Revert "feat: updating benchmark gem version"
henrikg-qc Nov 24, 2025
ecf8643
fix: idl changes after idl type checking
henrikg-qc Nov 24, 2025
94d2f1a
ci: renamned 32bit test suite regression to match previous regression…
henrikg-qc Nov 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/workflows/regress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,19 @@ jobs:
uses: actions/checkout@v4
- name: singularity setup
uses: ./.github/actions/singularity-setup
- name: Run riscv-tests
run: ./do test:riscv_tests CONFIG=rv32 JOBS=4
- name: Run RV32 riscv-tests
run: ./do test:riscv_tests CONFIG=rv32 IGNOREUNDEFINED=YES JOBS=4
regress-riscv-tests-64:
runs-on: ubuntu-latest
env:
SINGULARITY: 1
steps:
- name: Clone Github Repo Action
uses: actions/checkout@v4
- name: singularity setup
uses: ./.github/actions/singularity-setup
- name: Run RV64 riscv-tests
run: ./do test:riscv_tests CONFIG=rv64 IGNOREUNDEFINED=YES JOBS=4
regress-xqci-doc:
runs-on: ubuntu-latest
env:
Expand Down
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [],
Expand Down
6 changes: 6 additions & 0 deletions backends/cpp_hart_gen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ add_library(hart
# ../gen/iss/oryon/src/decode.cxx
)
target_include_directories(hart PUBLIC ${CMAKE_SOURCE_DIR}/include)
if(IGNOREUNDEFINED STREQUAL "YES")
target_compile_definitions(hart PUBLIC IGNOREUNDEFINED)
endif()
target_link_libraries(hart PUBLIC yaml-cpp::yaml-cpp nlohmann_json_schema_validator fmt::fmt ctre::ctre -lgmp -lgmpxx)

# add_library(hart_c ${CMAKE_SOURCE_DIR}/src/libhart_c.cpp)
Expand All @@ -135,6 +138,9 @@ add_executable(iss
${CMAKE_SOURCE_DIR}/src/iss.cpp
${CMAKE_SOURCE_DIR}/src/elf_reader.cpp
)
if(IGNOREUNDEFINED STREQUAL "YES")
target_compile_definitions(iss PUBLIC IGNOREUNDEFINED)
endif()
target_link_libraries(iss PRIVATE hart elf CLI11::CLI11)


Expand Down
49 changes: 29 additions & 20 deletions backends/cpp_hart_gen/cpp/include/udb/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ static_assert(sizeof(1ull) == 8);
#error "Compiler does not support __int128"
#endif

#ifndef IGNOREUNDEFINED
#define UNDEFINED_VALUE_ERROR(s) throw UndefinedValueError(s)
#else
#define UNDEFINED_VALUE_ERROR(s)
#endif


namespace udb {

// helper to find the max of N unsigned values at compile time
Expand Down Expand Up @@ -694,6 +701,10 @@ namespace udb {
}
}

constexpr std::conditional_t<Signed, SignedStorageType, const StorageType &> get_ignore_unknown() const {
return m_val;
}

constexpr const _Bits& to_defined() const { return *this; }

// cast to other Bits types
Expand Down Expand Up @@ -2408,27 +2419,25 @@ namespace udb {
constexpr operator BitsType<M, _Signed>() const {
if constexpr (!BitsType<M, _Signed>::PossiblyUnknown) {
if (m_unknown_mask != 0) {
throw UndefinedValueError("Cannot convert value with unknowns to Bits type");
UNDEFINED_VALUE_ERROR("Cannot convert value with unknowns to Bits type");
}
}
return BitsType<M, _Signed>{*this};
}

template <typename T = std::conditional_t<Signed, SignedStorageType, StorageType>>
constexpr T get() const {
if (m_unknown_mask == 0_b) {
return m_val.get();
} else {
throw UndefinedValueError("Cannot convert value with unknowns to a native C++ type");
if (m_unknown_mask != 0_b) {
UNDEFINED_VALUE_ERROR("Cannot convert value with unknowns to a native C++ type");
}
return m_val.get();
}

constexpr _Bits<N, Signed> to_defined() const {
if (m_unknown_mask == 0_b) {
return m_val;
} else {
throw UndefinedValueError("Cannot convert value with unknowns to a defined type");
if (m_unknown_mask != 0_b) {
UNDEFINED_VALUE_ERROR("Cannot convert value with unknowns to a defined type");
}
return m_val;
}


Expand Down Expand Up @@ -2480,7 +2489,7 @@ namespace udb {
constexpr bool operator op(const BitsType<M, _Signed> &rhs) const { \
if (m_unknown_mask != 0_b || \
(BitsType<M, _Signed>::PossiblyUnknown && (rhs.unknown_mask() != 0_b))) { \
throw UndefinedValueError("Cannot compare unknown value"); \
UNDEFINED_VALUE_ERROR("Cannot compare unknown value"); \
} \
return get() op rhs.to_defined().get(); \
}
Expand Down Expand Up @@ -2626,7 +2635,7 @@ namespace udb {
constexpr _PossiblyUnknownBits operator<<(const BitsType<M, false> &shamt) const {
if constexpr (BitsType<M, false>::PossiblyUnknown) {
if (shamt.unknown_mask() != 0_b) {
throw UndefinedValueError("Cannot shift an unknown amount");
UNDEFINED_VALUE_ERROR("Cannot shift an unknown amount");
}
}
if (shamt.get() >= N) {
Expand All @@ -2641,7 +2650,7 @@ namespace udb {
constexpr _PossiblyUnknownBits operator>>(const BitsClass<M, false> &shamt) const {
if constexpr (BitsClass<M, false>::PossiblyUnknown) {
if (shamt.unknown_mask() != 0_b) {
throw UndefinedValueError("Cannot shift an unknown amount");
UNDEFINED_VALUE_ERROR("Cannot shift an unknown amount");
}
}
if (shamt.get() >= N) {
Expand All @@ -2656,7 +2665,7 @@ namespace udb {
constexpr _PossiblyUnknownBits sra(const BitsClass<M, false> &shamt) const {
if constexpr (BitsClass<M, false>::PossiblyUnknown) {
if (shamt.unknown_mask() != 0_b) {
throw UndefinedValueError("Cannot shift an unknown amount");
UNDEFINED_VALUE_ERROR("Cannot shift an unknown amount");
}
}
if (shamt.get() >= N) {
Expand Down Expand Up @@ -2715,7 +2724,7 @@ namespace udb {
_Bits<constmax_v<N, RhsN> + 1, Signed> lhs{*this};

if (m_unknown_mask != 0_b || _rhs.unknown_mask() != 0_b) {
throw UndefinedValueError("Addition is not defined on undefined values");
UNDEFINED_VALUE_ERROR("Addition is not defined on undefined values");
}

if constexpr (RhsBitsType<RhsN, RhsSigned>::RuntimeWidth) {
Expand All @@ -2738,7 +2747,7 @@ namespace udb {
_Bits<constmax_v<N, RhsN> + 1, Signed> lhs{*this};

if (m_unknown_mask != 0_b || _rhs.unknown_mask() != 0_b) {
throw UndefinedValueError("Addition is not defined on undefined values");
UNDEFINED_VALUE_ERROR("Addition is not defined on undefined values");
}

if constexpr (RhsBitsType<RhsN, RhsSigned>::RuntimeWidth) {
Expand Down Expand Up @@ -2767,7 +2776,7 @@ namespace udb {
_Bits<addsat_v<N, RhsN>, Signed> lhs{*this};

if (m_unknown_mask != 0_b || _rhs.unknown_mask() != 0_b) {
throw UndefinedValueError("Addition is not defined on undefined values");
UNDEFINED_VALUE_ERROR("Addition is not defined on undefined values");
}

if constexpr (RhsBitsType<RhsN, RhsSigned>::RuntimeWidth) {
Expand Down Expand Up @@ -3171,7 +3180,7 @@ namespace udb {
m_val, result_width};

if (unknown_mask() != 0_b || other.unknown_mask() != 0_b) {
throw UndefinedValueError("Multiplication not defined on undefined values");
UNDEFINED_VALUE_ERROR("Multiplication not defined on undefined values");
}

if constexpr (RhsBitsType<addsat_v<MaxN, RhsN>, RhsSigned>::RuntimeWidth) {
Expand All @@ -3194,7 +3203,7 @@ namespace udb {
m_val, result_width};

if (unknown_mask() != 0_b || other.unknown_mask() != 0_b) {
throw UndefinedValueError("Addition not defined on undefined values");
UNDEFINED_VALUE_ERROR("Addition not defined on undefined values");
}

if constexpr (RhsBitsType<constmax_v<MaxN, RhsN> + 1, RhsSigned>::RuntimeWidth) {
Expand All @@ -3217,7 +3226,7 @@ namespace udb {
m_val, result_width};

if (unknown_mask() != 0_b || other.unknown_mask() != 0_b) {
throw UndefinedValueError("Subtraction not defined on undefined values");
UNDEFINED_VALUE_ERROR("Subtraction not defined on undefined values");
}

if constexpr (RhsBitsType<constmax_v<MaxN, RhsN> + 1, RhsSigned>::RuntimeWidth) {
Expand Down Expand Up @@ -3467,7 +3476,7 @@ struct fmt::formatter<BitsClass<N, Signed>>
: formatter<typename BitsClass<N, Signed>::StorageType> {
template <typename CONTEXT_TYPE>
auto format(BitsClass<N, Signed> value, CONTEXT_TYPE &ctx) const {
return fmt::formatter<typename BitsClass<N, Signed>::StorageType>::format(value.get(), ctx);
return fmt::formatter<typename BitsClass<N, Signed>::StorageType>::format(value.get_ignore_unknown(), ctx);
}
};

Expand Down
80 changes: 66 additions & 14 deletions backends/cpp_hart_gen/tasks.rake
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,14 @@ rule %r{#{CPP_HART_GEN_DST}/[^/]+/build/Makefile} => [
"-DCONFIG_LIST=\"#{ENV['CONFIG'].gsub(',', ';')}\"",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
"-DCMAKE_BUILD_TYPE=#{cmake_build_type}"
].join(" ")
]
if ENV["IGNOREUNDEFINED"].nil?
cmd.push("-DIGNOREUNDEFINED=NO")
else
cmd.push("-DIGNOREUNDEFINED=YES")
end

sh cmd
sh cmd.join(" ")
end

rule %r{#{CPP_HART_GEN_DST}/[^/]+/include/udb/[^/]+\.hpp} do |t|
Expand Down Expand Up @@ -346,6 +351,15 @@ namespace :build do
end
end

task iss: ["gen:cpp_hart"] do
_, build_name = configs_build_name

Rake::Task["#{CPP_HART_GEN_DST}/#{build_name}/build/Makefile"].invoke
Dir.chdir("#{CPP_HART_GEN_DST}/#{build_name}/build") do
sh "make -j #{$jobs} iss"
end
end

task renode_hart: ["gen:cpp_hart"] do
_, build_name = configs_build_name

Expand Down Expand Up @@ -395,7 +409,7 @@ namespace :test do
end
end

task riscv_tests: ["build_riscv_tests", "build:cpp_hart"] do
task riscv_tests: ["build_riscv_tests", "build:iss"] do
configs_name, build_name = configs_build_name
rv32uiTests = ["simple", "add", "addi", "and",
"andi", "auipc", "beq", "bge", "bgeu", "blt",
Expand All @@ -405,24 +419,62 @@ namespace :test do
"sw", "st_ld", "sll", "slli", "slt", "slti",
"sltiu", "sltu", "sra", "srai", "srl",
"srli", "sub", "xor", "xori"]
rv64uiTests = ["add", "addi", "addiw", "addw",
"and", "andi",
"auipc",
"beq", "bge", "bgeu", "blt", "bltu", "bne",
"simple",
"fence_i",
"jal", "jalr",
"lb", "lbu", "lh", "lhu", "lw", "lwu", "ld", "ld_st",
"lui",
"ma_data",
"or", "ori",
"sb", "sh", "sw", "sd", "st_ld",
"sll", "slli", "slliw", "sllw",
"slt", "slti", "sltiu", "sltu",
"sra", "srai", "sraiw", "sraw",
"srl", "srli", "srliw", "srlw",
"sub", "subw",
"xor", "xori"]

rv32umTests = [ "div", "divu",
"mul", "mulh", "mulhsu", "mulhu",
"rem", "remu" ]
rv64umTests = ["div", "divu", "divuw", "divw",
"mul", "mulh", "mulhsu", "mulhu", "mulw",
"rem", "remu", "remuw", "remw"]

# compressed tests same for rv32 as rv64
ucTests = [ "rvc" ]

rv32siTests = ["csr", "dirty", "ma_fetch", "scall", "sbreak"]
rv64siTests = ["csr", "dirty", "icache-alias", "ma_fetch", "scall", "sbreak"]

rv32uiTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m rv32 -c #{$root}/cfgs/rv32-riscv-tests.yaml ext/riscv-tests/isa/rv32ui-p-#{t}"
if configs_name[0] == "rv64"
uiTests = rv64uiTests
umTests = rv64umTests
siTests = rv64siTests
else
uiTests = rv32uiTests
umTests = rv32umTests
siTests = rv32siTests
end

rv32umTests = [ "div", "divu", "mul", "mulh", "mulhsu", "mulhu", "rem", "remu" ]
rv32umTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m rv32 -c #{$root}/cfgs/rv32-riscv-tests.yaml ext/riscv-tests/isa/rv32um-p-#{t}"
uiTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m #{configs_name[0]} -c #{$root}/cfgs/#{configs_name[0]}-riscv-tests.yaml ext/riscv-tests/isa/#{configs_name[0]}ui-p-#{t}"
end

rv32ucTests = [ "rvc" ]
rv32ucTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m rv32 -c #{$root}/cfgs/rv32-riscv-tests.yaml ext/riscv-tests/isa/rv32uc-p-#{t}"
umTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m #{configs_name[0]} -c #{$root}/cfgs/#{configs_name[0]}-riscv-tests.yaml ext/riscv-tests/isa/#{configs_name[0]}um-p-#{t}"
end

rv32siTests = ["csr", "dirty", "ma_fetch", "scall", "sbreak"]
rv32siTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m rv32 -c #{$root}/cfgs/rv32-riscv-tests.yaml ext/riscv-tests/isa/rv32si-p-#{t}"
ucTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m #{configs_name[0]} -c #{$root}/cfgs/#{configs_name[0]}-riscv-tests.yaml ext/riscv-tests/isa/#{configs_name[0]}uc-p-#{t}"
end

siTests.each do |t|
sh "#{CPP_HART_GEN_DST}/#{build_name}/build/iss -m #{configs_name[0]} -c #{$root}/cfgs/#{configs_name[0]}-riscv-tests.yaml ext/riscv-tests/isa/#{configs_name[0]}si-p-#{t}"
end
end
end
2 changes: 1 addition & 1 deletion backends/cpp_hart_gen/templates/csrs.hxx.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 3 additions & 6 deletions backends/cpp_hart_gen/templates/hart.hxx.erb
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,9 @@ namespace udb {
_set_xreg(Bits<8>{num}, Bits<MXLEN>{value});
}

template <
template <unsigned, bool> class IdxType, unsigned IdxN, bool IdxSigned,
template<unsigned, bool> class ValueType, unsigned ValueN, bool ValueSigned
>
requires (BitsType<IdxType<IdxN, IdxSigned>> && BitsType<ValueType<ValueN, ValueSigned>>)
void _set_xreg(const IdxType<IdxN, IdxSigned>& num, const ValueType<ValueN, ValueSigned>& value) {
template < template <unsigned, bool> class IdxType, unsigned IdxN, bool IdxSigned >
requires (BitsType<IdxType<IdxN, IdxSigned>>)
void _set_xreg(const IdxType<IdxN, IdxSigned>& num, const _PossiblyUnknownBits<MXLEN, false>& value) {
if (num != 0_b) {
m_xregs[static_cast<unsigned>(num.get())] = value;
}
Expand Down
Loading
Loading