From 330a747b542d999b300f2de2fce1ec4e9fd47299 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 13 Apr 2023 17:49:39 -0700 Subject: [PATCH] Support loadarch+dtm in cosimulation with spike --- .../src/main/resources/csrc/cospike.cc | 68 +++++++++++++++++-- .../src/main/resources/csrc/cospike_dtm.h | 0 .../src/main/resources/vsrc/cospike.v | 11 +-- .../chipyard/src/main/scala/Cospike.scala | 12 ++-- .../src/main/scala/HarnessBinders.scala | 3 +- 5 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 generators/chipyard/src/main/resources/csrc/cospike_dtm.h diff --git a/generators/chipyard/src/main/resources/csrc/cospike.cc b/generators/chipyard/src/main/resources/csrc/cospike.cc index fa0513d7..66b2cd29 100644 --- a/generators/chipyard/src/main/resources/csrc/cospike.cc +++ b/generators/chipyard/src/main/resources/csrc/cospike.cc @@ -6,6 +6,13 @@ #include #include +#if __has_include ("cospike_dtm.h") +#define COSPIKE_DTM +#include "testchip_dtm.h" +extern testchip_dtm_t* dtm; +bool spike_loadarch_done = false; +#endif + #define CLINT_BASE (0x2000000) #define CLINT_SIZE (0x1000) @@ -64,7 +71,8 @@ extern "C" void cospike_cosim(long long int cycle, int raise_exception, int raise_interrupt, unsigned long long int cause, - unsigned long long int wdata) + unsigned long long int wdata, + int priv) { assert(info); if (!sim) { @@ -168,16 +176,60 @@ extern "C" void cospike_cosim(long long int cycle, printf("Fromhost: %lx\n", fromhost_addr); } + if (priv & 0x4) { // debug + return; + } + processor_t* p = sim->get_core(hartid); 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"); + // copy the loadarch state into the cosim + loadarch_state_t &ls = dtm->loadarch_state[hartid]; + s->pc = ls.pc; + s->prv = ls.prv; +#define RESTORE(CSRID, csr) s->csrmap[CSRID]->write(ls.csr); + RESTORE(CSR_STVEC , stvec); + RESTORE(CSR_SSCRATCH , sscratch); + RESTORE(CSR_SEPC , sepc); + RESTORE(CSR_SCAUSE , scause); + RESTORE(CSR_STVAL , stval); + RESTORE(CSR_SATP , satp); + RESTORE(CSR_MSTATUS , mstatus); + RESTORE(CSR_MEDELEG , medeleg); + RESTORE(CSR_MIDELEG , mideleg); + RESTORE(CSR_MIE , mie); + RESTORE(CSR_MTVEC , mtvec); + RESTORE(CSR_MSCRATCH , mscratch); + RESTORE(CSR_MEPC , mepc); + RESTORE(CSR_MCAUSE , mcause); + RESTORE(CSR_MTVAL , mtval); + RESTORE(CSR_MIP , mip); + RESTORE(CSR_MCYCLE , mcycle); + RESTORE(CSR_MINSTRET , minstret); + for (size_t i = 0; i < 32; i++) { + s->XPR.write(i, ls.XPR[i]); + s->FPR.write(i, { (uint64_t)ls.FPR[i], (uint64_t)-1 }); + } + spike_loadarch_done = true; + p->clear_waiting_for_interrupt(); + } +#endif uint64_t s_pc = s->pc; + uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF; + bool msip_interrupt = interrupt_cause == 0x3; + bool debug_interrupt = interrupt_cause == 0xe; if (raise_interrupt) { printf("%d interrupt %lx\n", cycle, cause); - uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF; - if (interrupt_cause == 3) { + + if (msip_interrupt) { s->mip->backdoor_write_with_mask(MIP_MSIP, MIP_MSIP); + } else if (debug_interrupt) { + return; } else { printf("Unknown interrupt %lx\n", interrupt_cause); + abort(); } } if (raise_exception) @@ -189,12 +241,13 @@ extern "C" void cospike_cosim(long long int cycle, } printf("\n"); } - if (valid || raise_interrupt || raise_exception) + if (valid || raise_interrupt || raise_exception) { p->step(1); + } if (valid) { if (s_pc != iaddr) { - printf("%d PC mismatch %lx != %lx\n", cycle, s_pc, iaddr); + printf("%d PC mismatch spike:%lx != dut:%lx\n", cycle, s_pc, iaddr); exit(1); } @@ -247,7 +300,8 @@ extern "C" void cospike_cosim(long long int cycle, 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); + 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); } } @@ -255,4 +309,4 @@ extern "C" void cospike_cosim(long long int cycle, } } } -// } + diff --git a/generators/chipyard/src/main/resources/csrc/cospike_dtm.h b/generators/chipyard/src/main/resources/csrc/cospike_dtm.h new file mode 100644 index 00000000..e69de29b diff --git a/generators/chipyard/src/main/resources/vsrc/cospike.v b/generators/chipyard/src/main/resources/vsrc/cospike.v index f9d2322c..824e8d35 100644 --- a/generators/chipyard/src/main/resources/vsrc/cospike.v +++ b/generators/chipyard/src/main/resources/vsrc/cospike.v @@ -16,7 +16,8 @@ import "DPI-C" function void cospike_cosim(input longint cycle, input bit raise_exception, input bit raise_interrupt, input longint cause, - input longint wdata + input longint wdata, + input int priv ); @@ -42,6 +43,7 @@ module SpikeCosim #( input [63:0] trace_0_cause, input trace_0_has_wdata, input [63:0] trace_0_wdata, + input [2:0] trace_0_priv, input trace_1_valid, input [63:0] trace_1_iaddr, @@ -50,7 +52,8 @@ module SpikeCosim #( input trace_1_interrupt, input [63:0] trace_1_cause, input trace_1_has_wdata, - input [63:0] trace_1_wdata + input [63:0] trace_1_wdata, + input [2:0] trace_1_priv ); initial begin @@ -62,12 +65,12 @@ module SpikeCosim #( if (trace_0_valid || trace_0_exception || trace_0_cause) begin cospike_cosim(cycle, hartid, trace_0_has_wdata, trace_0_valid, trace_0_iaddr, trace_0_insn, trace_0_exception, trace_0_interrupt, trace_0_cause, - trace_0_wdata); + trace_0_wdata, trace_0_priv); end if (trace_1_valid || trace_1_exception || trace_1_cause) begin cospike_cosim(cycle, hartid, trace_1_has_wdata, trace_1_valid, trace_1_iaddr, trace_1_insn, trace_1_exception, trace_1_interrupt, trace_1_cause, - trace_1_wdata); + trace_1_wdata, trace_1_priv); end end end diff --git a/generators/chipyard/src/main/scala/Cospike.scala b/generators/chipyard/src/main/scala/Cospike.scala index fffb97d6..cee23413 100644 --- a/generators/chipyard/src/main/scala/Cospike.scala +++ b/generators/chipyard/src/main/scala/Cospike.scala @@ -18,7 +18,8 @@ case class SpikeCosimConfig( mem0_base: BigInt, mem0_size: BigInt, nharts: Int, - bootrom: String + bootrom: String, + has_dtm: Boolean ) class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map( @@ -32,6 +33,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map( { addResource("/csrc/cospike.cc") addResource("/vsrc/cospike.v") + if (cfg.has_dtm) addResource("/csrc/cospike_dtm.h") val io = IO(new Bundle { val clock = Input(Clock()) val reset = Input(Bool()) @@ -46,6 +48,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map( val cause = UInt(64.W) val has_wdata = Bool() val wdata = UInt(64.W) + val priv = UInt(3.W) })) }) } @@ -64,12 +67,8 @@ object SpikeCosim require(trace.numInsns <= 2) cosim.io.cycle := cycle cosim.io.trace.map(t => { + t := DontCare t.valid := false.B - t.iaddr := 0.U - t.insn := 0.U - t.exception := false.B - t.interrupt := false.B - t.cause := 0.U }) cosim.io.hartid := hartid.U for (i <- 0 until trace.numInsns) { @@ -83,6 +82,7 @@ object SpikeCosim cosim.io.trace(i).cause := trace.insns(i).cause cosim.io.trace(i).has_wdata := trace.insns(i).wdata.isDefined.B cosim.io.trace(i).wdata := trace.insns(i).wdata.getOrElse(0.U) + cosim.io.trace(i).priv := trace.insns(i).priv } } } diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index 85ba3d5f..3e43dfe6 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -369,7 +369,8 @@ class WithCospike extends ComposeHarnessBinder({ mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)), pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0), nharts = tiles.size, - bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse("") + bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""), + has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM ) ports.map { p => p.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, cfg)) } }