Support m-mode only cospike

This commit is contained in:
Jerry Zhao
2023-06-20 14:28:54 -07:00
parent fce7e4c5aa
commit 4a1418dde2
5 changed files with 65 additions and 51 deletions

View File

@@ -35,6 +35,11 @@ extern std::map<long long int, backing_data_t> backing_mem_data;
#define PLIC_BASE (0xc000000) #define PLIC_BASE (0xc000000)
#define PLIC_SIZE (0x4000000) #define PLIC_SIZE (0x4000000)
#define COSPIKE_PRINTF(...) { \
printf(__VA_ARGS__); \
fprintf(stderr, __VA_ARGS__); \
}
typedef struct system_info_t { typedef struct system_info_t {
std::string isa; std::string isa;
int pmpregions; int pmpregions;
@@ -42,19 +47,21 @@ typedef struct system_info_t {
uint64_t mem0_size; uint64_t mem0_size;
int nharts; int nharts;
std::vector<char> bootrom; std::vector<char> bootrom;
std::string priv;
}; };
class read_override_device_t : public abstract_device_t { class read_override_device_t : public abstract_device_t {
public: public:
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(size), name(n) { }; read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(sz), name(n) { };
bool load(reg_t addr, size_t len, uint8_t* bytes) { virtual bool load(reg_t addr, size_t len, uint8_t* bytes) override {
if (addr + len < addr || addr + len > size) return false; if (addr + len > size) return false;
printf("Read from device %s at %lx\n", name.c_str(), addr); COSPIKE_PRINTF("Read from device %s at %lx\n", name.c_str(), addr);
was_read_from = true; was_read_from = true;
return true; return true;
} }
bool store(reg_t addr, size_t len, const uint8_t* bytes) { virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) override {
return (addr + len >= addr && addr + len <= size); COSPIKE_PRINTF("Store to device %s at %lx\n", name.c_str(), addr);
return (addr + len <= size);
} }
bool was_read_from; bool was_read_from;
private: private:
@@ -82,7 +89,7 @@ static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg
return mems; return mems;
} }
extern "C" void cospike_set_sysinfo(char* isa, int pmpregions, extern "C" void cospike_set_sysinfo(char* isa, char* priv, int pmpregions,
long long int mem0_base, long long int mem0_size, long long int mem0_base, long long int mem0_size,
int nharts, int nharts,
char* bootrom char* bootrom
@@ -91,6 +98,7 @@ extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
info = new system_info_t; info = new system_info_t;
// technically the targets aren't zicntr compliant, but they implement the zicntr registers // technically the targets aren't zicntr compliant, but they implement the zicntr registers
info->isa = std::string(isa) + "_zicntr"; info->isa = std::string(isa) + "_zicntr";
info->priv = std::string(priv);
info->pmpregions = pmpregions; info->pmpregions = pmpregions;
info->mem0_base = mem0_base; info->mem0_base = mem0_base;
info->mem0_size = mem0_size; info->mem0_size = mem0_size;
@@ -118,7 +126,7 @@ extern "C" void cospike_cosim(long long int cycle,
assert(info); assert(info);
if (unlikely(!sim)) { if (unlikely(!sim)) {
printf("Configuring spike cosim\n"); COSPIKE_PRINTF("Configuring spike cosim\n");
std::vector<mem_cfg_t> mem_cfg; std::vector<mem_cfg_t> mem_cfg;
std::vector<size_t> hartids; std::vector<size_t> hartids;
mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size)); mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size));
@@ -128,7 +136,7 @@ extern "C" void cospike_cosim(long long int cycle,
cfg = new cfg_t(std::make_pair(0, 0), cfg = new cfg_t(std::make_pair(0, 0),
nullptr, nullptr,
info->isa.c_str(), info->isa.c_str(),
"MSU", info->priv.c_str(),
"vlen:128,elen:64", "vlen:128,elen:64",
false, false,
endianness_little, endianness_little,
@@ -200,12 +208,13 @@ extern "C" void cospike_cosim(long long int cycle,
.support_impebreak = true .support_impebreak = true
}; };
printf("isa string: %s\n", info->isa.c_str()); COSPIKE_PRINTF("isa string: %s\n", info->isa.c_str());
printf("htif args: "); COSPIKE_PRINTF("htif args: ");
for (int i = 0; i < htif_args.size(); i++) { for (int i = 0; i < htif_args.size(); i++) {
printf("%s", htif_args[i].c_str()); COSPIKE_PRINTF("%s", htif_args[i].c_str());
} }
printf("\n"); COSPIKE_PRINTF("\n");
std::vector<const device_factory_t*> plugin_device_factories; std::vector<const device_factory_t*> plugin_device_factories;
sim = new sim_t(cfg, false, sim = new sim_t(cfg, false,
mems, mems,
@@ -229,9 +238,9 @@ extern "C" void cospike_cosim(long long int cycle,
for (auto& pair : backing_mem_data) { for (auto& pair : backing_mem_data) {
size_t base = pair.first; size_t base = pair.first;
size_t size = pair.second.size; size_t size = pair.second.size;
printf("Matching spike memory initial state for region %lx-%lx\n", base, base + size); COSPIKE_PRINTF("Matching spike memory initial state for region %lx-%lx\n", base, base + size);
if (!temp_mem_bus.store(base, size, pair.second.data)) { if (!temp_mem_bus.store(base, size, pair.second.data)) {
printf("Error, unable to match memory at address %lx\n", base); COSPIKE_PRINTF("Error, unable to match memory at address %lx\n", base);
abort(); abort();
} }
} }
@@ -251,17 +260,17 @@ extern "C" void cospike_cosim(long long int cycle,
sim->set_debug(cospike_debug); sim->set_debug(cospike_debug);
sim->set_histogram(true); sim->set_histogram(true);
sim->set_procs_debug(cospike_debug); sim->set_procs_debug(cospike_debug);
printf("Setting up htif for spike cosim\n"); COSPIKE_PRINTF("Setting up htif for spike cosim\n");
((htif_t*)sim)->start(); ((htif_t*)sim)->start();
printf("Spike cosim started\n"); COSPIKE_PRINTF("Spike cosim started\n");
tohost_addr = ((htif_t*)sim)->get_tohost_addr(); tohost_addr = ((htif_t*)sim)->get_tohost_addr();
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr(); fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
printf("Tohost : %lx\n", tohost_addr); COSPIKE_PRINTF("Tohost : %lx\n", tohost_addr);
printf("Fromhost: %lx\n", fromhost_addr); COSPIKE_PRINTF("Fromhost: %lx\n", fromhost_addr);
printf("BootROM base : %lx\n", default_boot_rom_addr); COSPIKE_PRINTF("BootROM base : %lx\n", default_boot_rom_addr);
printf("BootROM size : %lx\n", boot_rom->contents().size()); COSPIKE_PRINTF("BootROM size : %lx\n", boot_rom->contents().size());
printf("Memory base : %lx\n", info->mem0_base); COSPIKE_PRINTF("Memory base : %lx\n", info->mem0_base);
printf("Memory size : %lx\n", info->mem0_size); COSPIKE_PRINTF("Memory size : %lx\n", info->mem0_size);
} }
if (priv & 0x4) { // debug if (priv & 0x4) { // debug
@@ -270,7 +279,7 @@ extern "C" void cospike_cosim(long long int cycle,
if (cospike_timeout && cycle > cospike_timeout) { if (cospike_timeout && cycle > cospike_timeout) {
if (sim) { if (sim) {
printf("Cospike reached timeout cycles = %ld, terminating\n", cospike_timeout); COSPIKE_PRINTF("Cospike reached timeout cycles = %ld, terminating\n", cospike_timeout);
delete sim; delete sim;
} }
exit(0); exit(0);
@@ -281,7 +290,7 @@ extern "C" void cospike_cosim(long long int cycle,
state_t* s = p->get_state(); state_t* s = p->get_state();
#ifdef COSPIKE_DTM #ifdef COSPIKE_DTM
if (dtm && dtm->loadarch_done && !spike_loadarch_done) { if (dtm && dtm->loadarch_done && !spike_loadarch_done) {
printf("Restoring spike state from testchip_dtm loadarch\n"); COSPIKE_PRINTF("Restoring spike state from testchip_dtm loadarch\n");
// copy the loadarch state into the cosim // copy the loadarch state into the cosim
loadarch_state_t &ls = dtm->loadarch_state[hartid]; loadarch_state_t &ls = dtm->loadarch_state[hartid];
s->pc = ls.pc; s->pc = ls.pc;
@@ -313,11 +322,11 @@ extern "C" void cospike_cosim(long long int cycle,
RESTORE(CSR_MCYCLE , mcycle); RESTORE(CSR_MCYCLE , mcycle);
RESTORE(CSR_MINSTRET , minstret); RESTORE(CSR_MINSTRET , minstret);
if (ls.VLEN != p->VU.VLEN) { if (ls.VLEN != p->VU.VLEN) {
printf("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN); COSPIKE_PRINTF("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN);
abort(); abort();
} }
if (ls.ELEN != p->VU.ELEN) { if (ls.ELEN != p->VU.ELEN) {
printf("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN); COSPIKE_PRINTF("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN);
abort(); abort();
} }
for (size_t i = 0; i < 32; i++) { for (size_t i = 0; i < 32; i++) {
@@ -337,7 +346,7 @@ extern "C" void cospike_cosim(long long int cycle,
bool mtip_interrupt = interrupt_cause == 0x7; bool mtip_interrupt = interrupt_cause == 0x7;
bool debug_interrupt = interrupt_cause == 0xe; bool debug_interrupt = interrupt_cause == 0xe;
if (raise_interrupt) { if (raise_interrupt) {
printf("%d interrupt %lx\n", cycle, cause); COSPIKE_PRINTF("%d interrupt %lx\n", cycle, cause);
if (ssip_interrupt || stip_interrupt) { if (ssip_interrupt || stip_interrupt) {
// do nothing // do nothing
@@ -348,41 +357,41 @@ extern "C" void cospike_cosim(long long int cycle,
} else if (debug_interrupt) { } else if (debug_interrupt) {
return; return;
} else { } else {
printf("Unknown interrupt %lx\n", interrupt_cause); COSPIKE_PRINTF("Unknown interrupt %lx\n", interrupt_cause);
abort(); abort();
} }
} }
if (raise_exception) if (raise_exception)
printf("%d exception %lx\n", cycle, cause); COSPIKE_PRINTF("%d exception %lx\n", cycle, cause);
if (valid) { if (valid) {
p->clear_waiting_for_interrupt(); p->clear_waiting_for_interrupt();
printf("%d Cosim: %lx", cycle, iaddr); COSPIKE_PRINTF("%d Cosim: %lx", cycle, iaddr);
// if (has_wdata) { // if (has_wdata) {
// printf(" s: %lx", wdata); // COSPIKE_PRINTF(" s: %lx", wdata);
// } // }
printf("\n"); COSPIKE_PRINTF("\n");
} }
if (valid || raise_interrupt || raise_exception) { if (valid || raise_interrupt || raise_exception) {
p->clear_waiting_for_interrupt(); p->clear_waiting_for_interrupt();
for (auto& e : read_override_devices) e.get()->was_read_from = false; for (auto& e : read_override_devices) e.get()->was_read_from = false;
p->step(1); p->step(1);
if (unlikely(cospike_debug)) { if (unlikely(cospike_debug)) {
printf("spike pc is %lx\n", s->pc); COSPIKE_PRINTF("spike pc is %lx\n", s->pc);
printf("spike mstatus is %lx\n", s->mstatus->read()); COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
printf("spike mip is %lx\n", s->mip->read()); COSPIKE_PRINTF("spike mip is %lx\n", s->mip->read());
printf("spike mie is %lx\n", s->mie->read()); COSPIKE_PRINTF("spike mie is %lx\n", s->mie->read());
printf("spike wfi state is %d\n", p->is_waiting_for_interrupt()); COSPIKE_PRINTF("spike wfi state is %d\n", p->is_waiting_for_interrupt());
} }
} }
if (valid && !raise_exception) { if (valid && !raise_exception) {
if (s_pc != iaddr) { if (s_pc != iaddr) {
printf("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr); COSPIKE_PRINTF("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
if (unlikely(cospike_debug)) { if (unlikely(cospike_debug)) {
printf("spike mstatus is %lx\n", s->mstatus->read()); COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
printf("spike mcause is %lx\n", s->mcause->read()); COSPIKE_PRINTF("spike mcause is %lx\n", s->mcause->read());
printf("spike mtval is %lx\n" , s->mtval->read()); COSPIKE_PRINTF("spike mtval is %lx\n" , s->mtval->read());
printf("spike mtinst is %lx\n", s->mtinst->read()); COSPIKE_PRINTF("spike mtinst is %lx\n", s->mtinst->read());
} }
exit(1); exit(1);
} }
@@ -403,7 +412,7 @@ extern "C" void cospike_cosim(long long int cycle,
} }
// Try to remember magic_mem addrs, and ignore these in the future // 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)) { 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); COSPIKE_PRINTF("Probable magic mem %lx\n", w_data);
magic_addrs.insert(w_data); magic_addrs.insert(w_data);
} }
} }
@@ -451,7 +460,7 @@ extern "C" void cospike_cosim(long long int cycle,
uint64_t csr_addr = (insn >> 20) & 0xfff; uint64_t csr_addr = (insn >> 20) & 0xfff;
bool csr_read = (insn & 0x7f) == 0x73; bool csr_read = (insn & 0x7f) == 0x73;
if (csr_read) if (csr_read)
printf("CSR read %lx\n", csr_addr); COSPIKE_PRINTF("CSR read %lx\n", csr_addr);
if (csr_read && ((csr_addr == 0x301) || // misa if (csr_read && ((csr_addr == 0x301) || // misa
(csr_addr == 0x306) || // mcounteren (csr_addr == 0x306) || // mcounteren
(csr_addr == 0xf13) || // mimpid (csr_addr == 0xf13) || // mimpid
@@ -465,17 +474,17 @@ extern "C" void cospike_cosim(long long int cycle,
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers (csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr (csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
)) { )) {
printf("CSR override\n"); COSPIKE_PRINTF("CSR override\n");
s->XPR.write(rd, wdata); s->XPR.write(rd, wdata);
} else if (ignore_read) { } else if (ignore_read) {
// Don't check reads from tohost, reads from magic memory, or reads // Don't check reads from tohost, reads from magic memory, or reads
// from clint Technically this could be buggy because log_mem_read // from clint Technically this could be buggy because log_mem_read
// only reports vaddrs, but no software ever should access // only reports vaddrs, but no software ever should access
// tohost/fromhost/clint with vaddrs anyways // tohost/fromhost/clint with vaddrs anyways
printf("Read override %lx = %lx\n", mem_read_addr, wdata); COSPIKE_PRINTF("Read override %lx = %lx\n", mem_read_addr, wdata);
s->XPR.write(rd, wdata); s->XPR.write(rd, wdata);
} else if (wdata != regwrite.second.v[0]) { } else if (wdata != regwrite.second.v[0]) {
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd, COSPIKE_PRINTF("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
regwrite.second.v[0], wdata); regwrite.second.v[0], wdata);
exit(1); exit(1);
} }
@@ -483,7 +492,7 @@ extern "C" void cospike_cosim(long long int cycle,
// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt) // TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
// if (scalar_wb ^ has_wdata) { // if (scalar_wb ^ has_wdata) {
// printf("Scalar wdata behavior divergence between spike and DUT\n"); // COSPIKE_PRINTF("Scalar wdata behavior divergence between spike and DUT\n");
// exit(-1); // exit(-1);
// } // }
} }

View File

@@ -1,5 +1,6 @@
import "DPI-C" function void cospike_set_sysinfo( import "DPI-C" function void cospike_set_sysinfo(
input string isa, input string isa,
input string priv,
input int pmpregions, input int pmpregions,
input longint mem0_base, input longint mem0_base,
input longint mem0_size, input longint mem0_size,
@@ -23,6 +24,7 @@ import "DPI-C" function void cospike_cosim(input longint cycle,
module SpikeCosim #( module SpikeCosim #(
parameter ISA, parameter ISA,
parameter PRIV,
parameter PMPREGIONS, parameter PMPREGIONS,
parameter MEM0_BASE, parameter MEM0_BASE,
parameter MEM0_SIZE, parameter MEM0_SIZE,
@@ -57,7 +59,7 @@ module SpikeCosim #(
); );
initial begin initial begin
cospike_set_sysinfo(ISA, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM); cospike_set_sysinfo(ISA, PRIV, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM);
end; end;
always @(posedge clock) begin always @(posedge clock) begin

View File

@@ -14,6 +14,7 @@ import testchipip.TileTraceIO
case class SpikeCosimConfig( case class SpikeCosimConfig(
isa: String, isa: String,
priv: String,
pmpregions: Int, pmpregions: Int,
mem0_base: BigInt, mem0_base: BigInt,
mem0_size: BigInt, mem0_size: BigInt,
@@ -24,6 +25,7 @@ case class SpikeCosimConfig(
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map( class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
"ISA" -> StringParam(cfg.isa), "ISA" -> StringParam(cfg.isa),
"PRIV" -> StringParam(cfg.priv),
"PMPREGIONS" -> IntParam(cfg.pmpregions), "PMPREGIONS" -> IntParam(cfg.pmpregions),
"MEM0_BASE" -> IntParam(cfg.mem0_base), "MEM0_BASE" -> IntParam(cfg.mem0_base),
"MEM0_SIZE" -> IntParam(cfg.mem0_size), "MEM0_SIZE" -> IntParam(cfg.mem0_size),

View File

@@ -365,6 +365,7 @@ class WithCospike extends ComposeHarnessBinder({
val tiles = chipyardSystem.tiles val tiles = chipyardSystem.tiles
val cfg = SpikeCosimConfig( val cfg = SpikeCosimConfig(
isa = tiles.headOption.map(_.isaDTS).getOrElse(""), isa = tiles.headOption.map(_.isaDTS).getOrElse(""),
priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""),
mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)), mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)),
mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)), mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0), pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),