aboutsummaryrefslogtreecommitdiff
path: root/rv64cpu/tb/compliance
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-07 03:30:17 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-07 03:31:03 +0800
commit2a4c290c55b683352a16747432a7fc4635597cc6 (patch)
treea150caea2ade12af4c5dcd70f09bacd3318f4d43 /rv64cpu/tb/compliance
parente0948e3fc10029ba4bb4d48d7b5daae94fe575b9 (diff)
downloadrcc-project-2a4c290c55b683352a16747432a7fc4635597cc6.tar.gz
rcc-project-2a4c290c55b683352a16747432a7fc4635597cc6.tar.xz
refactor: reset software and test directories
Diffstat (limited to 'rv64cpu/tb/compliance')
-rw-r--r--rv64cpu/tb/compliance/CMakeLists.txt60
-rw-r--r--rv64cpu/tb/compliance/compliance_runner.cc634
2 files changed, 0 insertions, 694 deletions
diff --git a/rv64cpu/tb/compliance/CMakeLists.txt b/rv64cpu/tb/compliance/CMakeLists.txt
deleted file mode 100644
index 677cae6..0000000
--- a/rv64cpu/tb/compliance/CMakeLists.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-# ─── Compliance Test CMake ───────────────────────────────────────────────────────
-#
-# Builds the compliance test runner and registers riscv-arch-test tests.
-#
-# ─────────────────────────────────────────────────────────────────────────────────
-
-# Minimal compliance runner target (core-only for bootstrap stage).
-# NOTE: This uses richard_core until SoC top and memory/peripheral harness are ready.
-add_verilator_target(
- NAME compliance_runner
- TOP_MODULE richard_core
- SOURCES ${RTL_CORE_DIR}/include/rv64_pkg.sv
- ${RTL_CORE_DIR}/alu.sv
- ${RTL_CORE_DIR}/branch_unit.sv
- ${RTL_CORE_DIR}/compressed_decoder.sv
- ${RTL_CORE_DIR}/decoder.sv
- ${RTL_CORE_DIR}/regfile.sv
- ${RTL_CORE_DIR}/fp_regfile.sv
- ${RTL_CORE_DIR}/if_stage.sv
- ${RTL_CORE_DIR}/if_id_reg.sv
- ${RTL_CORE_DIR}/id_stage.sv
- ${RTL_CORE_DIR}/id_ex_reg.sv
- ${RTL_CORE_DIR}/ex_stage.sv
- ${RTL_CORE_DIR}/fpu/fpu_unit.sv
- ${RTL_CORE_DIR}/ex_mem_reg.sv
- ${RTL_CORE_DIR}/mem_stage.sv
- ${RTL_CORE_DIR}/mem_wb_reg.sv
- ${RTL_CORE_DIR}/wb_stage.sv
- ${RTL_CORE_DIR}/hazard_unit.sv
- ${RTL_CORE_DIR}/include/csr_pkg.sv
- ${RTL_CORE_DIR}/csr_unit.sv
- ${RTL_CORE_DIR}/pmp_checker.sv
- ${RTL_CORE_DIR}/mmu/tlb.sv
- ${RTL_CORE_DIR}/mmu/ptw.sv
- ${RTL_CORE_DIR}/mmu/mmu_top.sv
- ${RTL_CORE_DIR}/trap_ctrl.sv
- ${RTL_CORE_DIR}/richard_core.sv
- INCLUDE_DIRS ${RTL_COMMON_INCLUDES}
- TB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/compliance_runner.cc
- EXTRA_FLAGS -Wno-PINCONNECTEMPTY
-)
-
-# ─── Register individual compliance tests via CTest ──────────────────────────────
-# This is done dynamically by the compliance_runner binary and run_compliance.py.
-# You can also manually register tests like:
-#
-# set(RISCV_ARCH_TEST_DIR ${CMAKE_SOURCE_DIR}/sw/riscv-arch-test)
-#
-# file(GLOB RV64I_TESTS ${RISCV_ARCH_TEST_DIR}/riscv-test-suite/rv64i_m/I/src/*.S)
-# foreach(test_src ${RV64I_TESTS})
-# get_filename_component(test_name ${test_src} NAME_WE)
-# add_test(
-# NAME compliance_rv64i_${test_name}
-# COMMAND compliance_runner --test ${test_src}
-# )
-# set_tests_properties(compliance_rv64i_${test_name} PROPERTIES
-# LABELS "compliance;rv64i"
-# TIMEOUT 30
-# )
-# endforeach()
diff --git a/rv64cpu/tb/compliance/compliance_runner.cc b/rv64cpu/tb/compliance/compliance_runner.cc
deleted file mode 100644
index ba52647..0000000
--- a/rv64cpu/tb/compliance/compliance_runner.cc
+++ /dev/null
@@ -1,634 +0,0 @@
-// Richard CPU
-// Copyright (C) 2026 Richard Qin
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-//
-// File path: tb/compliance/compliance_runner.cc
-// Minimal compliance runner bootstrap.
-// This runner intentionally keeps behavior simple so the toolchain flow can be
-// integrated first, then replaced with full ELF/signature handling.
-
-#include <cinttypes>
-#include <cstdint>
-#include <cstring>
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <string>
-#include <sstream>
-#include <vector>
-#include <verilated.h>
-
-#include "Vrichard_core.h"
-#include "Vrichard_core___024root.h"
-
-namespace {
-
-struct Options {
- uint64_t max_cycles = 2000;
- std::string elf_path;
- std::string signature_path;
- uint64_t trace_pc_count = 0;
- bool show_help = false;
-};
-
-struct Symbols {
- uint64_t begin_signature = 0;
- uint64_t end_signature = 0;
- uint64_t tohost = 0;
-};
-
-class ByteMemory {
-public:
- static constexpr uint64_t UART_THR = 0x10000000ULL;
- static constexpr uint64_t UART_LSR = 0x10000005ULL;
- static constexpr uint64_t CLINT_MTIME = 0x0200BFF8ULL;
-
- void write_byte(uint64_t addr, uint8_t value) {
- if (addr == UART_THR) {
- return;
- }
- mem_[addr] = value;
- }
-
- uint8_t read_byte(uint64_t addr) const {
- if (addr == UART_LSR) {
- return 0x20;
- }
- auto it = mem_.find(addr);
- if (it == mem_.end()) {
- return 0;
- }
- return it->second;
- }
-
- uint32_t read_u32(uint64_t addr) const {
- uint32_t value = 0;
- for (int i = 0; i < 4; ++i) {
- value |= static_cast<uint32_t>(read_byte(addr + i)) << (8 * i);
- }
- return value;
- }
-
- uint64_t read_u64(uint64_t addr) const {
- uint64_t value = 0;
- for (int i = 0; i < 8; ++i) {
- value |= static_cast<uint64_t>(read_byte(addr + i)) << (8 * i);
- }
- return value;
- }
-
- void write_store(uint64_t addr, uint64_t wdata, uint8_t size_code) {
- uint64_t bytes = 0;
- switch (size_code) {
- case 0b000:
- case 0b100:
- bytes = 1;
- break;
- case 0b001:
- case 0b101:
- bytes = 2;
- break;
- case 0b010:
- case 0b110:
- bytes = 4;
- break;
- case 0b011:
- default:
- bytes = 8;
- break;
- }
-
- const uint64_t offset = addr & 0x7ULL;
- const uint64_t aligned = addr & ~0x7ULL;
- for (uint64_t i = 0; i < bytes; ++i) {
- const uint64_t lane = offset + i;
- const uint8_t byte_value = static_cast<uint8_t>((wdata >> (lane * 8)) & 0xFFULL);
- write_byte(aligned + lane, byte_value);
- }
- }
-
-private:
- std::map<uint64_t, uint8_t> mem_;
-};
-
-#pragma pack(push, 1)
-struct Elf64Ehdr {
- unsigned char e_ident[16];
- uint16_t e_type;
- uint16_t e_machine;
- uint32_t e_version;
- uint64_t e_entry;
- uint64_t e_phoff;
- uint64_t e_shoff;
- uint32_t e_flags;
- uint16_t e_ehsize;
- uint16_t e_phentsize;
- uint16_t e_phnum;
- uint16_t e_shentsize;
- uint16_t e_shnum;
- uint16_t e_shstrndx;
-};
-
-struct Elf64Phdr {
- uint32_t p_type;
- uint32_t p_flags;
- uint64_t p_offset;
- uint64_t p_vaddr;
- uint64_t p_paddr;
- uint64_t p_filesz;
- uint64_t p_memsz;
- uint64_t p_align;
-};
-
-struct Elf64Shdr {
- uint32_t sh_name;
- uint32_t sh_type;
- uint64_t sh_flags;
- uint64_t sh_addr;
- uint64_t sh_offset;
- uint64_t sh_size;
- uint32_t sh_link;
- uint32_t sh_info;
- uint64_t sh_addralign;
- uint64_t sh_entsize;
-};
-
-struct Elf64Sym {
- uint32_t st_name;
- unsigned char st_info;
- unsigned char st_other;
- uint16_t st_shndx;
- uint64_t st_value;
- uint64_t st_size;
-};
-#pragma pack(pop)
-
-constexpr uint32_t PT_LOAD = 1;
-constexpr uint32_t SHT_SYMTAB = 2;
-
-Options parse_args(int argc, char** argv) {
- Options opts;
- for (int i = 1; i < argc; ++i) {
- const std::string arg = argv[i];
- if (arg == "--help" || arg == "-h") {
- opts.show_help = true;
- continue;
- }
- if (arg == "--max-cycles" && (i + 1) < argc) {
- opts.max_cycles = static_cast<uint64_t>(std::stoull(argv[++i]));
- continue;
- }
- if (arg == "--elf" && (i + 1) < argc) {
- opts.elf_path = argv[++i];
- continue;
- }
- if (arg == "--signature" && (i + 1) < argc) {
- opts.signature_path = argv[++i];
- continue;
- }
- if (arg == "--trace-pc" && (i + 1) < argc) {
- opts.trace_pc_count = static_cast<uint64_t>(std::stoull(argv[++i]));
- continue;
- }
- }
- return opts;
-}
-
-void print_help() {
- std::cout
- << "compliance_runner (bootstrap)\n"
- << "Usage:\n"
- << " compliance_runner --elf PATH [--max-cycles N] [--signature PATH] [--trace-pc N]\n";
-}
-
-std::string hex64(uint64_t value) {
- std::ostringstream out;
- out << "0x" << std::hex << std::setfill('0') << std::setw(16) << value;
- return out.str();
-}
-
-void dump_selected_gprs(const Vrichard_core* top, const char* prefix) {
- const auto& regs = top->rootp->richard_core__DOT__u_id_stage__DOT__u_regfile__DOT__regs;
- std::cerr << prefix << ": selected GPRs\n"
- << " x2/sp=" << hex64(regs[2])
- << " x3/gp=" << hex64(regs[3])
- << " x4/tp=" << hex64(regs[4])
- << " x5/t0=" << hex64(regs[5]) << "\n"
- << " x6/t1=" << hex64(regs[6])
- << " x7/t2=" << hex64(regs[7])
- << " x8/s0=" << hex64(regs[8])
- << " x9/s1=" << hex64(regs[9]) << "\n"
- << " x10/a0=" << hex64(regs[10])
- << " x11/a1=" << hex64(regs[11])
- << " x20/s4=" << hex64(regs[20])
- << " x21/s5=" << hex64(regs[21]) << "\n";
- std::cerr << " mstatus=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mstatus_reg)
- << " sstatus=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sstatus_reg)
- << " mcause=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mcause_reg)
- << " mepc=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mepc_reg)
- << "\n";
- std::cerr << " priv=" << static_cast<unsigned>(top->rootp->richard_core__DOT__u_csr_unit__DOT__priv_mode_q)
- << " medeleg=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__medeleg_reg)
- << " mideleg=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mideleg_reg)
- << " mtvec=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mtvec_reg)
- << " stvec=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__stvec_reg)
- << "\n";
- std::cerr << " mstateen0=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mstateen_reg[0])
- << " sstateen0=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sstateen_reg[0])
- << " menvcfg=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__menvcfg_reg)
- << " senvcfg=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__senvcfg_reg)
- << "\n";
-}
-
-bool load_elf64(const std::string& path, ByteMemory* memory, Symbols* symbols) {
- std::ifstream in(path, std::ios::binary);
- if (!in) {
- std::cerr << "Failed to open ELF: " << path << "\n";
- return false;
- }
-
- in.seekg(0, std::ios::end);
- const std::streamsize size = in.tellg();
- in.seekg(0, std::ios::beg);
- if (size <= 0) {
- std::cerr << "Empty ELF file: " << path << "\n";
- return false;
- }
-
- std::vector<uint8_t> data(static_cast<size_t>(size));
- in.read(reinterpret_cast<char*>(data.data()), size);
- if (!in) {
- std::cerr << "Failed to read ELF contents: " << path << "\n";
- return false;
- }
-
- if (data.size() < sizeof(Elf64Ehdr)) {
- std::cerr << "ELF too small: " << path << "\n";
- return false;
- }
-
- const auto* ehdr = reinterpret_cast<const Elf64Ehdr*>(data.data());
- if (!(ehdr->e_ident[0] == 0x7F && ehdr->e_ident[1] == 'E' && ehdr->e_ident[2] == 'L' && ehdr->e_ident[3] == 'F')) {
- std::cerr << "Invalid ELF magic: " << path << "\n";
- return false;
- }
- if (ehdr->e_ident[4] != 2 || ehdr->e_ident[5] != 1) {
- std::cerr << "Only ELF64 little-endian is supported: " << path << "\n";
- return false;
- }
-
- const uint64_t ph_end = ehdr->e_phoff + static_cast<uint64_t>(ehdr->e_phnum) * ehdr->e_phentsize;
- if (ph_end > data.size()) {
- std::cerr << "Program header table out of range\n";
- return false;
- }
-
- for (uint16_t i = 0; i < ehdr->e_phnum; ++i) {
- const uint64_t off = ehdr->e_phoff + static_cast<uint64_t>(i) * ehdr->e_phentsize;
- const auto* phdr = reinterpret_cast<const Elf64Phdr*>(data.data() + off);
- if (phdr->p_type != PT_LOAD) {
- continue;
- }
- if (phdr->p_offset + phdr->p_filesz > data.size()) {
- std::cerr << "LOAD segment out of range\n";
- return false;
- }
-
- const uint64_t base = (phdr->p_paddr != 0) ? phdr->p_paddr : phdr->p_vaddr;
- for (uint64_t j = 0; j < phdr->p_filesz; ++j) {
- memory->write_byte(base + j, data[phdr->p_offset + j]);
- }
- for (uint64_t j = phdr->p_filesz; j < phdr->p_memsz; ++j) {
- memory->write_byte(base + j, 0);
- }
- }
-
- const uint64_t sh_end = ehdr->e_shoff + static_cast<uint64_t>(ehdr->e_shnum) * ehdr->e_shentsize;
- if (ehdr->e_shoff == 0 || ehdr->e_shnum == 0 || sh_end > data.size()) {
- return true;
- }
-
- for (uint16_t i = 0; i < ehdr->e_shnum; ++i) {
- const uint64_t off = ehdr->e_shoff + static_cast<uint64_t>(i) * ehdr->e_shentsize;
- const auto* shdr = reinterpret_cast<const Elf64Shdr*>(data.data() + off);
- if (shdr->sh_type != SHT_SYMTAB || shdr->sh_entsize == 0) {
- continue;
- }
- if (shdr->sh_offset + shdr->sh_size > data.size() || shdr->sh_link >= ehdr->e_shnum) {
- continue;
- }
-
- const uint64_t str_off = ehdr->e_shoff + static_cast<uint64_t>(shdr->sh_link) * ehdr->e_shentsize;
- const auto* str_shdr = reinterpret_cast<const Elf64Shdr*>(data.data() + str_off);
- if (str_shdr->sh_offset + str_shdr->sh_size > data.size()) {
- continue;
- }
-
- const char* strtab = reinterpret_cast<const char*>(data.data() + str_shdr->sh_offset);
- const uint64_t sym_count = shdr->sh_size / shdr->sh_entsize;
- for (uint64_t s = 0; s < sym_count; ++s) {
- const uint64_t sym_off = shdr->sh_offset + s * shdr->sh_entsize;
- const auto* sym = reinterpret_cast<const Elf64Sym*>(data.data() + sym_off);
- if (sym->st_name >= str_shdr->sh_size) {
- continue;
- }
- const std::string name(strtab + sym->st_name);
- if (name == "begin_signature") {
- symbols->begin_signature = sym->st_value;
- } else if (name == "end_signature") {
- symbols->end_signature = sym->st_value;
- } else if (name == "tohost") {
- symbols->tohost = sym->st_value;
- }
- }
- }
-
- return true;
-}
-
-void drive_memory_response(Vrichard_core* top, ByteMemory* memory) {
- top->imem_rdata = memory->read_u32(top->imem_addr);
- top->dmem_rdata = top->dmem_read_en ? memory->read_u64(top->dmem_addr & ~0x7ULL) : 0;
-}
-
-void tick(Vrichard_core* top, ByteMemory* memory) {
- drive_memory_response(top, memory);
- top->m_timer_interrupt = 0;
- top->m_software_interrupt = 0;
- top->m_external_interrupt = 0;
- top->s_timer_interrupt = 0;
- top->s_software_interrupt = 0;
- top->s_external_interrupt = 0;
-
- top->clk = 0;
- top->eval();
- drive_memory_response(top, memory);
- top->eval();
- top->clk = 1;
- top->eval();
-
- if (top->dmem_write_en) {
- memory->write_store(top->dmem_addr, top->dmem_wdata, top->dmem_size);
- if ((top->dmem_addr <= ByteMemory::CLINT_MTIME + 7ULL) &&
- (top->dmem_addr + 7ULL >= ByteMemory::CLINT_MTIME)) {
- top->rootp->richard_core__DOT__u_csr_unit__DOT__time_reg =
- memory->read_u64(ByteMemory::CLINT_MTIME);
- }
- }
-}
-
-void dump_signature(const ByteMemory& memory, const Symbols& symbols, const std::string& signature_path) {
- if (signature_path.empty()) {
- return;
- }
-
- std::ofstream sig(signature_path);
- if (!sig) {
- std::cerr << "Failed to open signature file for writing: " << signature_path << "\n";
- return;
- }
-
- if (symbols.begin_signature == 0 || symbols.end_signature <= symbols.begin_signature) {
- sig << "00000000\n";
- return;
- }
-
- const uint64_t bytes = symbols.end_signature - symbols.begin_signature;
- for (uint64_t off = 0; off + 8 <= bytes; off += 8) {
- const uint64_t value = memory.read_u64(symbols.begin_signature + off);
- sig << std::hex << std::setfill('0') << std::setw(16) << value << "\n";
- }
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- Verilated::commandArgs(argc, argv);
- const Options opts = parse_args(argc, argv);
-
- if (opts.show_help) {
- print_help();
- return 0;
- }
- if (opts.elf_path.empty()) {
- // Keep compatibility with CTest smoke invocation that runs the binary
- // without arguments to validate toolchain/linking only.
- std::cout << "compliance_runner: no --elf provided, smoke mode pass\n";
- return 0;
- }
-
- auto* top = new Vrichard_core;
- ByteMemory memory;
- Symbols symbols;
-
- if (!load_elf64(opts.elf_path, &memory, &symbols)) {
- delete top;
- return 2;
- }
-
- top->rst = 1;
- for (int i = 0; i < 5; ++i) {
- tick(top, &memory);
- }
- top->rst = 0;
-
- bool saw_tohost = false;
- bool test_pass = false;
- uint64_t store_trace_printed = 0;
- uint64_t read_trace_printed = 0;
- uint64_t wb_trace_printed = 0;
- uint64_t trap_trace_printed = 0;
- std::string uart_trace;
- std::vector<uint64_t> pc_trace;
- if (opts.trace_pc_count != 0) {
- pc_trace.reserve(static_cast<size_t>(opts.trace_pc_count));
- }
-
- for (uint64_t i = 0; i < opts.max_cycles; ++i) {
- if (opts.trace_pc_count != 0) {
- if (pc_trace.size() == opts.trace_pc_count) {
- pc_trace.erase(pc_trace.begin());
- }
- pc_trace.push_back(top->imem_addr);
- }
- tick(top, &memory);
- if (opts.trace_pc_count != 0 &&
- top->dmem_read_en &&
- (top->dmem_addr >= 0x000000008004cd20ULL) &&
- (top->dmem_addr < 0x000000008004cd40ULL) &&
- read_trace_printed < 32) {
- std::cerr << "load cycle=" << i
- << " pc=" << hex64(top->imem_addr)
- << " addr=" << hex64(top->dmem_addr)
- << " rdata=" << hex64(top->dmem_rdata)
- << " size=" << static_cast<unsigned>(top->dmem_size)
- << "\n";
- ++read_trace_printed;
- }
- if (opts.trace_pc_count != 0 && top->dmem_write_en && top->dmem_addr == ByteMemory::UART_THR) {
- uart_trace.push_back(static_cast<char>(top->dmem_wdata & 0xFFULL));
- }
- if (opts.trace_pc_count != 0 &&
- top->dmem_write_en &&
- top->dmem_addr >= 0x00000000800115e0ULL &&
- top->dmem_addr < 0x0000000080011608ULL) {
- std::cerr << "scratch-store cycle=" << i
- << " pc=" << hex64(top->imem_addr)
- << " addr=" << hex64(top->dmem_addr)
- << " data=" << hex64(top->dmem_wdata)
- << " size=" << static_cast<unsigned>(top->dmem_size)
- << "\n";
- }
- if (opts.trace_pc_count != 0 &&
- top->rootp->richard_core__DOT__csr_req &&
- (((top->rootp->richard_core__DOT__wb_instr_in >> 20) & 0xFFFU) == 0x341 ||
- ((top->rootp->richard_core__DOT__wb_instr_in >> 20) & 0xFFFU) == 0x141 ||
- ((top->rootp->richard_core__DOT__wb_instr_in >> 20) & 0xFFFU) == 0x300 ||
- ((top->rootp->richard_core__DOT__wb_instr_in >> 20) & 0xFFFU) == 0x100)) {
- std::cerr << "csr cycle=" << i
- << " pc=" << hex64(top->rootp->richard_core__DOT__wb_pc_in)
- << " addr=0x" << std::hex << std::setw(3) << std::setfill('0')
- << ((top->rootp->richard_core__DOT__wb_instr_in >> 20) & 0xFFFU)
- << " op=" << std::dec
- << static_cast<unsigned>((top->rootp->richard_core__DOT__wb_instr_in >> 12) & 0x7U)
- << " rs1=" << hex64(top->rootp->richard_core__DOT__csr_rs1_data)
- << " mepc_old=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mepc_reg)
- << " sepc_old=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sepc_reg)
- << " instr=0x" << std::hex << std::setw(8) << std::setfill('0')
- << top->rootp->richard_core__DOT__wb_instr_in
- << std::dec << std::setfill(' ') << "\n";
- }
- if (opts.trace_pc_count != 0 &&
- (top->rootp->richard_core__DOT__trap_ctrl_mret_en ||
- top->rootp->richard_core__DOT__trap_ctrl_sret_en)) {
- std::cerr << "xret cycle=" << i
- << " pc=" << hex64(top->rootp->richard_core__DOT__wb_pc_in)
- << " mret=" << static_cast<unsigned>(top->rootp->richard_core__DOT__trap_ctrl_mret_en)
- << " sret=" << static_cast<unsigned>(top->rootp->richard_core__DOT__trap_ctrl_sret_en)
- << " target=" << hex64(top->rootp->richard_core__DOT__hu_pc_redirect_target)
- << " mepc=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mepc_reg)
- << " sepc=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sepc_reg)
- << "\n";
- }
- if (opts.trace_pc_count != 0 &&
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000e1b4ULL &&
- trap_trace_printed < 128) {
- const auto& regs = top->rootp->richard_core__DOT__u_id_stage__DOT__u_regfile__DOT__regs;
- const uint64_t sig_ptr = regs[6];
- std::cerr << "trap-check cycle=" << i
- << " t1=" << hex64(sig_ptr)
- << " cause=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mcause_reg)
- << " mepc=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__mepc_reg)
- << " stored_msig=" << hex64(memory.read_u64(0x00000000800115f0ULL))
- << " exp_status=" << hex64(memory.read_u64(sig_ptr))
- << " exp_cause=" << hex64(memory.read_u64(sig_ptr + 8))
- << " exp_epc=" << hex64(memory.read_u64(sig_ptr + 16))
- << "\n";
- ++trap_trace_printed;
- }
- if (opts.trace_pc_count != 0 &&
- (top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000eb84ULL ||
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000eb88ULL ||
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000ebc8ULL ||
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000ebccULL ||
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000ebecULL ||
- top->rootp->richard_core__DOT__wb_pc_in == 0x000000008000ec60ULL) &&
- trap_trace_printed < 256) {
- const auto& regs = top->rootp->richard_core__DOT__u_id_stage__DOT__u_regfile__DOT__regs;
- std::cerr << "strap-debug cycle=" << i
- << " pc=" << hex64(top->rootp->richard_core__DOT__wb_pc_in)
- << " sp=" << hex64(regs[2])
- << " t1=" << hex64(regs[6])
- << " t2=" << hex64(regs[7])
- << " s0=" << hex64(regs[8])
- << " s1=" << hex64(regs[9])
- << " a0=" << hex64(regs[10])
- << " a1=" << hex64(regs[11])
- << " sscratch=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sscratch_reg)
- << " scause=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__scause_reg)
- << " sepc=" << hex64(top->rootp->richard_core__DOT__u_csr_unit__DOT__sepc_reg)
- << " mem[Strap_sig]=" << hex64(memory.read_u64(0x00000000800115f0ULL))
- << " mem[Ssig_bgn]=" << hex64(memory.read_u64(0x00000000800115d0ULL))
- << " mem[Sbase]=" << hex64(memory.read_u64(0x00000000800115b0ULL))
- << "\n";
- ++trap_trace_printed;
- }
- if (opts.trace_pc_count != 0 &&
- top->rootp->richard_core__DOT__wb_reg_write_en_out &&
- (top->rootp->richard_core__DOT__wb_rd_addr_in == 8 ||
- top->rootp->richard_core__DOT__wb_rd_addr_in == 4 ||
- top->rootp->richard_core__DOT__wb_rd_addr_in == 13 ||
- top->rootp->richard_core__DOT__wb_rd_addr_in == 20) &&
- wb_trace_printed < 64) {
- std::cerr << "wb cycle=" << i
- << " pc=" << hex64(top->rootp->richard_core__DOT__wb_pc_in)
- << " rd=x" << static_cast<unsigned>(top->rootp->richard_core__DOT__wb_rd_addr_in)
- << " data=" << hex64(top->rootp->richard_core__DOT__wb_rd_wdata)
- << " instr=0x" << std::hex << std::setw(8) << std::setfill('0')
- << top->rootp->richard_core__DOT__wb_instr_in
- << std::dec << std::setfill(' ') << "\n";
- ++wb_trace_printed;
- }
- if (top->dmem_write_en && symbols.tohost != 0) {
- const uint64_t addr = top->dmem_addr;
- if (opts.trace_pc_count != 0 && store_trace_printed < 128) {
- std::cerr << "store cycle=" << i
- << " pc=" << hex64(top->imem_addr)
- << " addr=" << hex64(addr)
- << " data=" << hex64(top->dmem_wdata)
- << " size=" << static_cast<unsigned>(top->dmem_size)
- << "\n";
- ++store_trace_printed;
- }
- const bool overlaps_tohost = (addr <= symbols.tohost + 3ULL) && (addr + 7ULL >= symbols.tohost);
- if (overlaps_tohost) {
- const uint32_t status = static_cast<uint32_t>(memory.read_u64(symbols.tohost) & 0xFFFFFFFFULL);
- if (status == 1U) {
- saw_tohost = true;
- test_pass = true;
- break;
- }
- if (status == 3U) {
- saw_tohost = true;
- test_pass = false;
- break;
- }
- }
- }
- }
-
- dump_signature(memory, symbols, opts.signature_path);
-
- if (opts.trace_pc_count != 0 && !uart_trace.empty()) {
- std::cerr << "uart output:\n" << uart_trace << "\n";
- }
- if (!saw_tohost) {
- if (!pc_trace.empty()) {
- std::cerr << "timeout: last " << pc_trace.size() << " fetch PCs\n";
- for (uint64_t pc : pc_trace) {
- std::cerr << " " << hex64(pc) << "\n";
- }
- dump_selected_gprs(top, "timeout");
- }
- delete top;
- return 3;
- }
- if (opts.trace_pc_count != 0 && !test_pass) {
- dump_selected_gprs(top, "fail");
- }
- delete top;
- return test_pass ? 0 : 1;
-}