Support dmi-based Spike bringup

This commit is contained in:
Jerry Zhao
2023-04-10 15:42:10 -07:00
parent 1097073c79
commit 6a97f2eb97
7 changed files with 65 additions and 13 deletions

View File

@@ -2,13 +2,20 @@
#include <riscv/processor.h>
#include <riscv/log_file.h>
#include <fesvr/context.h>
#include <fesvr/htif.h>
#include <map>
#include <sstream>
#include <vpi_user.h>
#include <svdpi.h>
#include "testchip_tsi.h"
#include "spiketile_htif_mode.h"
extern testchip_tsi_t* tsi;
#if defined(SPIKETILE_HTIF_TSI)
extern htif_t* tsi;
#elif defined(SPIKETILE_HTIF_DTM)
extern htif_t* dtm;
#else
#error "SpikeTile must be used with the TSI or DTM-based HTIF bringup"
#endif
enum transfer_t {
NToB,
@@ -84,6 +91,7 @@ public:
void drain_stq();
bool stq_empty() { return st_q.size() == 0; };
void flush_icache();
const cfg_t &get_cfg() const { return cfg; }
const std::map<size_t, processor_t*>& get_harts() const { return harts; }
@@ -334,14 +342,21 @@ extern "C" void spike_tile(int hartid, char* isa,
tile_t* tile = tiles[hartid];
chipyard_simif_t* simif = tile->simif;
processor_t* proc = tile->proc;
if (!simif->htif && tsi) {
simif->htif = (htif_t*) tsi;
}
#if defined(SPIKETILE_HTIF_TSI)
if (!simif->htif && tsi)
simif->htif = tsi;
#elif defined(SPIKETILE_HTIF_DTM)
if (!simif->htif && dtm)
simif->htif = dtm;
#endif
simif->cycle = cycle;
if (debug) {
proc->halt_request = proc->HR_REGULAR;
}
if (!debug && proc->halt_request != proc->HR_NONE) {
proc->halt_request = proc->HR_NONE;
}
proc->get_state()->mip->backdoor_write_with_mask(MIP_MTIP, mtip ? MIP_MTIP : 0);
proc->get_state()->mip->backdoor_write_with_mask(MIP_MSIP, msip ? MIP_MSIP : 0);
@@ -504,6 +519,12 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
tcm = (uint8_t*)malloc(tcm_size);
}
void chipyard_simif_t::flush_icache() {
for (auto &w : icache) {
for (size_t i = 0; i < icache_sets; i++) w[i].state = NONE;
}
}
bool chipyard_simif_t::reservable(reg_t addr) {
for (auto& r: cacheables) {
if (addr >= r.base && addr < r.base + r.size) {
@@ -605,6 +626,7 @@ void chipyard_simif_t::handle_mmio_access(reg_t addr, size_t len,
mmio_st = type == STORE;
if (type == STORE) {
assert(len <= 8);
mmio_stdata = 0;
memcpy(&mmio_stdata, store_bytes, len);
}
mmio_len = len;
@@ -1075,7 +1097,16 @@ void spike_thread_main(void* arg)
tile->max_insns = 0;
}
}
if (tile->max_insns % 100 == 0) {
if (state->debug_mode) {
// TODO: Fix. This needs to apply the same hack as rocket-chip...
// JALRs in debug mode should flush the ICache.
// There is no API to determine if a JALR was executed, so hack the
// pc of the JALR in the debug rom here instead.
if (state->pc == 0x838) {
simif->flush_icache();
}
}
if (tile->max_insns % 101 == 0) { // 101 to avoid harmonics with small loops
uint64_t old_minstret = state->minstret->read();
uint64_t tohost_addr = simif->htif ? simif->htif->get_tohost_addr() : 0;
uint64_t fromhost_addr = simif->htif ? simif->htif->get_fromhost_addr() : 0;

View File

@@ -0,0 +1 @@
#define SPIKETILE_HTIF_DTM

View File

@@ -0,0 +1 @@
#define SPIKETILE_HTIF_TSI

View File

@@ -252,7 +252,7 @@ class WithSimDebug extends OverrideHarnessBinder({
case d: ClockedDMIIO =>
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val dtm = Module(new SimDTM).connect(th.buildtopClock, th.buildtopReset.asBool, d, dtm_success)
val dtm = Module(new TestchipSimDTM).connect(th.buildtopClock, th.buildtopReset.asBool, d, dtm_success)
case j: JTAGChipIO =>
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
@@ -262,7 +262,8 @@ class WithSimDebug extends OverrideHarnessBinder({
j.TCK := jtag_wire.TCK
j.TMS := jtag_wire.TMS
j.TDI := jtag_wire.TDI
val jtag = Module(new SimJTAG(tickDelay=3)).connect(jtag_wire, th.buildtopClock, th.buildtopReset.asBool, ~(th.buildtopReset.asBool), dtm_success)
val jtag = Module(new SimJTAG(tickDelay=3))
jtag.connect(jtag_wire, th.buildtopClock, th.buildtopReset.asBool, ~(th.buildtopReset.asBool), dtm_success)
}
}
})

View File

@@ -7,6 +7,7 @@ import chisel3.experimental.{IntParam, StringParam, IO}
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.devices.debug.{ExportDebug, DMI}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.rocket._
import freechips.rocketchip.tilelink._
@@ -189,7 +190,8 @@ class SpikeBlackBox(
readonly_uncacheable_regions: String,
executable_regions: String,
tcm_base: BigInt,
tcm_size: BigInt) extends BlackBox(Map(
tcm_size: BigInt,
use_dtm: Boolean) extends BlackBox(Map(
"HARTID" -> IntParam(hartId),
"ISA" -> StringParam(isa),
"PMPREGIONS" -> IntParam(pmpregions),
@@ -302,7 +304,11 @@ class SpikeBlackBox(
})
addResource("/vsrc/spiketile.v")
addResource("/csrc/spiketile.cc")
if (use_dtm) {
addResource("/csrc/spiketile_dtm/spiketile_htif_mode.h")
} else {
addResource("/csrc/spiketile_tsi/spiketile_htif_mode.h")
}
}
class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
@@ -326,13 +332,18 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
val (dcache_tl, dcacheEdge) = outer.dcacheNode.out(0)
val (mmio_tl, mmioEdge) = outer.mmioNode.out(0)
// Note: This assumes that if the debug module exposes the ClockedDMI port,
// then the DTM-based bringup with SimDTM will be used. This isn't required to be
// true, but it usually is
val useDTM = p(ExportDebug).protocols.contains(DMI)
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
tileParams.dcache.get.nMSHRs,
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0)
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0),
useDTM
))
spike.io.clock := clock.asBool
val cycle = RegInit(0.U(64.W))
@@ -421,7 +432,7 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
spike.io.mmio.a.ready := mmio_tl.a.ready
mmio_tl.a.valid := spike.io.mmio.a.valid
val log_size = MuxCase(0.U, (0 until 3).map { i => (spike.io.mmio.a.size === (1 << i).U) -> i.U })
val log_size = (0 until 4).map { i => Mux(spike.io.mmio.a.size === (1 << i).U, i.U, 0.U) }.reduce(_|_)
mmio_tl.a.bits := Mux(spike.io.mmio.a.store,
mmioEdge.Put(0.U, spike.io.mmio.a.address, log_size, spike.io.mmio.a.data)._2,
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)

View File

@@ -10,6 +10,13 @@ class SpikeConfig extends Config(
new chipyard.WithNSpikeCores(1) ++
new chipyard.config.AbstractConfig)
class dmiSpikeConfig extends Config(
new chipyard.harness.WithSerialAdapterTiedOff ++ // don't attach an external SimSerial
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new chipyard.WithNSpikeCores(1) ++
new chipyard.config.AbstractConfig)
// Avoids polling on the UART registers
class SpikeFastUARTConfig extends Config(
new chipyard.WithNSpikeCores(1) ++