Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

misc: many fixes to cospike #1450

Merged
merged 3 commits into from
Apr 20, 2023
Merged
Changes from all commits
Commits
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
172 changes: 114 additions & 58 deletions generators/chipyard/src/main/resources/csrc/cospike.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
#include <cstdint>
#include <vector>
#include <string>
#include <riscv/sim.h>
#include <vpi_user.h>
#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
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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") {
Expand All @@ -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());
}
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
}

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);
}
}
bool scalar_wb = false;
bool vector_wb = false;
uint32_t vector_cnt = 0;

for (auto &regwrite : 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) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: fix the alignment here.

(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 (scalar_wb ^ has_wdata) {
printf("Scalar behavior divergence between spike and DUT\n");
exit(-1);
}
}
}