Merge pull request #1450 from tianrui-wei/cospike-rebase
misc: many fixes to cospike
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <riscv/sim.h>
|
||||
@@ -5,6 +6,12 @@
|
||||
#include <svdpi.h>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if __has_include ("cospike_dtm.h")
|
||||
#define COSPIKE_DTM
|
||||
@@ -27,6 +34,7 @@ typedef struct system_info_t {
|
||||
|
||||
system_info_t* info = NULL;
|
||||
sim_t* sim = NULL;
|
||||
bool cospike_debug;
|
||||
reg_t tohost_addr = 0;
|
||||
reg_t fromhost_addr = 0;
|
||||
std::set<reg_t> magic_addrs;
|
||||
@@ -72,10 +80,10 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
int raise_interrupt,
|
||||
unsigned long long int cause,
|
||||
unsigned long long int wdata,
|
||||
int priv)
|
||||
int priv)
|
||||
{
|
||||
assert(info);
|
||||
if (!sim) {
|
||||
if (unlikely(!sim)) {
|
||||
printf("Configuring spike cosim\n");
|
||||
std::vector<mem_cfg_t> mem_cfg;
|
||||
std::vector<size_t> hartids;
|
||||
@@ -118,7 +126,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
abort();
|
||||
std::vector<std::string> htif_args;
|
||||
bool in_permissive = false;
|
||||
bool cospike_debug = false;
|
||||
cospike_debug = false;
|
||||
for (int i = 1; i < vinfo.argc; i++) {
|
||||
std::string arg(vinfo.argv[i]);
|
||||
if (arg == "+permissive") {
|
||||
@@ -144,7 +152,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
.support_impebreak = true
|
||||
};
|
||||
|
||||
printf("%s\n", info->isa.c_str());
|
||||
printf("isa string is %s\n", info->isa.c_str());
|
||||
for (int i = 0; i < htif_args.size(); i++) {
|
||||
printf("%s\n", htif_args[i].c_str());
|
||||
}
|
||||
@@ -154,7 +162,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
plugin_devices,
|
||||
htif_args,
|
||||
dm_config,
|
||||
nullptr,
|
||||
"cospike.log",
|
||||
false,
|
||||
nullptr,
|
||||
false,
|
||||
@@ -174,6 +182,8 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
|
||||
printf("Tohost : %lx\n", tohost_addr);
|
||||
printf("Fromhost: %lx\n", fromhost_addr);
|
||||
printf("Memory base : %lx\n", info->mem0_base);
|
||||
printf("Memory Size : %lx\n", info->mem0_size);
|
||||
}
|
||||
|
||||
if (priv & 0x4) { // debug
|
||||
@@ -253,76 +263,122 @@ extern "C" void cospike_cosim(long long int cycle,
|
||||
if (valid) {
|
||||
printf("%d Cosim: %lx", cycle, iaddr);
|
||||
if (has_wdata) {
|
||||
printf(" %lx", wdata);
|
||||
printf(" s: %lx", wdata);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
if (valid || raise_interrupt || raise_exception) {
|
||||
p->step(1);
|
||||
if (unlikely(cospike_debug)) {
|
||||
printf("spike pc is %lx\n", s->pc);
|
||||
printf("spike mstatus is %lx\n", s->mstatus->read());
|
||||
printf("spike mip is %lx\n", s->mip->read());
|
||||
printf("spike mie is %lx\n", s->mie->read());
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (s_pc != iaddr) {
|
||||
printf("%d PC mismatch spike:%lx != dut:%lx\n", cycle, s_pc, iaddr);
|
||||
printf("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
|
||||
if (unlikely(cospike_debug)) {
|
||||
printf("spike mstatus is %lx\n", s->mstatus->read());
|
||||
printf("spike mcause is %lx\n", s->mcause->read());
|
||||
printf("spike mtval is %lx\n" , s->mtval->read());
|
||||
printf("spike mtinst is %lx\n", s->mtinst->read());
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Try to remember magic_mem addrs, and ignore these in the future
|
||||
|
||||
auto& mem_write = s->log_mem_write;
|
||||
if (!mem_write.empty() && tohost_addr && std::get<0>(mem_write[0]) == tohost_addr) {
|
||||
reg_t wdata = std::get<1>(mem_write[0]);
|
||||
if (wdata >= info->mem0_base && wdata < (info->mem0_base + info->mem0_size)) {
|
||||
printf("Probable magic mem %x\n", wdata);
|
||||
magic_addrs.insert(wdata);
|
||||
auto& log = s->log_reg_write;
|
||||
auto& mem_read = s->log_mem_read;
|
||||
|
||||
for (auto memwrite : mem_write) {
|
||||
reg_t waddr = std::get<0>(memwrite);
|
||||
uint64_t w_data = std::get<1>(memwrite);
|
||||
if ((waddr == CLINT_BASE + 4*hartid) && w_data == 0) {
|
||||
s->mip->backdoor_write_with_mask(MIP_MSIP, 0);
|
||||
}
|
||||
// Try to remember magic_mem addrs, and ignore these in the future
|
||||
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
||||
printf("Probable magic mem %lx\n", w_data);
|
||||
magic_addrs.insert(w_data);
|
||||
}
|
||||
}
|
||||
// Try to remember magic_mem addrs, and ignore these in the future
|
||||
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
||||
printf("Probable magic mem %lx\n", w_data);
|
||||
magic_addrs.insert(w_data);
|
||||
}
|
||||
}
|
||||
|
||||
bool scalar_wb = false;
|
||||
bool vector_wb = false;
|
||||
uint32_t vector_cnt = 0;
|
||||
|
||||
for (auto ®write : log) {
|
||||
|
||||
//TODO: scaling to multi issue reads?
|
||||
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
|
||||
|
||||
int rd = regwrite.first >> 4;
|
||||
int type = regwrite.first & 0xf;
|
||||
|
||||
// 0 => int
|
||||
// 1 => fp
|
||||
// 2 => vec
|
||||
// 3 => vec hint
|
||||
// 4 => csr
|
||||
|
||||
bool ignore_read = (!mem_read.empty() &&
|
||||
((magic_addrs.count(mem_read_addr) ||
|
||||
(tohost_addr && mem_read_addr == tohost_addr) ||
|
||||
(fromhost_addr && mem_read_addr == fromhost_addr) ||
|
||||
(CLINT_BASE <= mem_read_addr &&
|
||||
mem_read_addr < (CLINT_BASE + CLINT_SIZE)))));
|
||||
|
||||
// check the type is compliant with writeback first
|
||||
if ((type == 0 || type == 1))
|
||||
scalar_wb = true;
|
||||
if (type == 2) {
|
||||
vector_wb = true;
|
||||
}
|
||||
if (type == 3) continue;
|
||||
|
||||
|
||||
if ((rd != 0 && type == 0) || type == 1) {
|
||||
// Override reads from some CSRs
|
||||
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
||||
bool csr_read = (insn & 0x7f) == 0x73;
|
||||
if (csr_read)
|
||||
printf("CSR read %lx\n", csr_addr);
|
||||
if (csr_read && ((csr_addr == 0xf13) || // mimpid
|
||||
(csr_addr == 0xf12) || // marchid
|
||||
(csr_addr == 0xf11) || // mvendorid
|
||||
(csr_addr == 0xb00) || // mcycle
|
||||
(csr_addr == 0xb02) || // minstret
|
||||
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
||||
)) {
|
||||
printf("CSR override\n");
|
||||
s->XPR.write(rd, wdata);
|
||||
} else if (ignore_read) {
|
||||
// Don't check reads from tohost, reads from magic memory, or reads
|
||||
// from clint Technically this could be buggy because log_mem_read
|
||||
// only reports vaddrs, but no software ever should access
|
||||
// tohost/fromhost/clint with vaddrs anyways
|
||||
printf("Read override %lx\n", mem_read_addr);
|
||||
s->XPR.write(rd, wdata);
|
||||
} else if (wdata != regwrite.second.v[0]) {
|
||||
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
|
||||
regwrite.second.v[0], wdata);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_wdata) {
|
||||
auto& log = s->log_reg_write;
|
||||
auto& mem_read = s->log_mem_read;
|
||||
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
|
||||
for (auto regwrite : log) {
|
||||
int rd = regwrite.first >> 4;
|
||||
int type = regwrite.first & 0xf;
|
||||
// 0 => int
|
||||
// 1 => fp
|
||||
// 2 => vec
|
||||
// 3 => vec hint
|
||||
// 4 => csr
|
||||
if ((rd != 0 && type == 0) || type == 1) {
|
||||
// Override reads from some CSRs
|
||||
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
||||
bool csr_read = (insn & 0x7f) == 0x73;
|
||||
if (csr_read) printf("CSR read %lx\n", csr_addr);
|
||||
if (csr_read && (
|
||||
(csr_addr == 0x301) || // misa
|
||||
(csr_addr == 0xf13) || // mimpid
|
||||
(csr_addr == 0xf12) || // marchid
|
||||
(csr_addr == 0xf11) || // mvendorid
|
||||
(csr_addr == 0xb00) || // mcycle
|
||||
(csr_addr == 0xb02) || // minstret
|
||||
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
||||
)) {
|
||||
printf("CSR override\n");
|
||||
s->XPR.write(rd, wdata);
|
||||
} else if (!mem_read.empty() && ((magic_addrs.count(mem_read_addr) ||
|
||||
(tohost_addr && mem_read_addr == tohost_addr) ||
|
||||
(fromhost_addr && mem_read_addr == fromhost_addr) ||
|
||||
(CLINT_BASE <= mem_read_addr && mem_read_addr < (CLINT_BASE + CLINT_SIZE))
|
||||
))) {
|
||||
// Don't check reads from tohost, reads from magic memory, or reads from clint
|
||||
// Technically this could be buggy because log_mem_read only reports vaddrs, but
|
||||
// no software ever should access tohost/fromhost/clint with vaddrs anyways
|
||||
printf("Read override %lx\n", mem_read_addr);
|
||||
s->XPR.write(rd, wdata);
|
||||
} else if (wdata != regwrite.second.v[0]) {
|
||||
printf("%d wdata mismatch reg %d spike:%lx != dut:%lx addr: %lx\n",
|
||||
cycle, rd, regwrite.second.v[0], wdata, mem_read_addr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scalar_wb ^ has_wdata) {
|
||||
printf("Scalar behavior divergence between spike and DUT\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user