Support dmi-based Spike bringup
This commit is contained in:
@@ -2,13 +2,20 @@
|
|||||||
#include <riscv/processor.h>
|
#include <riscv/processor.h>
|
||||||
#include <riscv/log_file.h>
|
#include <riscv/log_file.h>
|
||||||
#include <fesvr/context.h>
|
#include <fesvr/context.h>
|
||||||
|
#include <fesvr/htif.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vpi_user.h>
|
#include <vpi_user.h>
|
||||||
#include <svdpi.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 {
|
enum transfer_t {
|
||||||
NToB,
|
NToB,
|
||||||
@@ -84,6 +91,7 @@ public:
|
|||||||
|
|
||||||
void drain_stq();
|
void drain_stq();
|
||||||
bool stq_empty() { return st_q.size() == 0; };
|
bool stq_empty() { return st_q.size() == 0; };
|
||||||
|
void flush_icache();
|
||||||
|
|
||||||
const cfg_t &get_cfg() const { return cfg; }
|
const cfg_t &get_cfg() const { return cfg; }
|
||||||
const std::map<size_t, processor_t*>& get_harts() const { return harts; }
|
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];
|
tile_t* tile = tiles[hartid];
|
||||||
chipyard_simif_t* simif = tile->simif;
|
chipyard_simif_t* simif = tile->simif;
|
||||||
processor_t* proc = tile->proc;
|
processor_t* proc = tile->proc;
|
||||||
if (!simif->htif && tsi) {
|
#if defined(SPIKETILE_HTIF_TSI)
|
||||||
simif->htif = (htif_t*) tsi;
|
if (!simif->htif && tsi)
|
||||||
}
|
simif->htif = tsi;
|
||||||
|
#elif defined(SPIKETILE_HTIF_DTM)
|
||||||
|
if (!simif->htif && dtm)
|
||||||
|
simif->htif = dtm;
|
||||||
|
#endif
|
||||||
|
|
||||||
simif->cycle = cycle;
|
simif->cycle = cycle;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
proc->halt_request = proc->HR_REGULAR;
|
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_MTIP, mtip ? MIP_MTIP : 0);
|
||||||
proc->get_state()->mip->backdoor_write_with_mask(MIP_MSIP, msip ? MIP_MSIP : 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);
|
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) {
|
bool chipyard_simif_t::reservable(reg_t addr) {
|
||||||
for (auto& r: cacheables) {
|
for (auto& r: cacheables) {
|
||||||
if (addr >= r.base && addr < r.base + r.size) {
|
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;
|
mmio_st = type == STORE;
|
||||||
if (type == STORE) {
|
if (type == STORE) {
|
||||||
assert(len <= 8);
|
assert(len <= 8);
|
||||||
|
mmio_stdata = 0;
|
||||||
memcpy(&mmio_stdata, store_bytes, len);
|
memcpy(&mmio_stdata, store_bytes, len);
|
||||||
}
|
}
|
||||||
mmio_len = len;
|
mmio_len = len;
|
||||||
@@ -1075,7 +1097,16 @@ void spike_thread_main(void* arg)
|
|||||||
tile->max_insns = 0;
|
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 old_minstret = state->minstret->read();
|
||||||
uint64_t tohost_addr = simif->htif ? simif->htif->get_tohost_addr() : 0;
|
uint64_t tohost_addr = simif->htif ? simif->htif->get_tohost_addr() : 0;
|
||||||
uint64_t fromhost_addr = simif->htif ? simif->htif->get_fromhost_addr() : 0;
|
uint64_t fromhost_addr = simif->htif ? simif->htif->get_fromhost_addr() : 0;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#define SPIKETILE_HTIF_DTM
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#define SPIKETILE_HTIF_TSI
|
||||||
@@ -252,7 +252,7 @@ class WithSimDebug extends OverrideHarnessBinder({
|
|||||||
case d: ClockedDMIIO =>
|
case d: ClockedDMIIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.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 =>
|
case j: JTAGChipIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.B }
|
when (dtm_success) { th.success := true.B }
|
||||||
@@ -262,7 +262,8 @@ class WithSimDebug extends OverrideHarnessBinder({
|
|||||||
j.TCK := jtag_wire.TCK
|
j.TCK := jtag_wire.TCK
|
||||||
j.TMS := jtag_wire.TMS
|
j.TMS := jtag_wire.TMS
|
||||||
j.TDI := jtag_wire.TDI
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import chisel3.experimental.{IntParam, StringParam, IO}
|
|||||||
import org.chipsalliance.cde.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.devices.debug.{ExportDebug, DMI}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.rocket._
|
import freechips.rocketchip.rocket._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
@@ -189,7 +190,8 @@ class SpikeBlackBox(
|
|||||||
readonly_uncacheable_regions: String,
|
readonly_uncacheable_regions: String,
|
||||||
executable_regions: String,
|
executable_regions: String,
|
||||||
tcm_base: BigInt,
|
tcm_base: BigInt,
|
||||||
tcm_size: BigInt) extends BlackBox(Map(
|
tcm_size: BigInt,
|
||||||
|
use_dtm: Boolean) extends BlackBox(Map(
|
||||||
"HARTID" -> IntParam(hartId),
|
"HARTID" -> IntParam(hartId),
|
||||||
"ISA" -> StringParam(isa),
|
"ISA" -> StringParam(isa),
|
||||||
"PMPREGIONS" -> IntParam(pmpregions),
|
"PMPREGIONS" -> IntParam(pmpregions),
|
||||||
@@ -302,7 +304,11 @@ class SpikeBlackBox(
|
|||||||
})
|
})
|
||||||
addResource("/vsrc/spiketile.v")
|
addResource("/vsrc/spiketile.v")
|
||||||
addResource("/csrc/spiketile.cc")
|
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) {
|
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 (dcache_tl, dcacheEdge) = outer.dcacheNode.out(0)
|
||||||
val (mmio_tl, mmioEdge) = outer.mmioNode.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,
|
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
|
||||||
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
|
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
|
||||||
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
|
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
|
||||||
tileParams.dcache.get.nMSHRs,
|
tileParams.dcache.get.nMSHRs,
|
||||||
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
|
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
|
||||||
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
|
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
|
spike.io.clock := clock.asBool
|
||||||
val cycle = RegInit(0.U(64.W))
|
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
|
spike.io.mmio.a.ready := mmio_tl.a.ready
|
||||||
mmio_tl.a.valid := spike.io.mmio.a.valid
|
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,
|
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.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)
|
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ class SpikeConfig extends Config(
|
|||||||
new chipyard.WithNSpikeCores(1) ++
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
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
|
// Avoids polling on the UART registers
|
||||||
class SpikeFastUARTConfig extends Config(
|
class SpikeFastUARTConfig extends Config(
|
||||||
new chipyard.WithNSpikeCores(1) ++
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
|
|||||||
Submodule generators/testchipip updated: ee47d2ea20...da5bf77b6e
Reference in New Issue
Block a user