aboutsummaryrefslogtreecommitdiff
path: root/rv64cpu/tb/core
diff options
context:
space:
mode:
Diffstat (limited to 'rv64cpu/tb/core')
-rw-r--r--rv64cpu/tb/core/tb_core.cc425
1 files changed, 418 insertions, 7 deletions
diff --git a/rv64cpu/tb/core/tb_core.cc b/rv64cpu/tb/core/tb_core.cc
index 30fe554..39d4f19 100644
--- a/rv64cpu/tb/core/tb_core.cc
+++ b/rv64cpu/tb/core/tb_core.cc
@@ -20,11 +20,14 @@
// (instruction memory + data memory) to verify multi-cycle pipeline behavior.
// It acts as a simple memory model, feeding instructions and returning data.
+#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdint>
+#include <iterator>
#include <vector>
#include <map>
+#include <string>
#include <verilated.h>
#include "Vrichard_core.h"
@@ -32,6 +35,53 @@
#include <verilated_vcd_c.h>
#endif
+// ---------------------------------
+// CSR addresses & cause codes used in tests
+// ---------------------------------
+constexpr uint16_t CSR_MSTATUS = 0x300;
+constexpr uint16_t CSR_MISA = 0x301;
+constexpr uint16_t CSR_MEDELEG = 0x302;
+constexpr uint16_t CSR_MIDELEG = 0x303;
+constexpr uint16_t CSR_MIE = 0x304;
+constexpr uint16_t CSR_MTVEC = 0x305;
+constexpr uint16_t CSR_MEPC = 0x341;
+constexpr uint16_t CSR_MSCRATCH = 0x340;
+constexpr uint16_t CSR_MCAUSE = 0x342;
+constexpr uint16_t CSR_MTVAL = 0x343;
+constexpr uint16_t CSR_SSTATUS = 0x100;
+constexpr uint16_t CSR_STVEC = 0x105;
+constexpr uint16_t CSR_SSCRATCH = 0x140;
+constexpr uint16_t CSR_SEPC = 0x141;
+constexpr uint16_t CSR_SCAUSE = 0x142;
+constexpr uint16_t CSR_STVAL = 0x143;
+
+constexpr int MSTATUS_MIE_BIT = 3;
+constexpr int MSTATUS_MPIE_BIT = 7;
+constexpr int MSTATUS_MPP_LO = 11;
+constexpr int SSTATUS_SIE_BIT = 1;
+constexpr int SSTATUS_SPIE_BIT = 5;
+constexpr int SSTATUS_SPP_BIT = 8;
+
+constexpr uint64_t EXC_INST_ILLEGAL = 2ULL;
+constexpr uint64_t EXC_BREAKPOINT = 3ULL;
+constexpr uint64_t EXC_LOAD_FAULT = 5ULL;
+constexpr uint64_t EXC_STORE_FAULT = 7ULL;
+constexpr uint64_t EXC_ECALL_FROM_U = 8ULL;
+constexpr uint64_t EXC_ECALL_FROM_M = 11ULL;
+constexpr uint64_t INTERRUPT_BIT = 1ULL << 63;
+constexpr uint64_t INT_M_EXTERNAL = 11ULL;
+constexpr uint64_t INT_M_TIMER = 7ULL;
+
+constexpr uint64_t LOG_ENTRY_STRIDE = 24ULL;
+constexpr uint64_t MACHINE_TRAP_VECTOR = 0x00000000ULL;
+constexpr uint64_t SUPERVISOR_TRAP_VECTOR = 0x00000100ULL;
+constexpr uint64_t MACHINE_LOG_PTR_ADDR = 0x000000000000FFF0ULL;
+constexpr uint64_t SUPERVISOR_LOG_PTR_ADDR = 0x000000000000FFE0ULL;
+
+constexpr uint64_t PRIV_MODE_U = 0ULL;
+constexpr uint64_t PRIV_MODE_S = 1ULL;
+constexpr uint64_t PRIV_MODE_M = 3ULL;
+
// -----------------------
// RISC-V Instruction Encoding Helpers
// -----------------------
@@ -81,6 +131,7 @@ static uint32_t rv_b_type(int32_t offset, uint32_t rs2, uint32_t rs1, uint32_t f
// Common instruction shorthands
static uint32_t NOP() { return 0x00000013; } // addi x0, x0, 0
+static uint32_t ILLEGAL() { return 0xFFFFFFFF; }
static uint32_t ADDI(uint32_t rd, uint32_t rs1, int32_t imm) {
return rv_i_type(static_cast<uint32_t>(imm) & 0xFFF, rs1, 0x0, rd, 0x13);
}
@@ -108,6 +159,51 @@ static uint32_t LUI(uint32_t rd, uint32_t imm) {
static uint32_t JAL(uint32_t rd, int32_t offset) {
return rv_j_type(offset, rd, 0x6f);
}
+static uint32_t JALR(uint32_t rd, uint32_t rs1, int32_t imm) {
+ return rv_i_type(static_cast<uint32_t>(imm) & 0xFFF, rs1, 0x0, rd, 0x67);
+}
+static uint32_t SYSTEM(uint32_t funct12, uint32_t rs1, uint32_t funct3, uint32_t rd) {
+ return ((funct12 & 0xFFF) << 20) | ((rs1 & 0x1F) << 15) | ((funct3 & 0x7) << 12) | ((rd & 0x1F) << 7) | 0x73;
+}
+static uint32_t ECALL() { return SYSTEM(0x000, 0, 0x0, 0); }
+static uint32_t EBREAK() { return SYSTEM(0x001, 0, 0x0, 0); }
+static uint32_t MRET() { return SYSTEM(0x302, 0, 0x0, 0); }
+static uint32_t SRET() { return SYSTEM(0x102, 0, 0x0, 0); }
+static uint32_t CSRInstrReg(uint32_t csr, uint32_t funct3, uint32_t rd, uint32_t rs1) {
+ return ((csr & 0xFFF) << 20) | ((rs1 & 0x1F) << 15) | ((funct3 & 0x7) << 12) | ((rd & 0x1F) << 7) | 0x73;
+}
+static uint32_t CSRRW(uint32_t rd, uint32_t csr, uint32_t rs1) {
+ return CSRInstrReg(csr, 0b001, rd, rs1);
+}
+static uint32_t CSRRS(uint32_t rd, uint32_t csr, uint32_t rs1) {
+ return CSRInstrReg(csr, 0b010, rd, rs1);
+}
+static uint32_t CSRRWI(uint32_t rd, uint32_t csr, uint32_t zimm) {
+ return CSRInstrReg(csr, 0b101, rd, zimm & 0x1F);
+}
+
+static void emit_load_imm64(std::vector<uint32_t>& prog, uint32_t rd, uint64_t imm) {
+ const uint64_t upper = (imm + 0x800ULL) >> 12;
+ int32_t lower = static_cast<int32_t>(imm & 0xFFFULL);
+ if (lower >= 2048) {
+ lower -= 4096;
+ }
+ prog.push_back(LUI(rd, static_cast<uint32_t>(upper)));
+ prog.push_back(ADDI(rd, rd, lower));
+}
+
+static void emit_nops(std::vector<uint32_t>& prog, int count) {
+ for (int i = 0; i < count; ++i) {
+ prog.push_back(NOP());
+ }
+}
+
+static void emit_csrrw_imm64(std::vector<uint32_t>& prog, uint32_t tmp_reg, uint32_t csr, uint64_t value) {
+ // CSR source operand is read in ID stage, so we need a short drain window after loading tmp_reg.
+ emit_load_imm64(prog, tmp_reg, value);
+ emit_nops(prog, 6);
+ prog.push_back(CSRRW(0, csr, tmp_reg));
+}
// -----------------------
// Test Infrastructure
@@ -148,7 +244,7 @@ public:
return NOP(); // Return NOP for unmapped addresses
}
- uint64_t read_data(uint64_t addr) {
+ uint64_t read_data(uint64_t addr) const {
// Align to doubleword
uint64_t aligned = addr & ~0x7ULL;
auto it = dmem.find(aligned);
@@ -162,6 +258,92 @@ public:
}
};
+static std::vector<uint32_t> make_machine_trap_handler_program() {
+ constexpr uint32_t REG_PTR = 5;
+ constexpr uint32_t REG_MCAUSE = 6;
+ constexpr uint32_t REG_MEPC = 7;
+ constexpr uint32_t REG_MTVAL = 28;
+ constexpr uint32_t REG_TMP = 29;
+ constexpr uint32_t REG_SLOT_ADDR = 30;
+
+ std::vector<uint32_t> prog;
+ emit_load_imm64(prog, REG_SLOT_ADDR, MACHINE_LOG_PTR_ADDR);
+ prog.push_back(LD(REG_PTR, REG_SLOT_ADDR, 0));
+ emit_nops(prog, 12);
+ prog.push_back(CSRRS(REG_MCAUSE, CSR_MCAUSE, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_MCAUSE, REG_PTR, 0));
+ prog.push_back(CSRRS(REG_MEPC, CSR_MEPC, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_MEPC, REG_PTR, 8));
+ prog.push_back(CSRRS(REG_MTVAL, CSR_MTVAL, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_MTVAL, REG_PTR, 16));
+ prog.push_back(ADDI(REG_PTR, REG_PTR, static_cast<int32_t>(LOG_ENTRY_STRIDE)));
+ prog.push_back(SD(REG_PTR, REG_SLOT_ADDR, 0));
+ prog.push_back(CSRRS(REG_TMP, CSR_MEPC, 0));
+ prog.push_back(ADDI(REG_TMP, REG_TMP, 4));
+ emit_nops(prog, 12);
+ prog.push_back(CSRRW(0, CSR_MEPC, REG_TMP));
+ prog.push_back(MRET());
+ prog.push_back(NOP());
+ prog.push_back(NOP());
+ return prog;
+}
+
+static std::vector<uint32_t> make_supervisor_trap_handler_program() {
+ constexpr uint32_t REG_PTR = 5;
+ constexpr uint32_t REG_SCAUSE = 6;
+ constexpr uint32_t REG_SEPC = 7;
+ constexpr uint32_t REG_STVAL = 28;
+ constexpr uint32_t REG_TMP = 29;
+ constexpr uint32_t REG_SLOT_ADDR = 30;
+
+ std::vector<uint32_t> prog;
+ emit_load_imm64(prog, REG_SLOT_ADDR, SUPERVISOR_LOG_PTR_ADDR);
+ prog.push_back(LD(REG_PTR, REG_SLOT_ADDR, 0));
+ emit_nops(prog, 12);
+ prog.push_back(CSRRS(REG_SCAUSE, CSR_SCAUSE, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_SCAUSE, REG_PTR, 0));
+ prog.push_back(CSRRS(REG_SEPC, CSR_SEPC, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_SEPC, REG_PTR, 8));
+ prog.push_back(CSRRS(REG_STVAL, CSR_STVAL, 0));
+ emit_nops(prog, 4);
+ prog.push_back(SD(REG_STVAL, REG_PTR, 16));
+ prog.push_back(ADDI(REG_PTR, REG_PTR, static_cast<int32_t>(LOG_ENTRY_STRIDE)));
+ prog.push_back(SD(REG_PTR, REG_SLOT_ADDR, 0));
+ prog.push_back(CSRRS(REG_TMP, CSR_SEPC, 0));
+ prog.push_back(ADDI(REG_TMP, REG_TMP, 4));
+ emit_nops(prog, 12);
+ prog.push_back(CSRRW(0, CSR_SEPC, REG_TMP));
+ prog.push_back(SRET());
+ prog.push_back(NOP());
+ prog.push_back(NOP());
+ return prog;
+}
+
+static void install_trap_handlers(MemoryModel& mem) {
+ mem.load_program(MACHINE_TRAP_VECTOR, make_machine_trap_handler_program());
+ mem.load_program(SUPERVISOR_TRAP_VECTOR, make_supervisor_trap_handler_program());
+}
+
+struct TrapRecord {
+ uint64_t mcause;
+ uint64_t mepc;
+ uint64_t mtval;
+};
+
+static TrapRecord fetch_trap_record(const MemoryModel& mem, uint64_t base, int index) {
+ const uint64_t addr = base + static_cast<uint64_t>(index) * LOG_ENTRY_STRIDE;
+ TrapRecord rec;
+ rec.mcause = mem.read_data(addr + 0);
+ rec.mepc = mem.read_data(addr + 8);
+ rec.mtval = mem.read_data(addr + 16);
+ return rec;
+}
+
// -----------------------
// Core Simulation Wrapper
// -----------------------
@@ -170,11 +352,17 @@ public:
Vrichard_core* top;
MemoryModel mem;
uint64_t sim_time;
+ bool ext_timer_int_level;
+ bool ext_software_int_level;
+ bool ext_external_int_level;
#if VM_TRACE
VerilatedVcdC* tfp;
#endif
- CoreSim() : sim_time(0) {
+ CoreSim() : sim_time(0),
+ ext_timer_int_level(false),
+ ext_software_int_level(false),
+ ext_external_int_level(false) {
top = new Vrichard_core;
#if VM_TRACE
Verilated::traceEverOn(true);
@@ -195,6 +383,7 @@ public:
top->rst = 1;
top->imem_rdata = NOP();
top->dmem_rdata = 0;
+ clear_interrupts();
for (int i = 0; i < cycles; i++) {
tick();
}
@@ -212,6 +401,10 @@ public:
top->dmem_rdata = 0;
}
+ top->ext_timer_int = ext_timer_int_level;
+ top->ext_software_int = ext_software_int_level;
+ top->ext_external_int = ext_external_int_level;
+
// Rising edge
top->clk = 0;
top->eval();
@@ -237,8 +430,28 @@ public:
tick();
}
}
+
+ void set_interrupt_lines(bool timer, bool software, bool external) {
+ ext_timer_int_level = timer;
+ ext_software_int_level = software;
+ ext_external_int_level = external;
+ }
+
+ void clear_interrupts() {
+ set_interrupt_lines(false, false, false);
+ }
};
+static std::vector<uint64_t> collect_pc_trace(CoreSim& sim, int cycles) {
+ std::vector<uint64_t> trace;
+ trace.reserve(static_cast<size_t>(cycles));
+ for (int i = 0; i < cycles; ++i) {
+ sim.tick();
+ trace.push_back(sim.top->imem_addr);
+ }
+ return trace;
+}
+
// ═══════════════════════════════════════════════════════════════
// Test Cases
// ═══════════════════════════════════════════════════════════════
@@ -631,16 +844,209 @@ void test_fibonacci(CoreSim& sim) {
}
// ═══════════════════════════════════════════════════════════════
+// Targeted Trap/Interrupt Scenarios (ctest-selectable)
+// ═══════════════════════════════════════════════════════════════
+
+static void run_mem_fault_pipeline_case() {
+ std::cout << "[CASE] mem_fault_pipeline" << std::endl;
+ CoreSim sim;
+ install_trap_handlers(sim.mem);
+
+ const uint64_t boot_pc = 0x80000000ULL;
+ const uint64_t load_addr = 0x0000000000001003ULL;
+ const uint64_t store_addr = 0x0000000000002005ULL;
+ const uint64_t log_base = 0x0000000000009000ULL;
+ sim.mem.write_data(MACHINE_LOG_PTR_ADDR, log_base);
+ ASSERT_EQ(sim.mem.read_data(MACHINE_LOG_PTR_ADDR), log_base, "machine log pointer seeded");
+
+ std::vector<uint32_t> program;
+ emit_nops(program, 8);
+ emit_csrrw_imm64(program, 1, CSR_MTVEC, MACHINE_TRAP_VECTOR);
+ emit_nops(program, 8);
+ emit_load_imm64(program, 3, load_addr);
+ program.push_back(LD(5, 3, 0));
+ program.push_back(JAL(0, -4));
+
+ sim.mem.load_program(boot_pc, program);
+ sim.reset();
+ sim.run(80);
+ ASSERT_EQ(sim.mem.read_data(MACHINE_LOG_PTR_ADDR), log_base + LOG_ENTRY_STRIDE, "machine log pointer advanced");
+
+ const TrapRecord load_trap = fetch_trap_record(sim.mem, log_base, 0);
+ ASSERT_EQ(load_trap.mcause, EXC_LOAD_FAULT, "load fault cause code");
+ ASSERT_EQ(load_trap.mtval, load_addr, "load fault address latched");
+ ASSERT_EQ(sim.mem.read_data(store_addr & ~0x7ULL), 0ULL, "misaligned store suppressed");
+}
+
+static void run_double_exception_flush_case() {
+ std::cout << "[CASE] double_exception_flush" << std::endl;
+ CoreSim sim;
+ install_trap_handlers(sim.mem);
+
+ const uint64_t boot_pc = 0x80000000ULL;
+ const uint64_t log_base = 0x0000000000009100ULL;
+ sim.mem.write_data(MACHINE_LOG_PTR_ADDR, log_base);
+ std::vector<uint32_t> program;
+ emit_nops(program, 8);
+ emit_csrrw_imm64(program, 1, CSR_MTVEC, MACHINE_TRAP_VECTOR);
+ emit_nops(program, 8);
+ program.push_back(ILLEGAL());
+ program.push_back(NOP());
+ program.push_back(JAL(0, -4));
+
+ sim.mem.load_program(boot_pc, program);
+ sim.reset();
+ sim.run(80);
+
+ const TrapRecord illegal_trap = fetch_trap_record(sim.mem, log_base, 0);
+ ASSERT_EQ(illegal_trap.mcause, EXC_INST_ILLEGAL, "first cause illegal");
+ ASSERT_EQ(sim.mem.read_data(MACHINE_LOG_PTR_ADDR), log_base + LOG_ENTRY_STRIDE, "single trap logged");
+}
+
+static void run_mret_sret_redirect_case() {
+ std::cout << "[CASE] mret_sret_redirect" << std::endl;
+ CoreSim sim;
+ install_trap_handlers(sim.mem);
+
+ const uint64_t boot_pc = 0x80000000ULL;
+ const uint64_t m_log_base = 0x0000000000009200ULL;
+ const uint64_t post_store_addr = 0x0000000000009400ULL;
+ const uint64_t post_trap_addr = 0x0000000000009408ULL;
+ sim.mem.write_data(MACHINE_LOG_PTR_ADDR, m_log_base);
+
+ std::vector<uint32_t> boot;
+ emit_nops(boot, 8);
+ emit_csrrw_imm64(boot, 1, CSR_MTVEC, MACHINE_TRAP_VECTOR);
+ emit_nops(boot, 8);
+ emit_load_imm64(boot, 11, post_store_addr);
+ emit_load_imm64(boot, 12, 0xCAFECAFEULL);
+ boot.push_back(SD(12, 11, 0));
+ boot.push_back(ECALL());
+ emit_load_imm64(boot, 13, post_trap_addr);
+ emit_load_imm64(boot, 14, 0xBEEFBEEFULL);
+ boot.push_back(SD(14, 13, 0));
+ boot.push_back(JAL(0, 0));
+ sim.mem.load_program(boot_pc, boot);
+
+ sim.reset();
+ sim.run(300);
+
+ const TrapRecord m_trap = fetch_trap_record(sim.mem, m_log_base, 0);
+ ASSERT_EQ(m_trap.mcause, EXC_ECALL_FROM_M, "ecall from machine traps to machine");
+ ASSERT_EQ(sim.mem.read_data(post_store_addr), 0xFFFFFFFFCAFECAFEULL, "post-trap store committed once");
+}
+
+static void run_branch_interrupt_priority_case() {
+ std::cout << "[CASE] branch_interrupt_priority" << std::endl;
+ CoreSim sim;
+ install_trap_handlers(sim.mem);
+
+ const uint64_t boot_pc = 0x80000000ULL;
+ const uint64_t log_base = 0x0000000000009600ULL;
+ sim.mem.write_data(MACHINE_LOG_PTR_ADDR, log_base);
+
+ std::vector<uint32_t> boot;
+ emit_nops(boot, 8);
+ emit_csrrw_imm64(boot, 1, CSR_MTVEC, MACHINE_TRAP_VECTOR);
+ emit_csrrw_imm64(boot, 2, CSR_MSTATUS, (1ULL << MSTATUS_MIE_BIT));
+ emit_csrrw_imm64(boot, 3, CSR_MIE, (1ULL << INT_M_EXTERNAL));
+ boot.push_back(JAL(0, 0));
+ sim.mem.load_program(boot_pc, boot);
+
+ sim.reset();
+ sim.run(10);
+ sim.set_interrupt_lines(false, false, true);
+ sim.run(40);
+ sim.clear_interrupts();
+ sim.run(20);
+
+ const TrapRecord interrupt_trap = fetch_trap_record(sim.mem, log_base, 0);
+ ASSERT_EQ(interrupt_trap.mcause, INTERRUPT_BIT | INT_M_EXTERNAL, "external interrupt cause");
+ ASSERT_EQ(interrupt_trap.mtval, 0ULL, "interrupt mtval should be zero");
+}
+
+static void run_mie_masking_case() {
+ std::cout << "[CASE] mie_masking_response" << std::endl;
+ CoreSim sim;
+ install_trap_handlers(sim.mem);
+
+ const uint64_t boot_pc = 0x80000000ULL;
+ const uint64_t log_base = 0x0000000000009700ULL;
+ sim.mem.write_data(MACHINE_LOG_PTR_ADDR, log_base);
+ for (int i = 0; i < 3; ++i) {
+ sim.mem.write_data(log_base + static_cast<uint64_t>(i) * 8ULL, 0ULL);
+ }
+
+ std::vector<uint32_t> program;
+ emit_nops(program, 8);
+ emit_csrrw_imm64(program, 1, CSR_MTVEC, MACHINE_TRAP_VECTOR);
+ emit_csrrw_imm64(program, 2, CSR_MIE, (1ULL << INT_M_EXTERNAL));
+ program.push_back(CSRRW(0, CSR_MSTATUS, 0));
+ emit_nops(program, 8);
+ emit_nops(program, 48);
+ emit_csrrw_imm64(program, 4, CSR_MSTATUS, (1ULL << MSTATUS_MIE_BIT));
+ program.push_back(JAL(0, 0));
+
+ sim.mem.load_program(boot_pc, program);
+ sim.reset();
+
+ sim.set_interrupt_lines(false, false, true);
+ sim.run(20);
+ ASSERT_EQ(sim.mem.read_data(log_base), 0ULL, "no trap while MIE=0");
+ sim.run(100);
+ const TrapRecord int_trap = fetch_trap_record(sim.mem, log_base, 0);
+ ASSERT_EQ(int_trap.mcause, INTERRUPT_BIT | INT_M_EXTERNAL, "external interrupt cause");
+}
+
+// TODO: Add EXPECT_FAIL once trap_load_page_fault/trap_store_page_fault are driven by the MMU.
+
+struct CaseDispatchEntry {
+ const char* name;
+ void (*fn)();
+};
+
+static const CaseDispatchEntry kCaseDispatchTable[] = {
+ {"mem_fault_pipeline", run_mem_fault_pipeline_case},
+ {"double_exception_flush", run_double_exception_flush_case},
+ {"mret_sret_redirect", run_mret_sret_redirect_case},
+ {"branch_interrupt_priority", run_branch_interrupt_priority_case},
+ {"mie_masking_response", run_mie_masking_case}
+};
+
+// ═══════════════════════════════════════════════════════════════
// Main
// ═══════════════════════════════════════════════════════════════
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
+ std::string requested_case;
+ for (int i = 1; i < argc; ++i) {
+ if (std::string(argv[i]) == "--case" && (i + 1) < argc) {
+ requested_case = argv[++i];
+ }
+ }
+
+ if (!requested_case.empty()) {
+ const auto* entry = std::find_if(
+ std::begin(kCaseDispatchTable),
+ std::end(kCaseDispatchTable),
+ [&](const CaseDispatchEntry& item) { return requested_case == item.name; }
+ );
+ if (entry == std::end(kCaseDispatchTable)) {
+ std::cerr << "Unknown --case value: " << requested_case << std::endl;
+ return 2;
+ }
+ entry->fn();
+ std::cout << "================================================================" << std::endl;
+ std::cout << " Results: " << g_pass_count << "/" << g_test_count << " assertions passed" << std::endl;
+ std::cout << "================================================================" << std::endl;
+ return (g_pass_count == g_test_count) ? 0 : 1;
+ }
+
std::cout << "================================================================" << std::endl;
std::cout << " Richard CPU Core Integration Test" << std::endl;
std::cout << "================================================================" << std::endl;
- // Each test gets a fresh instance
{
CoreSim sim;
test_reset(sim);
@@ -689,12 +1095,17 @@ int main(int argc, char** argv) {
CoreSim sim;
test_reset_mid_execution(sim);
}
-
{
CoreSim sim;
test_fibonacci(sim);
}
+ run_mem_fault_pipeline_case();
+ run_double_exception_flush_case();
+ run_mret_sret_redirect_case();
+ run_branch_interrupt_priority_case();
+ run_mie_masking_case();
+
std::cout << "================================================================" << std::endl;
std::cout << " Results: " << g_pass_count << "/" << g_test_count << " assertions passed" << std::endl;
std::cout << "================================================================" << std::endl;
@@ -702,8 +1113,8 @@ int main(int argc, char** argv) {
if (g_pass_count == g_test_count) {
std::cout << " ALL TESTS PASSED" << std::endl;
return 0;
- } else {
- std::cout << " SOME TESTS FAILED" << std::endl;
- return 1;
}
+
+ std::cout << " SOME TESTS FAILED" << std::endl;
+ return 1;
}