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

Bump spike | support M-mode only cosim #1530

Merged
merged 3 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
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
141 changes: 76 additions & 65 deletions generators/chipyard/src/main/resources/csrc/cospike.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,33 @@ extern std::map<long long int, backing_data_t> backing_mem_data;
#define PLIC_BASE (0xc000000)
#define PLIC_SIZE (0x4000000)

#define COSPIKE_PRINTF(...) { \
printf(__VA_ARGS__); \
fprintf(stderr, __VA_ARGS__); \
}

typedef struct system_info_t {
std::string isa;
int pmpregions;
uint64_t mem0_base;
uint64_t mem0_size;
int nharts;
std::vector<char> bootrom;
std::string priv;
};

class read_override_device_t : public abstract_device_t {
public:
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(size), name(n) { };
bool load(reg_t addr, size_t len, uint8_t* bytes) {
if (addr + len < addr || addr + len > size) return false;
printf("Read from device %s at %lx\n", name.c_str(), addr);
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(sz), name(n) { };
virtual bool load(reg_t addr, size_t len, uint8_t* bytes) override {
if (addr + len > size) return false;
COSPIKE_PRINTF("Read from device %s at %lx\n", name.c_str(), addr);
was_read_from = true;
return true;
}
bool store(reg_t addr, size_t len, const uint8_t* bytes) {
return (addr + len >= addr && addr + len <= size);
virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) override {
COSPIKE_PRINTF("Store to device %s at %lx\n", name.c_str(), addr);
return (addr + len <= size);
}
bool was_read_from;
private:
Expand All @@ -70,7 +77,7 @@ reg_t fromhost_addr = 0;
reg_t cospike_timeout = 0;
std::set<reg_t> magic_addrs;
cfg_t* cfg;
std::vector<read_override_device_t*> read_override_devices;
std::vector<std::shared_ptr<read_override_device_t>> read_override_devices;

static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg_t> &layout)
{
Expand All @@ -82,7 +89,7 @@ static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg
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,
int nharts,
char* bootrom
Expand All @@ -91,6 +98,7 @@ extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
info = new system_info_t;
// technically the targets aren't zicntr compliant, but they implement the zicntr registers
info->isa = std::string(isa) + "_zicntr";
info->priv = std::string(priv);
info->pmpregions = pmpregions;
info->mem0_base = mem0_base;
info->mem0_size = mem0_size;
Expand Down Expand Up @@ -118,7 +126,7 @@ extern "C" void cospike_cosim(long long int cycle,
assert(info);

if (unlikely(!sim)) {
printf("Configuring spike cosim\n");
COSPIKE_PRINTF("Configuring spike cosim\n");
std::vector<mem_cfg_t> mem_cfg;
std::vector<size_t> hartids;
mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size));
Expand All @@ -128,7 +136,7 @@ extern "C" void cospike_cosim(long long int cycle,
cfg = new cfg_t(std::make_pair(0, 0),
nullptr,
info->isa.c_str(),
"MSU",
info->priv.c_str(),
"vlen:128,elen:64",
false,
endianness_little,
Expand All @@ -146,26 +154,26 @@ extern "C" void cospike_cosim(long long int cycle,
assert(info->bootrom.size() < default_boot_rom_size);
info->bootrom.resize(default_boot_rom_size);

rom_device_t *boot_rom = new rom_device_t(info->bootrom);
mem_t *boot_addr_reg = new mem_t(0x1000);
std::shared_ptr<rom_device_t> boot_rom = std::make_shared<rom_device_t>(info->bootrom);
std::shared_ptr<mem_t> boot_addr_reg = std::make_shared<mem_t>(0x1000);
uint64_t default_boot_addr = 0x80000000;
boot_addr_reg->store(0, 8, (const uint8_t*)(&default_boot_addr));
boot_addr_reg.get()->store(0, 8, (const uint8_t*)(&default_boot_addr));

read_override_device_t* clint = new read_override_device_t("clint", CLINT_SIZE);
read_override_device_t* uart = new read_override_device_t("uart", UART_SIZE);
read_override_device_t* plic = new read_override_device_t("plic", PLIC_SIZE);
std::shared_ptr<read_override_device_t> clint = std::make_shared<read_override_device_t>("clint", CLINT_SIZE);
std::shared_ptr<read_override_device_t> uart = std::make_shared<read_override_device_t>("uart", UART_SIZE);
std::shared_ptr<read_override_device_t> plic = std::make_shared<read_override_device_t>("plic", PLIC_SIZE);

read_override_devices.push_back(clint);
read_override_devices.push_back(uart);
read_override_devices.push_back(plic);

std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
std::vector<std::pair<reg_t, std::shared_ptr<abstract_device_t>>> devices;
// The device map is hardcoded here for now
plugin_devices.push_back(std::pair(0x4000, boot_addr_reg));
plugin_devices.push_back(std::pair(default_boot_rom_addr, boot_rom));
plugin_devices.push_back(std::pair(CLINT_BASE, clint));
plugin_devices.push_back(std::pair(UART_BASE, uart));
plugin_devices.push_back(std::pair(PLIC_BASE, plic));
devices.push_back(std::pair(0x4000, boot_addr_reg));
devices.push_back(std::pair(default_boot_rom_addr, boot_rom));
devices.push_back(std::pair(CLINT_BASE, clint));
devices.push_back(std::pair(UART_BASE, uart));
devices.push_back(std::pair(PLIC_BASE, plic));

s_vpi_vlog_info vinfo;
if (!vpi_get_vlog_info(&vinfo))
Expand Down Expand Up @@ -200,16 +208,17 @@ extern "C" void cospike_cosim(long long int cycle,
.support_impebreak = true
};

printf("isa string: %s\n", info->isa.c_str());
printf("htif args: ");
COSPIKE_PRINTF("isa string: %s\n", info->isa.c_str());
COSPIKE_PRINTF("htif args: ");
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;
sim = new sim_t(cfg, false,
mems,
plugin_devices,
plugin_device_factories,
htif_args,
dm_config,
nullptr,
Expand All @@ -218,6 +227,8 @@ extern "C" void cospike_cosim(long long int cycle,
false,
nullptr
);
for (auto &it : devices)
sim->add_device(it.first, it.second);

#ifdef COSPIKE_SIMDRAM
// match sim_t's backing memory with the SimDRAM memory
Expand All @@ -227,9 +238,9 @@ extern "C" void cospike_cosim(long long int cycle,
for (auto& pair : backing_mem_data) {
size_t base = pair.first;
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)) {
printf("Error, unable to match memory at address %lx\n", base);
COSPIKE_PRINTF("Error, unable to match memory at address %lx\n", base);
abort();
}
}
Expand All @@ -249,17 +260,17 @@ extern "C" void cospike_cosim(long long int cycle,
sim->set_debug(cospike_debug);
sim->set_histogram(true);
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();
printf("Spike cosim started\n");
COSPIKE_PRINTF("Spike cosim started\n");
tohost_addr = ((htif_t*)sim)->get_tohost_addr();
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
printf("Tohost : %lx\n", tohost_addr);
printf("Fromhost: %lx\n", fromhost_addr);
printf("BootROM base : %lx\n", default_boot_rom_addr);
printf("BootROM size : %lx\n", boot_rom->contents().size());
printf("Memory base : %lx\n", info->mem0_base);
printf("Memory size : %lx\n", info->mem0_size);
COSPIKE_PRINTF("Tohost : %lx\n", tohost_addr);
COSPIKE_PRINTF("Fromhost: %lx\n", fromhost_addr);
COSPIKE_PRINTF("BootROM base : %lx\n", default_boot_rom_addr);
COSPIKE_PRINTF("BootROM size : %lx\n", boot_rom->contents().size());
COSPIKE_PRINTF("Memory base : %lx\n", info->mem0_base);
COSPIKE_PRINTF("Memory size : %lx\n", info->mem0_size);
}

if (priv & 0x4) { // debug
Expand All @@ -268,7 +279,7 @@ extern "C" void cospike_cosim(long long int cycle,

if (cospike_timeout && cycle > cospike_timeout) {
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;
}
exit(0);
Expand All @@ -279,7 +290,7 @@ extern "C" void cospike_cosim(long long int cycle,
state_t* s = p->get_state();
#ifdef COSPIKE_DTM
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
loadarch_state_t &ls = dtm->loadarch_state[hartid];
s->pc = ls.pc;
Expand Down Expand Up @@ -311,11 +322,11 @@ extern "C" void cospike_cosim(long long int cycle,
RESTORE(CSR_MCYCLE , mcycle);
RESTORE(CSR_MINSTRET , minstret);
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();
}
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();
}
for (size_t i = 0; i < 32; i++) {
Expand All @@ -335,7 +346,7 @@ extern "C" void cospike_cosim(long long int cycle,
bool mtip_interrupt = interrupt_cause == 0x7;
bool debug_interrupt = interrupt_cause == 0xe;
if (raise_interrupt) {
printf("%d interrupt %lx\n", cycle, cause);
COSPIKE_PRINTF("%d interrupt %lx\n", cycle, cause);

if (ssip_interrupt || stip_interrupt) {
// do nothing
Expand All @@ -346,41 +357,41 @@ extern "C" void cospike_cosim(long long int cycle,
} else if (debug_interrupt) {
return;
} else {
printf("Unknown interrupt %lx\n", interrupt_cause);
COSPIKE_PRINTF("Unknown interrupt %lx\n", interrupt_cause);
abort();
}
}
if (raise_exception)
printf("%d exception %lx\n", cycle, cause);
COSPIKE_PRINTF("%d exception %lx\n", cycle, cause);
if (valid) {
p->clear_waiting_for_interrupt();
printf("%d Cosim: %lx", cycle, iaddr);
COSPIKE_PRINTF("%d Cosim: %lx", cycle, iaddr);
// if (has_wdata) {
// printf(" s: %lx", wdata);
// COSPIKE_PRINTF(" s: %lx", wdata);
// }
printf("\n");
COSPIKE_PRINTF("\n");
}
if (valid || raise_interrupt || raise_exception) {
p->clear_waiting_for_interrupt();
for (auto& e : read_override_devices) e->was_read_from = false;
for (auto& e : read_override_devices) e.get()->was_read_from = false;
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());
printf("spike wfi state is %d\n", p->is_waiting_for_interrupt());
COSPIKE_PRINTF("spike pc is %lx\n", s->pc);
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
COSPIKE_PRINTF("spike mip is %lx\n", s->mip->read());
COSPIKE_PRINTF("spike mie is %lx\n", s->mie->read());
COSPIKE_PRINTF("spike wfi state is %d\n", p->is_waiting_for_interrupt());
}
}

if (valid && !raise_exception) {
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)) {
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());
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
COSPIKE_PRINTF("spike mcause is %lx\n", s->mcause->read());
COSPIKE_PRINTF("spike mtval is %lx\n" , s->mtval->read());
COSPIKE_PRINTF("spike mtinst is %lx\n", s->mtinst->read());
}
exit(1);
}
Expand All @@ -401,7 +412,7 @@ extern "C" void cospike_cosim(long long int cycle,
}
// 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);
COSPIKE_PRINTF("Probable magic mem %lx\n", w_data);
magic_addrs.insert(w_data);
}
}
Expand All @@ -424,7 +435,7 @@ extern "C" void cospike_cosim(long long int cycle,
// 3 => vec hint
// 4 => csr
bool device_read = false;
for (auto& e : read_override_devices) if (e->was_read_from) device_read = true;
for (auto& e : read_override_devices) if (e.get()->was_read_from) device_read = true;

bool lr_read = ((insn & MASK_LR_D) == MATCH_LR_D) || ((insn & MASK_LR_W) == MATCH_LR_W);
bool sc_read = ((insn & MASK_SC_D) == MATCH_SC_D) || ((insn & MASK_SC_W) == MATCH_SC_W);
Expand All @@ -449,7 +460,7 @@ extern "C" void cospike_cosim(long long int cycle,
uint64_t csr_addr = (insn >> 20) & 0xfff;
bool csr_read = (insn & 0x7f) == 0x73;
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
(csr_addr == 0x306) || // mcounteren
(csr_addr == 0xf13) || // mimpid
Expand All @@ -463,25 +474,25 @@ extern "C" void cospike_cosim(long long int cycle,
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
)) {
printf("CSR override\n");
COSPIKE_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 = %lx\n", mem_read_addr, wdata);
COSPIKE_PRINTF("Read override %lx = %lx\n", mem_read_addr, wdata);
s->XPR.write(rd, wdata);
} 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);
exit(1);
}
}

// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
// 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);
// }
}
Expand Down
4 changes: 3 additions & 1 deletion generators/chipyard/src/main/resources/vsrc/cospike.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "DPI-C" function void cospike_set_sysinfo(
input string isa,
input string priv,
input int pmpregions,
input longint mem0_base,
input longint mem0_size,
Expand All @@ -23,6 +24,7 @@ import "DPI-C" function void cospike_cosim(input longint cycle,

module SpikeCosim #(
parameter ISA,
parameter PRIV,
parameter PMPREGIONS,
parameter MEM0_BASE,
parameter MEM0_SIZE,
Expand Down Expand Up @@ -57,7 +59,7 @@ module SpikeCosim #(
);

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;

always @(posedge clock) begin
Expand Down
2 changes: 2 additions & 0 deletions generators/chipyard/src/main/scala/Cospike.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import testchipip.TileTraceIO

case class SpikeCosimConfig(
isa: String,
priv: String,
pmpregions: Int,
mem0_base: BigInt,
mem0_size: BigInt,
Expand All @@ -24,6 +25,7 @@ case class SpikeCosimConfig(

class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
"ISA" -> StringParam(cfg.isa),
"PRIV" -> StringParam(cfg.priv),
"PMPREGIONS" -> IntParam(cfg.pmpregions),
"MEM0_BASE" -> IntParam(cfg.mem0_base),
"MEM0_SIZE" -> IntParam(cfg.mem0_size),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ class WithCospike extends ComposeHarnessBinder({
val tiles = chipyardSystem.tiles
val cfg = SpikeCosimConfig(
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_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)),
pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0),
Expand Down
2 changes: 1 addition & 1 deletion toolchains/riscv-tools/riscv-isa-sim
Submodule riscv-isa-sim updated 204 files