Merge branch 'cacheburstmode' into main.

Cache burst mode is now working! It also uses the new RAM.
This commit is contained in:
slmnemo 2022-06-13 12:26:18 -07:00
commit c5d2037a7f
9 changed files with 124 additions and 43 deletions

View File

@ -67,6 +67,7 @@ add wave -hex /testbench/dut/core/ebu/HTRANS
add wave -hex /testbench/dut/core/ebu/HRDATA
add wave -hex /testbench/dut/core/ebu/HWRITE
add wave -hex /testbench/dut/core/ebu/HWDATA
add wave -hex /testbench/dut/core/ebu/HBURST
add wave -hex /testbench/dut/core/ebu/CaptureDataM
add wave -divider

View File

@ -473,6 +473,7 @@ add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusRead
add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusAdr
add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusAck
add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUBusHRDATA
add wave -noupdate -group ifu /testbench/dut/core/ifu/IFUTransComplete
add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillF
add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/CurrState
add wave -noupdate -group ifu -expand -group spill /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillDataLine0

View File

@ -45,6 +45,10 @@ module ahblite (
input logic IFUBusRead,
output logic [`XLEN-1:0] IFUBusHRDATA,
output logic IFUBusAck,
output logic IFUBusInit,
input logic [2:0] IFUBurstType,
input logic [1:0] IFUTransType,
input logic IFUTransComplete,
// Signals from Data Cache
input logic [`PA_BITS-1:0] LSUBusAdr,
input logic LSUBusRead,
@ -52,7 +56,11 @@ module ahblite (
input logic [`XLEN-1:0] LSUBusHWDATA,
output logic [`XLEN-1:0] LSUBusHRDATA,
input logic [2:0] LSUBusSize,
input logic [2:0] LSUBurstType,
input logic [1:0] LSUTransType,
input logic LSUTransComplete,
output logic LSUBusAck,
output logic LSUBusInit,
// AHB-Lite external signals
(* mark_debug = "true" *) input logic [`AHBW-1:0] HRDATA,
(* mark_debug = "true" *) input logic HREADY, HRESP,
@ -87,6 +95,9 @@ module ahblite (
// Data accesses have priority over instructions. However, if a data access comes
// while an instruction read is occuring, the instruction read finishes before
// the data access can take place.
// *** This is no longer true when adding burst mode. We need to finish the current
// read before doing another read. Need to work this out, but preliminarily we can
// store the current read type in a flop and use that to figure out what burst type to use.
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
@ -100,19 +111,21 @@ module ahblite (
// interface that might be used in place of the ahblite.
always_comb
case (BusState)
IDLE: if (LSUBusRead) NextBusState = MEMREAD; // Memory has priority over instructions
else if (LSUBusWrite)NextBusState = MEMWRITE;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
INSTRREAD: if (~HREADY) NextBusState = INSTRREAD;
else NextBusState = IDLE; // if (IFUBusRead still high) *** need to wait?
default: NextBusState = IDLE;
IDLE: if (LSUBusRead) NextBusState = MEMREAD; // Memory has priority over instructions
else if (LSUBusWrite) NextBusState = MEMWRITE;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMREAD: if (LSUTransComplete & IFUBusRead) NextBusState = INSTRREAD;
else if (LSUTransComplete) NextBusState = IDLE;
else NextBusState = MEMREAD;
MEMWRITE: if (LSUTransComplete & IFUBusRead) NextBusState = INSTRREAD;
else if (LSUTransComplete) NextBusState = IDLE;
else NextBusState = MEMWRITE;
INSTRREAD: if (IFUTransComplete & LSUBusRead) NextBusState = MEMREAD;
else if (IFUTransComplete & LSUBusWrite) NextBusState = MEMWRITE;
else if (IFUTransComplete) NextBusState = IDLE;
else NextBusState = INSTRREAD;
default: NextBusState = IDLE;
endcase
@ -122,7 +135,7 @@ module ahblite (
assign #1 HADDR = AccessAddress;
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
assign HSIZE = (GrantData) ? {1'b0, LSUBusSize[1:0]} : ISize;
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
assign HBURST = (GrantData) ? LSUBurstType : IFUBurstType; // If doing memory accesses, use LSUburst, else use Instruction burst.
/* Cache burst read/writes case statement (hopefully) WRAPS only have access to 4 wraps. X changes position based on HSIZE.
000: Single (SINGLE)
@ -133,15 +146,16 @@ module ahblite (
101: 8-beat incrementing burst (INCR8)
110: 16-beat wrapping burst (WRAP16) [wraps if X in 0X000000]
111: 16-beat incrementing burst (INCR16)
*/
*** Remove if not necessary
*/
assign HPROT = 4'b0011; // not used; see Section 3.7
assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
assign HTRANS = (GrantData) ? LSUTransType : IFUTransType; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
assign HMASTLOCK = 0; // no locking supported
assign HWRITE = NextBusState == MEMWRITE;
assign HWRITE = (NextBusState == MEMWRITE);
// delay write data by one cycle for
flop #(`XLEN) wdreg(HCLK, LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
flopen #(`XLEN) wdreg(HCLK, (LSUBusAck | LSUBusInit), LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
// delay signals for subword writes
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
@ -153,7 +167,9 @@ module ahblite (
assign IFUBusHRDATA = HRDATA;
assign LSUBusHRDATA = HRDATA;
assign IFUBusAck = (BusState == INSTRREAD) & (NextBusState != INSTRREAD);
assign LSUBusAck = (BusState == MEMREAD) & (NextBusState != MEMREAD) | (BusState == MEMWRITE) & (NextBusState != MEMWRITE);
assign IFUBusInit = (BusState != INSTRREAD) & (NextBusState == INSTRREAD);
assign LSUBusInit = (((BusState != MEMREAD) & (NextBusState == MEMREAD)) | (BusState != MEMWRITE) & (NextBusState == MEMWRITE));
assign IFUBusAck = HREADY & (BusState == INSTRREAD);
assign LSUBusAck = HREADY & ((BusState == MEMREAD) | (BusState == MEMWRITE));
endmodule

View File

@ -38,9 +38,13 @@ module ifu (
// Bus interface
(* mark_debug = "true" *) input logic [`XLEN-1:0] IFUBusHRDATA,
(* mark_debug = "true" *) input logic IFUBusAck,
(* mark_debug = "true" *) input logic IFUBusInit,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] IFUBusAdr,
(* mark_debug = "true" *) output logic IFUBusRead,
(* mark_debug = "true" *) output logic IFUStallF,
(* mark_debug = "true" *) output logic [2:0] IFUBurstType,
(* mark_debug = "true" *) output logic [1:0] IFUTransType,
(* mark_debug = "true" *) output logic IFUTransComplete,
(* mark_debug = "true" *) output logic [`XLEN-1:0] PCF,
// Execute
output logic [`XLEN-1:0] PCLinkE,
@ -201,8 +205,8 @@ module ifu (
busdp #(WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED)
busdp(.clk, .reset,
.LSUBusHRDATA(IFUBusHRDATA), .LSUBusAck(IFUBusAck), .LSUBusWrite(), .LSUBusWriteCrit(),
.LSUBusRead(IFUBusRead), .LSUBusSize(),
.LSUBusHRDATA(IFUBusHRDATA), .LSUBusAck(IFUBusAck), .LSUBusInit(IFUBusInit), .LSUBusWrite(), .LSUBusWriteCrit(),
.LSUBusRead(IFUBusRead), .LSUBusSize(), .LSUBurstType(IFUBurstType), .LSUTransType(IFUTransType), .LSUTransComplete(IFUTransComplete),
.LSUFunct3M(3'b010), .LSUBusAdr(IFUBusAdr), .DCacheBusAdr(ICacheBusAdr),
.WordCount(),
.DCacheFetchLine(ICacheFetchLine),

View File

@ -40,9 +40,13 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED)
// bus interface
input logic [`XLEN-1:0] LSUBusHRDATA,
input logic LSUBusAck,
input logic LSUBusInit,
output logic LSUBusWrite,
output logic LSUBusRead,
output logic [2:0] LSUBusSize,
output logic [2:0] LSUBusSize,
output logic [2:0] LSUBurstType,
output logic [1:0] LSUTransType, // For AHBLite
output logic LSUTransComplete,
input logic [2:0] LSUFunct3M,
output logic [`PA_BITS-1:0] LSUBusAdr, // ** change name to HADDR to make ahb lite.
output logic [LOGWPL-1:0] WordCount,
@ -66,13 +70,15 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED)
localparam integer WordCountThreshold = CACHE_ENABLED ? WORDSPERLINE - 1 : 0;
logic [`PA_BITS-1:0] LocalLSUBusAdr;
logic [LOGWPL-1:0] WordCountDelayed;
// *** implement flops as an array if feasbile; DCacheBusWriteData might be a problem
// *** better name than DCacheBusWriteData
genvar index;
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
logic [WORDSPERLINE-1:0] CaptureWord;
assign CaptureWord[index] = LSUBusAck & LSUBusRead & (index == WordCount);
assign CaptureWord[index] = LSUBusAck & LSUBusRead & (index == WordCountDelayed);
flopen #(`XLEN) fb(.clk, .en(CaptureWord[index]), .d(LSUBusHRDATA),
.q(DCacheBusWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
@ -83,6 +89,6 @@ module busdp #(parameter WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED)
busfsm #(WordCountThreshold, LOGWPL, CACHE_ENABLED) busfsm(
.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine,
.LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusWriteCrit, .LSUBusRead,
.DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount);
.LSUBusAck, .LSUBusInit, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusWriteCrit, .LSUBusRead,
.LSUBurstType, .LSUTransType, .LSUTransComplete, .DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount, .WordCountDelayed);
endmodule

View File

@ -41,6 +41,7 @@ module busfsm #(parameter integer WordCountThreshold,
input logic DCacheFetchLine,
input logic DCacheWriteLine,
input logic LSUBusAck,
input logic LSUBusInit, // This might be better as LSUBusLock, or to send this using LSUBusAck.
input logic CPUBusy,
input logic CacheableM,
@ -48,10 +49,13 @@ module busfsm #(parameter integer WordCountThreshold,
output logic LSUBusWrite,
output logic LSUBusWriteCrit,
output logic LSUBusRead,
output logic [2:0] LSUBurstType,
output logic LSUTransComplete,
output logic [1:0] LSUTransType,
output logic DCacheBusAck,
output logic BusCommittedM,
output logic SelUncachedAdr,
output logic [LOGWPL-1:0] WordCount);
output logic [LOGWPL-1:0] WordCount, WordCountDelayed);
@ -61,7 +65,8 @@ module busfsm #(parameter integer WordCountThreshold,
logic CntReset;
logic WordCountFlag;
logic [LOGWPL-1:0] NextWordCount;
logic UnCachedAccess;
logic UnCachedAccess, UnCachedRW;
logic [2:0] LocalBurstType;
typedef enum logic [2:0] {STATE_BUS_READY,
@ -75,18 +80,27 @@ module busfsm #(parameter integer WordCountThreshold,
(* mark_debug = "true" *) busstatetype BusCurrState, BusNextState;
// Used to send address for address stage of AHB.
flopenr #(LOGWPL)
WordCountReg(.clk(clk),
.reset(reset | CntReset),
.en(CntEn),
.d(NextWordCount),
.q(WordCount));
.q(WordCount));
// Used to store data from data phase of AHB.
flopenr #(LOGWPL)
WordCountDelayedReg(.clk(clk),
.reset(reset | CntReset),
.en(CntEn),
.d(WordCount),
.q(WordCountDelayed));
assign NextWordCount = WordCount + 1'b1;
assign WordCountFlag = (WordCount == WordCountThreshold[LOGWPL-1:0]);
assign CntEn = PreCntEn & LSUBusAck;
assign PreCntEn = (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_WRITE);
assign WordCountFlag = (WordCountDelayed == WordCountThreshold[LOGWPL-1:0]); // Detect when we are waiting on the final access.
assign CntEn = (PreCntEn & LSUBusAck | (LSUBusInit)) & ~WordCountFlag & ~UnCachedRW; // Want to count when doing cache accesses and we aren't wrapping up.
assign UnCachedAccess = ~CACHE_ENABLED | ~CacheableM;
@ -120,14 +134,29 @@ module busfsm #(parameter integer WordCountThreshold,
endcase
end
always_comb begin
case(WordCountThreshold)
0: LocalBurstType = 3'b000;
3: LocalBurstType = 3'b011; // INCR4
7: LocalBurstType = 3'b101; // INCR8
15: LocalBurstType = 3'b111; // INCR16
default: LocalBurstType = 3'b001; // INCR without end.
endcase
end
assign CntReset = BusCurrState == STATE_BUS_READY;
// Would these be better as always_comb statements or muxes?
assign LSUBurstType = (UnCachedRW) ? 3'b0 : LocalBurstType; // Don't want to use burst when doing an Uncached Access.
assign LSUTransComplete = (UnCachedRW) ? LSUBusAck : WordCountFlag & LSUBusAck;
// Use SEQ if not doing first word, NONSEQ if doing the first read/write, and IDLE if finishing up.
assign LSUTransType = (|WordCount) & ~UnCachedRW ? 2'b11 : (LSUBusRead | LSUBusWrite) & (~LSUTransComplete) ? 2'b10 : 2'b00;
// Reset if we aren't initiating a transaction or if we are finishing a transaction.
assign CntReset = BusCurrState == STATE_BUS_READY & ~(DCacheFetchLine | DCacheWriteLine) | LSUTransComplete;
assign BusStall = (BusCurrState == STATE_BUS_READY & ~IgnoreRequest & ((UnCachedAccess & (|LSURWM)) | DCacheFetchLine | DCacheWriteLine)) |
(BusCurrState == STATE_BUS_UNCACHED_WRITE) |
(BusCurrState == STATE_BUS_UNCACHED_READ) |
(BusCurrState == STATE_BUS_FETCH) |
(BusCurrState == STATE_BUS_WRITE);
assign PreCntEn = BusCurrState == STATE_BUS_FETCH | BusCurrState == STATE_BUS_WRITE;
assign UnCachedLSUBusWrite = (BusCurrState == STATE_BUS_READY & UnCachedAccess & LSURWM[0] & ~IgnoreRequest) |
(BusCurrState == STATE_BUS_UNCACHED_WRITE);
assign LSUBusWrite = UnCachedLSUBusWrite | (BusCurrState == STATE_BUS_WRITE);
@ -139,6 +168,10 @@ module busfsm #(parameter integer WordCountThreshold,
(BusCurrState == STATE_BUS_UNCACHED_READ);
assign LSUBusRead = UnCachedLSUBusRead | (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_READY & DCacheFetchLine);
// Makes bus only do uncached reads/writes when we actually do uncached reads/writes. Needed because CacheableM is 0 when flushing cache.
assign UnCachedRW = UnCachedLSUBusWrite | UnCachedLSUBusRead;
assign DCacheBusAck = (BusCurrState == STATE_BUS_FETCH & WordCountFlag & LSUBusAck) |
(BusCurrState == STATE_BUS_WRITE & WordCountFlag & LSUBusAck);
assign BusCommittedM = BusCurrState != STATE_BUS_READY;

View File

@ -66,9 +66,13 @@ module lsu (
(* mark_debug = "true" *) output logic LSUBusRead,
(* mark_debug = "true" *) output logic LSUBusWrite,
(* mark_debug = "true" *) input logic LSUBusAck,
(* mark_debug = "true" *) input logic LSUBusInit,
(* mark_debug = "true" *) input logic [`XLEN-1:0] LSUBusHRDATA,
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUBusHWDATA,
(* mark_debug = "true" *) output logic [2:0] LSUBusSize,
(* mark_debug = "true" *) output logic [2:0] LSUBurstType,
(* mark_debug = "true" *) output logic [1:0] LSUTransType,
(* mark_debug = "true" *) output logic LSUTransComplete,
// page table walker
input logic [`XLEN-1:0] SATP_REGW, // from csr
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
@ -211,7 +215,7 @@ module lsu (
busdp #(WORDSPERLINE, LINELEN, LOGWPL, CACHE_ENABLED) busdp(
.clk, .reset,
.LSUBusHRDATA, .LSUBusAck, .LSUBusWrite, .LSUBusRead, .LSUBusSize,
.LSUBusHRDATA, .LSUBusAck, .LSUBusInit, .LSUBusWrite, .LSUBusRead, .LSUBusSize, .LSUBurstType, .LSUTransType, .LSUTransComplete,
.WordCount, .LSUBusWriteCrit,
.LSUFunct3M, .LSUBusAdr, .DCacheBusAdr, .DCacheFetchLine,
.DCacheWriteLine, .DCacheBusAck, .DCacheBusWriteData, .LSUPAdrM,

View File

@ -134,13 +134,16 @@ module wallypipelinedcore (
logic [`PA_BITS-1:0] IFUBusAdr;
logic [`XLEN-1:0] IFUBusHRDATA;
logic IFUBusRead;
logic IFUBusAck;
logic IFUBusAck, IFUBusInit;
logic [2:0] IFUBurstType;
logic [1:0] IFUTransType;
logic IFUTransComplete;
// AHB LSU interface
logic [`PA_BITS-1:0] LSUBusAdr;
logic LSUBusRead;
logic LSUBusWrite;
logic LSUBusAck;
logic LSUBusAck, LSUBusInit;
logic [`XLEN-1:0] LSUBusHRDATA;
logic [`XLEN-1:0] LSUBusHWDATA;
@ -152,6 +155,9 @@ module wallypipelinedcore (
logic [4:0] InstrClassM;
logic InstrAccessFaultF;
logic [2:0] LSUBusSize;
logic [2:0] LSUBurstType;
logic [1:0] LSUTransType;
logic LSUTransComplete;
logic DCacheMiss;
logic DCacheAccess;
@ -166,8 +172,8 @@ module wallypipelinedcore (
.StallF, .StallD, .StallE, .StallM,
.FlushF, .FlushD, .FlushE, .FlushM,
// Fetch
.IFUBusHRDATA, .IFUBusAck, .PCF, .IFUBusAdr,
.IFUBusRead, .IFUStallF,
.IFUBusHRDATA, .IFUBusAck, .IFUBusInit, .PCF, .IFUBusAdr,
.IFUBusRead, .IFUStallF, .IFUBurstType, .IFUTransType, .IFUTransComplete,
.ICacheAccess, .ICacheMiss,
// Execute
@ -247,8 +253,8 @@ module wallypipelinedcore (
.IEUAdrE, .IEUAdrM, .WriteDataE,
.ReadDataM, .FlushDCacheM,
// connected to ahb (all stay the same)
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck,
.LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize,
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck, .LSUBusInit,
.LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize, .LSUBurstType, .LSUTransType, .LSUTransComplete,
// connect to csr or privilege and stay the same.
.PrivilegeModeW, .BigEndianM, // connects to csr
@ -279,13 +285,22 @@ module wallypipelinedcore (
ahblite ebu(// IFU connections
.clk, .reset,
.UnsignedLoadM(1'b0), .AtomicMaskedM(2'b00),
.IFUBusAdr,
.IFUBusRead, .IFUBusHRDATA, .IFUBusAck,
.IFUBusAdr, .IFUBusRead,
.IFUBusHRDATA,
.IFUBurstType,
.IFUTransType,
.IFUTransComplete,
.IFUBusAck,
.IFUBusInit,
// Signals from Data Cache
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusHWDATA,
.LSUBusHRDATA,
.LSUBusSize,
.LSUBurstType,
.LSUTransType,
.LSUTransComplete,
.LSUBusAck,
.LSUBusInit,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn,
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST,

View File

@ -418,6 +418,7 @@ module riscvassertions;
//assert (`DMEM == `MEM_CACHE | `DBUS ==0) else $error("Dcache rquires DBUS.");
//assert (`IMEM == `MEM_CACHE | `IBUS ==0) else $error("Icache rquires IBUS.");
assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (`DMEM != `MEM_CACHE)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1");
assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words");
end
endmodule