Add support for TightlyCoupledMemory for SpikeTile

This commit is contained in:
Jerry Zhao
2023-03-25 21:41:40 -07:00
parent c1d609a03c
commit 298aadafc5
4 changed files with 351 additions and 67 deletions

View File

@@ -6,6 +6,9 @@
#include <sstream>
#include <vpi_user.h>
#include <svdpi.h>
#include "testchip_tsi.h"
extern testchip_tsi_t* tsi;
enum transfer_t {
NToB,
@@ -73,6 +76,12 @@ public:
void dcache_b(uint64_t address, uint64_t source, int param);
bool dcache_c(uint64_t *address, uint64_t* source, int* param, unsigned char* voluntary, unsigned char* has_data, uint64_t* data[8]);
void dcache_d(uint64_t sourceid, uint64_t data[8], unsigned char has_data, unsigned char grantack);
void tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size);
bool tcm_d(uint64_t *data);
void loadmem(const char* fname);
void drain_stq();
bool stq_empty() { return st_q.size() == 0; };
@@ -86,9 +95,13 @@ public:
char* readonly_uncacheable,
char* executable,
size_t icache_sourceids,
size_t dcache_sourceids);
size_t dcache_sourceids,
size_t tcm_base,
size_t tcm_size);
uint64_t cycle;
bool use_stq;
htif_t *htif;
bool fast_clint;
private:
bool handle_cache_access(reg_t addr, size_t len,
uint8_t* load_bytes,
@@ -133,6 +146,11 @@ private:
uint64_t mmio_stdata;
size_t mmio_len;
uint64_t mmio_lddata;
uint64_t tcm_base;
uint64_t tcm_size;
uint8_t* tcm;
std::vector<uint64_t> tcm_q;
};
class tile_t {
@@ -163,6 +181,7 @@ extern "C" void spike_tile(int hartid, char* isa,
int dcache_sets, int dcache_ways,
char* cacheable, char* uncacheable, char* readonly_uncacheable, char* executable,
int icache_sourceids, int dcache_sourceids,
long long int tcm_base, long long int tcm_size,
long long int reset_vector,
long long int ipc,
long long int cycle,
@@ -237,7 +256,18 @@ extern "C" void spike_tile(int hartid, char* isa,
int* mmio_a_size,
unsigned char mmio_d_valid,
long long int mmio_d_data
long long int mmio_d_data,
unsigned char tcm_a_valid,
long long int tcm_a_address,
long long int tcm_a_data,
int tcm_a_mask,
int tcm_a_opcode,
int tcm_a_size,
unsigned char* tcm_d_valid,
unsigned char tcm_d_ready,
long long int* tcm_d_data
)
{
if (!host) {
@@ -251,7 +281,8 @@ extern "C" void spike_tile(int hartid, char* isa,
chipyard_simif_t* simif = new chipyard_simif_t(icache_ways, icache_sets,
dcache_ways, dcache_sets,
cacheable, uncacheable, readonly_uncacheable, executable,
icache_sourceids, dcache_sourceids);
icache_sourceids, dcache_sourceids,
tcm_base, tcm_size);
std::string* isastr = new std::string(isa);
cfg_t* cfg = new cfg_t(std::make_pair(0, 0),
nullptr,
@@ -264,7 +295,7 @@ extern "C" void spike_tile(int hartid, char* isa,
std::vector<mem_cfg_t>(),
std::vector<size_t>(),
false,
0);
0);
processor_t* p = new processor_t(isa_parser,
cfg,
simif,
@@ -278,6 +309,7 @@ extern "C" void spike_tile(int hartid, char* isa,
s_vpi_vlog_info vinfo;
if (!vpi_get_vlog_info(&vinfo))
abort();
std::string loadmem_file = "";
for (int i = 1; i < vinfo.argc; i++) {
std::string arg(vinfo.argv[i]);
if (arg == "+spike-debug") {
@@ -286,7 +318,15 @@ extern "C" void spike_tile(int hartid, char* isa,
if (arg == "+spike-stq") {
simif->use_stq = true;
}
if (arg.find("+loadmem=") == 0) {
loadmem_file = arg.substr(strlen("+loadmem="));
}
if (arg == "+spike-fast-clint") {
simif->fast_clint = true;
}
}
if (loadmem_file != "" && tcm_size > 0)
simif->loadmem(loadmem_file.c_str());
p->reset();
p->get_state()->pc = reset_vector;
@@ -296,6 +336,9 @@ 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;
}
simif->cycle = cycle;
if (debug) {
@@ -357,6 +400,13 @@ extern "C" void spike_tile(int hartid, char* isa,
if (mmio_d_valid) {
simif->mmio_d(mmio_d_data);
}
if (tcm_a_valid) {
simif->tcm_a(tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size);
}
if (tcm_d_ready) {
*tcm_d_valid = simif->tcm_d((uint64_t*)tcm_d_data);
}
}
@@ -369,14 +419,20 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
char* readonly_uncacheable,
char* executable,
size_t ic_sourceids,
size_t dc_sourceids
size_t dc_sourceids,
size_t tcm_base,
size_t tcm_size
) :
cycle(0),
use_stq(false),
htif(nullptr),
fast_clint(false),
icache_ways(icache_ways),
icache_sets(icache_sets),
dcache_ways(dcache_ways),
dcache_sets(dcache_sets),
tcm_base(tcm_base),
tcm_size(tcm_size),
mmio_valid(false),
mmio_inflight(false)
{
@@ -432,6 +488,8 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
uint64_t size_int = std::stoul(size);
executables.push_back(mem_region_t { base_int, size_int });
}
tcm = (uint8_t*)malloc(tcm_size);
}
bool chipyard_simif_t::reservable(reg_t addr) {
@@ -440,12 +498,20 @@ bool chipyard_simif_t::reservable(reg_t addr) {
return true;
}
}
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
return true;
}
return false;
}
bool chipyard_simif_t::mmio_fetch(reg_t addr, size_t len, uint8_t* bytes) {
bool executable = false;
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
memcpy(bytes, tcm + addr - tcm_base, len);
return true;
}
for (auto& r: executables) {
if (addr >= r.base && addr + len <= r.base + r.size) {
executable = true;
@@ -466,6 +532,10 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
bool found = false;
bool cacheable = false;
bool readonly = false;
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
memcpy(bytes, tcm + addr - tcm_base, len);
return true;
}
for (auto& r: cacheables) {
if (addr >= r.base && addr + len <= r.base + r.size) {
cacheable = true;
@@ -829,9 +899,14 @@ bool chipyard_simif_t::dcache_c(uint64_t* address, uint64_t* source, int* param,
}
bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) {
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
memcpy(tcm + addr - tcm_base, bytes, len);
return true;
}
bool found = false;
bool cacheable = false;
for (auto& r: cacheables) {
for (auto& r: cacheables) {
if (addr >= r.base && addr + len <= r.base + r.size) {
cacheable = true;
found = true;
@@ -899,11 +974,64 @@ void chipyard_simif_t::dcache_d(uint64_t sourceid, uint64_t data[8], unsigned ch
}
}
void chipyard_simif_t::tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size) {
bool load = opcode == 4;
uint64_t rdata = 0;
memcpy(&rdata, tcm + address - tcm_base, 8);
tcm_q.push_back(rdata);
if (!load) {
for (size_t i = 0; i < 8; i++) {
if ((mask >> i) & 1) {
memcpy(tcm + address - tcm_base + i, ((uint8_t*)&data) + i, 1);
}
}
}
}
bool chipyard_simif_t::tcm_d(uint64_t* data) {
if (tcm_q.size() == 0)
return false;
*data = tcm_q[0];
tcm_q.erase(tcm_q.begin());
return true;
}
#define parse_nibble(c) ((c) >= 'a' ? (c)-'a'+10 : (c)-'0')
void chipyard_simif_t::loadmem(const char* fname) {
std::ifstream in(fname);
std::string line;
if (!in.is_open()) {
printf("SpikeTile couldn't open loadmem file %s\n", fname);
abort();
}
size_t fsize = 0;
size_t start = 0;
while (std::getline(in, line)) {
for (ssize_t i = line.length()-2, j = 0; i >= 0; i -= 2, j++) {
char byte = (parse_nibble(line[i]) << 4) | parse_nibble(line[i+1]);
ssize_t addr = (start + j) % tcm_size;
tcm[addr] = (uint8_t)byte;
}
start += line.length()/2;
fsize += line.length()/2;
if (fsize > tcm_size) {
fprintf(stderr, "Loadmem file is too large\n");
abort();
}
}
}
bool insn_should_fence(uint64_t bits) {
uint8_t opcode = bits & 0x7f;
return opcode == 0b0101111 || opcode == 0b0001111;
}
bool insn_is_wfi(uint64_t bits) {
return bits == 0x10500073;
}
void spike_thread_main(void* arg)
{
tile_t* tile = (tile_t*) arg;
@@ -913,12 +1041,30 @@ void spike_thread_main(void* arg)
}
while (tile->max_insns != 0) {
// TODO: Fences don't work
// uint64_t last_bits = tile->proc->get_last_bits();
//uint64_t last_bits = tile->proc->get_last_bits();
// if (insn_should_fence(last_bits) && !tile->simif->stq_empty()) {
// host->switch_to();
// }
uint64_t old_minstret = tile->proc->get_state()->minstret->read();
tile->proc->step(1);
tile->max_insns--;
if (tile->proc->is_waiting_for_interrupt()) {
if (tile->simif->fast_clint) {
tile->proc->get_state()->mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
}
tile->max_insns = 0;
}
if (tile->max_insns % 100 == 0) {
uint64_t tohost_addr = tile->simif->htif ? tile->simif->htif->get_tohost_addr() : 0;
uint64_t fromhost_addr = tile->simif->htif ? tile->simif->htif->get_fromhost_addr() : 0;
auto& mem_read = tile->proc->get_state()->log_mem_read;
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
if ((old_minstret == tile->proc->get_state()->minstret->read()) ||
(tohost_addr && mem_read_addr == tohost_addr) ||
(fromhost_addr && mem_read_addr == fromhost_addr)) {
tile->max_insns == 0;
}
}
tile->proc->get_state()->mcycle->write(tile->simif->cycle);
}
}

View File

@@ -13,6 +13,8 @@ import "DPI-C" function void spike_tile(input int hartid,
input string executable,
input int icache_sourceids,
input int dcache_sourceids,
input longint tcm_base,
input longint tcm_size,
input longint reset_vector,
input longint ipc,
input longint cycle,
@@ -89,7 +91,18 @@ import "DPI-C" function void spike_tile(input int hartid,
output int mmio_a_size,
input bit mmio_d_valid,
input longint mmio_d_data
input longint mmio_d_data,
input bit tcm_a_valid,
input longint tcm_a_address,
input longint tcm_a_data,
input int tcm_a_mask,
input int tcm_a_opcode,
input int tcm_a_size,
output bit tcm_d_valid,
input bit tcm_d_ready,
output longint tcm_d_data
);
@@ -106,7 +119,9 @@ module SpikeBlackBox #(
parameter READONLY_UNCACHEABLE,
parameter EXECUTABLE,
parameter ICACHE_SOURCEIDS,
parameter DCACHE_SOURCEIDS )(
parameter DCACHE_SOURCEIDS,
parameter TCM_BASE,
parameter TCM_SIZE)(
input clock,
input reset,
input [63:0] reset_vector,
@@ -185,7 +200,18 @@ module SpikeBlackBox #(
output [31:0] mmio_a_size,
input mmio_d_valid,
input [63:0] mmio_d_data
input [63:0] mmio_d_data,
input tcm_a_valid,
input [63:0] tcm_a_address,
input [63:0] tcm_a_data,
input [31:0] tcm_a_mask,
input [31:0] tcm_a_opcode,
input [31:0] tcm_a_size,
output tcm_d_valid,
input tcm_d_ready,
output [63:0] tcm_d_data
);
longint __insns_retired;
@@ -257,7 +283,13 @@ module SpikeBlackBox #(
reg [63:0] __dcache_c_data_6_reg;
reg [63:0] __dcache_c_data_7_reg;
wire __tcm_d_ready;
bit __tcm_d_valid;
longint __tcm_d_data;
reg __tcm_d_valid_reg;
reg [63:0] __tcm_d_data_reg;
always @(posedge clock) begin
@@ -322,12 +354,18 @@ module SpikeBlackBox #(
__dcache_c_data_6_reg <= 64'h0;
__dcache_c_data_7 = 64'h0;
__dcache_c_data_7_reg <= 64'h0;
__tcm_d_valid = 1'b0;
__tcm_d_valid_reg <= 1'b0;
__tcm_d_data = 64'h0;
__tcm_d_data_reg <= 64'h0;
spike_tile_reset(HARTID);
end else begin
spike_tile(HARTID, ISA, PMPREGIONS,
ICACHE_SETS, ICACHE_WAYS, DCACHE_SETS, DCACHE_WAYS,
CACHEABLE, UNCACHEABLE, READONLY_UNCACHEABLE, EXECUTABLE,
ICACHE_SOURCEIDS, DCACHE_SOURCEIDS,
TCM_BASE, TCM_SIZE,
reset_vector, ipc, cycle, __insns_retired,
debug, mtip, msip, meip, seip,
@@ -350,7 +388,10 @@ module SpikeBlackBox #(
dcache_d_data_4, dcache_d_data_5, dcache_d_data_6, dcache_d_data_7,
__mmio_a_ready, __mmio_a_valid, __mmio_a_address, __mmio_a_data, __mmio_a_store, __mmio_a_size,
mmio_d_valid, mmio_d_data
mmio_d_valid, mmio_d_data,
tcm_a_valid, tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size,
__tcm_d_valid, __tcm_d_ready, __tcm_d_data
);
__insns_retired_reg <= __insns_retired;
@@ -385,6 +426,10 @@ module SpikeBlackBox #(
__mmio_a_data_reg <= __mmio_a_data;
__mmio_a_store_reg <= __mmio_a_store;
__mmio_a_size_reg <= __mmio_a_size;
__tcm_d_valid_reg <= __tcm_d_valid;
__tcm_d_data_reg <= __tcm_d_data;
end
end // always @ (posedge clock)
assign insns_retired = __insns_retired_reg;
@@ -424,6 +469,8 @@ module SpikeBlackBox #(
assign mmio_a_size = __mmio_a_size_reg;
assign __mmio_a_ready = mmio_a_ready;
assign tcm_d_valid = __tcm_d_valid_reg;
assign tcm_d_data = __tcm_d_data_reg;
assign __tcm_d_ready = tcm_d_ready;
endmodule;

View File

@@ -15,8 +15,7 @@ import freechips.rocketchip.util._
import freechips.rocketchip.tile._
import freechips.rocketchip.prci.ClockSinkParameters
case class SpikeCoreParams(
) extends CoreParams {
case class SpikeCoreParams() extends CoreParams {
val useVM = true
val useHypervisor = false
val useSupervisor = true
@@ -79,7 +78,8 @@ case class SpikeTileParams(
hartId: Int = 0,
val core: SpikeCoreParams = SpikeCoreParams(),
icacheParams: ICacheParams = ICacheParams(nWays = 32),
dcacheParams: DCacheParams = DCacheParams(nWays = 32)
dcacheParams: DCacheParams = DCacheParams(nWays = 32),
tcmParams: Option[MasterPortParams] = None // tightly coupled memory
) extends InstantiableTileParams[SpikeTile]
{
val name = Some("spike_tile")
@@ -145,6 +145,27 @@ class SpikeTile(
sourceId = IdRange(0, 1),
requestFifo = true))))))
tlSlaveXbar.node :*= slaveNode
val tcmNode = spikeTileParams.tcmParams.map { tcmP =>
val device = new MemoryDevice
val base = AddressSet.misaligned(tcmP.base, tcmP.size)
val tcmNode = TLManagerNode(Seq(TLSlavePortParameters.v1(
managers = Seq(TLSlaveParameters.v1(
address = base,
resources = device.reg,
regionType = RegionType.IDEMPOTENT, // not cacheable
executable = true,
supportsGet = TransferSizes(1, 8),
supportsPutFull = TransferSizes(1, 8),
supportsPutPartial = TransferSizes(1, 8),
fifoId = Some(0)
)),
beatBytes = 8
)))
connectTLSlave(tcmNode := TLBuffer(), 8)
tcmNode
}
tlOtherMastersNode := TLBuffer() := tlMasterXbar.node
masterNode :=* tlOtherMastersNode
tlMasterXbar.node := TLWidthWidget(64) := TLBuffer():= icacheNode
@@ -166,7 +187,9 @@ class SpikeBlackBox(
cacheable_regions: String,
uncacheable_regions: String,
readonly_uncacheable_regions: String,
executable_regions: String) extends BlackBox(Map(
executable_regions: String,
tcm_base: BigInt,
tcm_size: BigInt) extends BlackBox(Map(
"HARTID" -> IntParam(hartId),
"ISA" -> StringParam(isa),
"PMPREGIONS" -> IntParam(pmpregions),
@@ -179,7 +202,9 @@ class SpikeBlackBox(
"UNCACHEABLE" -> StringParam(uncacheable_regions),
"READONLY_UNCACHEABLE" -> StringParam(readonly_uncacheable_regions),
"CACHEABLE" -> StringParam(cacheable_regions),
"EXECUTABLE" -> StringParam(executable_regions)
"EXECUTABLE" -> StringParam(executable_regions),
"TCM_BASE" -> IntParam(tcm_base),
"TCM_SIZE" -> IntParam(tcm_size)
)) with HasBlackBoxResource {
val io = IO(new Bundle {
@@ -258,6 +283,22 @@ class SpikeBlackBox(
val data = Input(UInt(64.W))
}
}
val tcm = new Bundle {
val a = new Bundle {
val valid = Input(Bool())
val address = Input(UInt(64.W))
val data = Input(UInt(64.W))
val mask = Input(UInt(32.W))
val opcode = Input(UInt(32.W))
val size = Input(UInt(32.W))
}
val d = new Bundle {
val valid = Output(Bool())
val ready = Input(Bool())
val data = Output(UInt(64.W))
}
}
})
addResource("/vsrc/spiketile.v")
addResource("/csrc/spiketile.cc")
@@ -289,7 +330,10 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
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))
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0)
))
spike.io.clock := clock.asBool
val cycle = RegInit(0.U(64.W))
cycle := cycle + 1.U
@@ -304,64 +348,63 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
spike.io.msip := int_bundle.msip
spike.io.meip := int_bundle.meip
spike.io.seip := int_bundle.seip.get
spike.io.ipc := PlusArg("spike-ipc", 10000, width=64)
spike.io.ipc := PlusArg("spike-ipc", width=32, default=10000)
val blockBits = log2Ceil(p(CacheBlockBytes))
val icache_a_q = Module(new Queue(new TLBundleA(icacheEdge.bundle), 1, flow=true, pipe=true))
spike.io.icache.a.ready := icache_a_q.io.enq.ready && icache_a_q.io.count === 0.U
icache_tl.a <> icache_a_q.io.deq
icache_a_q.io.enq.valid := spike.io.icache.a.valid
icache_a_q.io.enq.bits := icacheEdge.Get(
spike.io.icache.a.ready := icache_tl.a.ready
icache_tl.a.valid := spike.io.icache.a.valid
icache_tl.a.bits := icacheEdge.Get(
fromSource = spike.io.icache.a.sourceid,
toAddress = (spike.io.icache.a.address >> blockBits) << blockBits,
lgSize = blockBits.U)._2
icache_tl.d.ready := true.B
spike.io.icache.d.valid := icache_tl.d.valid
spike.io.icache.d.sourceid := icache_tl.d.bits.source
spike.io.icache.d.data := icache_tl.d.bits.data.asTypeOf(Vec(8, UInt(64.W)))
val dcache_a_q = Module(new Queue(new TLBundleA(dcacheEdge.bundle), 1, flow=true, pipe=true))
spike.io.dcache.a.ready := dcache_a_q.io.enq.ready && dcache_a_q.io.count === 0.U
dcache_tl.a <> dcache_a_q.io.deq
dcache_a_q.io.enq.valid := spike.io.dcache.a.valid
dcache_a_q.io.enq.bits := dcacheEdge.AcquireBlock(
fromSource = spike.io.dcache.a.sourceid,
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
lgSize = blockBits.U,
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
spike.io.dcache.a.ready := dcache_tl.a.ready
dcache_tl.a.valid := spike.io.dcache.a.valid
if (dcacheEdge.manager.anySupportAcquireB) {
dcache_tl.a.bits := dcacheEdge.AcquireBlock(
fromSource = spike.io.dcache.a.sourceid,
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
lgSize = blockBits.U,
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
} else {
dcache_tl.a.bits := DontCare
}
dcache_tl.b.ready := true.B
spike.io.dcache.b.valid := dcache_tl.b.valid
spike.io.dcache.b.address := dcache_tl.b.bits.address
spike.io.dcache.b.source := dcache_tl.b.bits.source
spike.io.dcache.b.param := dcache_tl.b.bits.param
val dcache_c_q = Module(new Queue(new TLBundleC(dcacheEdge.bundle), 1, flow=true, pipe=true))
spike.io.dcache.c.ready := dcache_c_q.io.enq.ready && dcache_c_q.io.count === 0.U
dcache_tl.c <> dcache_c_q.io.deq
dcache_c_q.io.enq.valid := spike.io.dcache.c.valid
dcache_c_q.io.enq.bits := Mux(spike.io.dcache.c.voluntary,
dcacheEdge.Release(
fromSource = spike.io.dcache.c.sourceid,
toAddress = spike.io.dcache.c.address,
lgSize = blockBits.U,
shrinkPermissions = spike.io.dcache.c.param,
data = spike.io.dcache.c.data.asUInt)._2,
Mux(spike.io.dcache.c.has_data,
dcacheEdge.ProbeAck(
spike.io.dcache.c.ready := dcache_tl.c.ready
dcache_tl.c.valid := spike.io.dcache.c.valid
if (dcacheEdge.manager.anySupportAcquireB) {
dcache_tl.c.bits := Mux(spike.io.dcache.c.voluntary,
dcacheEdge.Release(
fromSource = spike.io.dcache.c.sourceid,
toAddress = spike.io.dcache.c.address,
lgSize = blockBits.U,
reportPermissions = spike.io.dcache.c.param,
data = spike.io.dcache.c.data.asUInt),
dcacheEdge.ProbeAck(
fromSource = spike.io.dcache.c.sourceid,
toAddress = spike.io.dcache.c.address,
lgSize = blockBits.U,
reportPermissions = spike.io.dcache.c.param)
))
shrinkPermissions = spike.io.dcache.c.param,
data = spike.io.dcache.c.data.asUInt)._2,
Mux(spike.io.dcache.c.has_data,
dcacheEdge.ProbeAck(
fromSource = spike.io.dcache.c.sourceid,
toAddress = spike.io.dcache.c.address,
lgSize = blockBits.U,
reportPermissions = spike.io.dcache.c.param,
data = spike.io.dcache.c.data.asUInt),
dcacheEdge.ProbeAck(
fromSource = spike.io.dcache.c.sourceid,
toAddress = spike.io.dcache.c.address,
lgSize = blockBits.U,
reportPermissions = spike.io.dcache.c.param)
))
} else {
dcache_tl.c.bits := DontCare
}
val has_data = dcacheEdge.hasData(dcache_tl.d.bits)
val should_finish = dcacheEdge.isRequest(dcache_tl.d.bits)
@@ -376,12 +419,10 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
dcache_tl.e.valid := dcache_tl.d.valid && should_finish
dcache_tl.e.bits := dcacheEdge.GrantAck(dcache_tl.d.bits)
val mmio_a_q = Module(new Queue(new TLBundleA(mmioEdge.bundle), 1, flow=true, pipe=true))
spike.io.mmio.a.ready := mmio_a_q.io.enq.ready && mmio_a_q.io.count === 0.U
mmio_tl.a <> mmio_a_q.io.deq
mmio_a_q.io.enq.valid := spike.io.mmio.a.valid
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 })
mmio_a_q.io.enq.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.Get(0.U, spike.io.mmio.a.address, log_size)._2)
@@ -389,9 +430,33 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
spike.io.mmio.d.valid := mmio_tl.d.valid
spike.io.mmio.d.data := mmio_tl.d.bits.data
spike.io.tcm := DontCare
spike.io.tcm.a.valid := false.B
spike.io.tcm.d.ready := true.B
outer.tcmNode.map { tcmNode =>
val (tcm_tl, tcmEdge) = tcmNode.in(0)
val debug_tcm_tl = WireInit(tcm_tl)
dontTouch(debug_tcm_tl)
tcm_tl.a.ready := true.B
spike.io.tcm.a.valid := tcm_tl.a.valid
spike.io.tcm.a.address := tcm_tl.a.bits.address
spike.io.tcm.a.data := tcm_tl.a.bits.data
spike.io.tcm.a.mask := tcm_tl.a.bits.mask
spike.io.tcm.a.opcode := tcm_tl.a.bits.opcode
spike.io.tcm.a.size := tcm_tl.a.bits.size
spike.io.tcm.d.ready := tcm_tl.d.ready
tcm_tl.d.bits := tcmEdge.AccessAck(RegNext(tcm_tl.a.bits))
when (RegNext(tcm_tl.a.bits.opcode === TLMessages.Get)) {
tcm_tl.d.bits.opcode := TLMessages.AccessAckData
}
tcm_tl.d.valid := spike.io.tcm.d.valid
tcm_tl.d.bits.data := spike.io.tcm.d.data
}
}
class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
class WithNSpikeCores(n: Int = 1, tileParams: SpikeTileParams = SpikeTileParams(),
overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
// Calculate the next available hart ID (since hart ID cannot be duplicated)
val prev = up(TilesLocated(InSubsystem), site)
@@ -399,8 +464,21 @@ class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends
// Create TileAttachParams for every core to be instantiated
(0 until n).map { i =>
SpikeTileAttachParams(
tileParams = SpikeTileParams(hartId = i + idOffset)
tileParams = tileParams.copy(hartId = i + idOffset)
)
} ++ prev
}
})
class WithSpikeTCM extends Config((site, here, up) => {
case TilesLocated(InSubsystem) => {
val prev = up(TilesLocated(InSubsystem))
require(prev.size == 1)
val spike = prev(0).asInstanceOf[SpikeTileAttachParams]
Seq(spike.copy(tileParams = spike.tileParams.copy(
tcmParams = Some(up(ExtMem).get.master)
)))
}
case ExtMem => None
case BankedL2Key => up(BankedL2Key).copy(nBanks = 0)
})

View File

@@ -1,6 +1,7 @@
package chipyard
import freechips.rocketchip.config.{Config}
import freechips.rocketchip.rocket.{DCacheParams}
// Configs which instantiate a Spike-simulated
// tile that interacts with the Chipyard SoC
@@ -14,6 +15,18 @@ class SpikeConfig extends Config(
class SpikeFastUARTConfig extends Config(
new chipyard.WithNSpikeCores(1) ++
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
new chipyard.config.WithMemoryBusFrequency(1) ++
new chipyard.config.WithPeripheryBusFrequency(1) ++
new chipyard.config.WithMemoryBusFrequency(2) ++
new chipyard.config.WithPeripheryBusFrequency(2) ++
new chipyard.config.AbstractConfig)
// Makes the UART fast, also builds no L2 and a ludicrous L1D
class SpikeUltraFastConfig extends Config(
new chipyard.WithSpikeTCM ++
new chipyard.WithNSpikeCores(1) ++
new testchipip.WithSerialPBusMem ++
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
new chipyard.config.WithMemoryBusFrequency(2) ++
new chipyard.config.WithPeripheryBusFrequency(2) ++
new chipyard.config.WithBroadcastManager ++
new chipyard.config.AbstractConfig)