Skip to content

Commit

Permalink
Pluggable memory bus cache and sequential instruction prefetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
martonbognar committed Jan 31, 2024
1 parent f16ea5c commit a5b77ab
Show file tree
Hide file tree
Showing 27 changed files with 840 additions and 650 deletions.
2 changes: 1 addition & 1 deletion sim/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ $(EXE_FILE): $(BUILD_DIR)/$(VERILATOR_NAME).mk main.cpp
make -C $(BUILD_DIR) -f $(VERILATOR_NAME).mk $(EXE_NAME)

$(BUILD_DIR)/$(VERILATOR_NAME).mk: $(VERILOG_INPUT)
verilator --cc --exe --trace -O3 -CFLAGS "-O3 -std=c++11" -Wno-WIDTH -Wno-UNOPTFLAT -Wno-CMPCONST -Wno-UNSIGNED -Mdir $(BUILD_DIR) $(VERILOG_INPUT) main.cpp -o $(EXE_NAME)
verilator --cc --exe --trace -O3 -CFLAGS "-O3 -std=c++20" -Wno-WIDTH -Wno-UNOPTFLAT -Wno-CMPCONST -Wno-UNSIGNED -Mdir $(BUILD_DIR) $(VERILOG_INPUT) main.cpp -o $(EXE_NAME)

$(VERILOG_INPUT): $(BASE_DIR)/$(VERILOG_FILE_NAME)
mkdir -p $(@D)
Expand Down
63 changes: 47 additions & 16 deletions sim/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <verilated.h>
#include <verilated_vcd_c.h>

#include <bit>

#include <memory>
#include <vector>
#include <iostream>
Expand All @@ -20,6 +22,9 @@ const int CLOCK_PERIOD = 1/(CLOCK_FREQUENCY*TIMESCALE);

const std::uint64_t MAX_CYCLES = 1000000000ULL;

const unsigned int MEMBUS_WORDS = 4;
const unsigned int MEMBUS_OFFSET = 2 + std::bit_width(MEMBUS_WORDS) - 1;

class Memory
{
public:
Expand Down Expand Up @@ -56,7 +61,9 @@ class Memory

if (nextReadCycle_ == cycle)
{
top_.io_axi_r_payload_data = nextReadWord_;
for (unsigned i = 0; i < MEMBUS_WORDS; ++i) {
top_.io_axi_r_payload_data[i] = nextReadData_[i];
}
top_.io_axi_r_payload_id = nextReadId_;
top_.io_axi_r_payload_last = true;
top_.io_axi_r_valid = true;
Expand All @@ -77,7 +84,7 @@ class Memory
}
else
{
nextReadWord_ = read(top_.io_axi_arw_payload_addr);
read(top_.io_axi_arw_payload_addr, nextReadData_);
nextReadCycle_ = cycle + 1;
nextReadId_ = top_.io_axi_arw_payload_id;
}
Expand All @@ -88,43 +95,67 @@ class Memory

using Address = std::uint32_t;
using Word = std::uint32_t;
using Mask = std::uint8_t;
using Mask = std::uint32_t;

Word read(Address address)
void read(Address address, WDataOutP value)
{
ensureEnoughMemory(address);
return memory_[(address >> 2)];

auto baseAddress = (address >> MEMBUS_OFFSET) << (MEMBUS_OFFSET - 2);

for (unsigned i = 0; i < MEMBUS_WORDS; ++i) {
value[i] = memory_[baseAddress + i];
}
}

void write(Address address, Mask mask, Word value)
void write(Address address, Mask mask, WDataInP value)
{
ensureEnoughMemory(address);

auto bitMask = Word{0};
if (mask & 0x1) bitMask |= 0x000000ff;
if (mask & 0x2) bitMask |= 0x0000ff00;
if (mask & 0x4) bitMask |= 0x00ff0000;
if (mask & 0x8) bitMask |= 0xff000000;
unsigned extra = 0;
for (unsigned i = 0; i < MEMBUS_WORDS; ++i) {
if (mask & (1 << (4 * i + 0))) {
extra = i;
bitMask |= 0x000000ff;
}
if (mask & (1 << (4 * i + 1))) {
extra = i;
bitMask |= 0x0000ff00;
}
if (mask & (1 << (4 * i + 2))) {
extra = i;
bitMask |= 0x00ff0000;
}
if (mask & (1 << (4 * i + 3))) {
extra = i;
bitMask |= 0xff000000;
}
}

auto baseAddress = (address >> MEMBUS_OFFSET) << (MEMBUS_OFFSET - 2);

auto& memoryValue = memory_[(address >> 2)];
auto& memoryValue = memory_[baseAddress + extra];
memoryValue &= ~bitMask;
memoryValue |= value & bitMask;
memoryValue |= value[0] & bitMask;
}

void ensureEnoughMemory(Address address)
{
if ((address >> 2) >= memory_.size())
auto baseAddress = ((address >> MEMBUS_OFFSET) + 1) << (MEMBUS_OFFSET - 2);

if ((baseAddress) >= memory_.size())
{
memory_.reserve((address >> 2) + 1);
memory_.reserve(baseAddress + 1);

while ((address >> 2) >= memory_.size())
while ((baseAddress) >= memory_.size())
memory_.push_back(0xcafebabe);
}
}

VCore& top_;
std::vector<Word> memory_;
Word nextReadWord_;
uint32_t nextReadData_[MEMBUS_WORDS];
vluint64_t nextReadCycle_ = 0;
vluint8_t nextReadId_;
};
Expand Down
13 changes: 9 additions & 4 deletions src/main/scala/riscv/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,25 @@ object BaseIsa {

class Config(val baseIsa: BaseIsa, val debug: Boolean = true) {
def xlen = baseIsa.xlen
def numRegs = baseIsa.xlen
def numRegs = baseIsa.numRegs

def memBusWidth: Int = 128

def ibusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
dataWidth = baseIsa.xlen,
idWidth = 2,
dataWidth = memBusWidth,
readWrite = false
)
def readDbusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
dataWidth = baseIsa.xlen,
idWidth = 2,
dataWidth = memBusWidth,
readWrite = false
)
def dbusConfig = MemBusConfig(
addressWidth = baseIsa.xlen,
dataWidth = baseIsa.xlen
idWidth = 2,
dataWidth = memBusWidth
)
}
36 changes: 25 additions & 11 deletions src/main/scala/riscv/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,25 @@ object createStaticPipeline {
)
}

val backbone = new memory.StaticMemoryBackbone

val prefetcher = new memory.SequentialInstructionPrefetcher()

pipeline.addPlugins(
Seq(
new StaticMemoryBackbone,
new Fetcher(pipeline.fetch),
backbone,
new memory.Fetcher(pipeline.fetch),
new Decoder(pipeline.decode),
new RegisterFileAccessor(pipeline.decode, pipeline.writeback),
new IntAlu(Set(pipeline.execute)),
new Shifter(Set(pipeline.execute)),
new Lsu(Set(pipeline.memory), Seq(pipeline.memory), pipeline.memory),
new memory.Lsu(Set(pipeline.memory), Seq(pipeline.memory), pipeline.memory),
new BranchUnit(Set(pipeline.execute)),
new PcManager(0x80000000L),
new BranchTargetPredictor(pipeline.fetch, pipeline.execute, 8, conf.xlen),
prefetcher,
new Cache(sets = 2, ways = 2, backbone.filterIBus, Some(prefetcher)),
new Cache(sets = 8, ways = 2, backbone.filterDBus),
new CsrFile(pipeline.writeback, pipeline.writeback), // TODO: ugly
new Timers,
new MachineMode(pipeline.execute),
Expand Down Expand Up @@ -201,21 +208,25 @@ object createDynamicPipeline {
val loadStage3 = new Stage("LOAD3")
override val loadStages: Seq[Stage] = Seq(loadStage1, loadStage2, loadStage3)
override val retirementStage = new Stage("RET")
override val unorderedStages: Seq[Stage] = rsStages ++ loadStages
override val stages = issuePipeline.stages ++ unorderedStages :+ retirementStage
override val parallelStages: Seq[Stage] = rsStages ++ loadStages
override val stages = issuePipeline.stages ++ parallelStages :+ retirementStage
override val backbone =
new memory.DynamicMemoryBackbone(
loadStages.size + 1
) // +1 for write stage (which also uses an ID currently)
}

pipeline.issuePipeline.addPlugins(
Seq(
new scheduling.static.Scheduler(canStallExternally = true),
new scheduling.static.PcManager(0x80000000L),
new DynamicMemoryBackbone(
pipeline.loadStages.size + 1
), // +1 for write stage (which also uses an ID currently)
new Fetcher(pipeline.issuePipeline.fetch)
pipeline.backbone,
new memory.Fetcher(pipeline.issuePipeline.fetch)
)
)

val prefetcher = new memory.SequentialInstructionPrefetcher()

pipeline.addPlugins(
Seq(
new Decoder(pipeline.issuePipeline.decode), // TODO: ugly alert!!
Expand All @@ -228,7 +239,7 @@ object createDynamicPipeline {
readStage = pipeline.issuePipeline.decode,
writeStage = pipeline.retirementStage
),
new Lsu(
new memory.Lsu(
Set(pipeline.intAlu1, pipeline.intAlu2, pipeline.intAlu3, pipeline.intAlu4),
pipeline.loadStages,
pipeline.retirementStage
Expand All @@ -239,6 +250,9 @@ object createDynamicPipeline {
8,
conf.xlen
),
prefetcher,
new Cache(sets = 2, ways = 2, pipeline.backbone.filterIBus, Some(prefetcher)),
new Cache(sets = 8, ways = 2, pipeline.backbone.filterDBus),
new IntAlu(Set(pipeline.intAlu1, pipeline.intAlu2, pipeline.intAlu3, pipeline.intAlu4)),
new Shifter(Set(pipeline.intAlu1, pipeline.intAlu2, pipeline.intAlu3, pipeline.intAlu4)),
new MulDiv(Set(pipeline.intMul1)),
Expand Down Expand Up @@ -299,7 +313,7 @@ object CoreDynamicSim {

object CoreDynamicExtMem {
def main(args: Array[String]) {
SpinalVerilog(SoC.dynamic(RamType.ExternalAxi4(10 MiB), 64))
SpinalVerilog(SoC.dynamic(RamType.ExternalAxi4(10 MiB), 32))
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/main/scala/riscv/DynamicPipeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ trait DynamicPipeline extends Pipeline {
var rob: ReorderBuffer = null
val loadStages: Seq[Stage]

val unorderedStages: Seq[Stage]
var components: Seq[Resettable] = null
val parallelStages: Seq[Stage]
var resettables: Seq[Resettable] = null
val backbone: MemoryService with Resettable

var pipelineRegs: Map[Stage, PipelineRegs] = null

Expand Down Expand Up @@ -44,7 +45,7 @@ trait DynamicPipeline extends Pipeline {

override def connectStages(): Unit = {

for (stage <- unorderedStages :+ retirementStage) {
for (stage <- parallelStages :+ retirementStage) {
stage.output(data.PC)
stage.output(data.IR)

Expand Down Expand Up @@ -86,7 +87,7 @@ trait DynamicPipeline extends Pipeline {

val issueStage = issuePipeline.stages.last

for (stage <- unorderedStages :+ retirementStage) {
for (stage <- parallelStages :+ retirementStage) {
// FIXME copy-pasted from StaticPipeline
for (valueData <- stage.lastValues.keys) {
if (!stage.outputs.contains(valueData)) {
Expand Down
Loading

0 comments on commit a5b77ab

Please sign in to comment.