diff --git a/generators/chipyard/src/main/resources/csrc/cospike.cc b/generators/chipyard/src/main/resources/csrc/cospike.cc index 1c6cd58f..1b4cdb93 100644 --- a/generators/chipyard/src/main/resources/csrc/cospike.cc +++ b/generators/chipyard/src/main/resources/csrc/cospike.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #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 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; std::vector hartids; @@ -118,7 +126,7 @@ extern "C" void cospike_cosim(long long int cycle, abort(); std::vector 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); } } } -