Merge pull request #247 from AlecVercruysse/code_quality

Code Quality
This commit is contained in:
Ross Thompson 2023-04-14 16:46:39 -05:00 committed by GitHub
commit 29146ac839
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 453 additions and 453 deletions

18
src/cache/cache.sv vendored
View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// cache // cache.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: 7 July 2021 // Created: 7 July 2021
@ -167,22 +167,22 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
// Adjust byte mask from word to cache line // Adjust byte mask from word to cache line
onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded)); onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded));
for(index = 0; index < 2**LOGCWPL; index++) begin for(index = 0; index < 2**LOGCWPL; index++) begin
assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0; assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0;
end end
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1. assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
// Merge write data into fetched cache line for store miss // Merge write data into fetched cache line for store miss
for(index = 0; index < LINELEN/8; index++) begin for(index = 0; index < LINELEN/8; index++) begin
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]), mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index])); .d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index]));
end end
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0; assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
end end
else else
begin:WriteSelLogic begin:WriteSelLogic
// No need for this mux if the cache does not handle writes. // No need for this mux if the cache does not handle writes.
assign LineWriteData = FetchBuffer; assign LineWriteData = FetchBuffer;
assign LineByteMask = '1; assign LineByteMask = '1;
end end
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Flush logic // Flush logic
@ -203,8 +203,8 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
assign FlushWayFlag = FlushWay[NUMWAYS-1]; assign FlushWayFlag = FlushWay[NUMWAYS-1];
end // block: flushlogic end // block: flushlogic
else begin:flushlogic else begin:flushlogic
assign FlushWayFlag = 0; assign FlushWayFlag = 0;
assign FlushAdrFlag = 0; assign FlushAdrFlag = 0;
end end
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// dcache (data cache) // cacheLRU.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: 20 July 2021 // Created: 20 July 2021
@ -37,7 +37,7 @@ module cacheLRU
input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
input logic [SETLEN-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr input logic [SETLEN-1:0] CacheSet, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] PAdr, // Physical address input logic [SETLEN-1:0] PAdr, // Physical address
input logic LRUWriteEn, // Update the LRU state input logic LRUWriteEn, // Update the LRU state
input logic SetValid, // Set the dirty bit in the selected way and set input logic SetValid, // Set the dirty bit in the selected way and set

View File

@ -1,11 +1,11 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// dcache (data cache) fsm // cachefsm.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: 25 August 2021 // Created: 25 August 2021
// Modified: 20 January 2023 // Modified: 20 January 2023
// //
// Purpose: Controller for the dcache fsm // Purpose: Controller for the cache fsm
// //
// Documentation: RISC-V System on Chip Design Chapter 7 (Figure 7.14 and Table 7.1) // Documentation: RISC-V System on Chip Design Chapter 7 (Figure 7.14 and Table 7.1)
// //

View File

@ -1,11 +1,11 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// subcachelineread // subcachelineread.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: 4 February 2022 // Created: 4 February 2022
// Modified: 20 January 2023 // Modified: 20 January 2023
// //
// Purpose: Muxes the cache line downto the word size. Also include possilbe save/restore registers/muxes. // Purpose: Muxes the cache line down to the word size. Also include possible save/restore registers/muxes.
// //
// Documentation: RISC-V System on Chip Design Chapter 7 // Documentation: RISC-V System on Chip Design Chapter 7
@ -31,7 +31,6 @@
module subcachelineread #(parameter LINELEN, WORDLEN, module subcachelineread #(parameter LINELEN, WORDLEN,
parameter MUXINTERVAL )( // The number of bits between mux. Set to 16 for I$ to support compressed. Set to `LLEN for D$ parameter MUXINTERVAL )( // The number of bits between mux. Set to 16 for I$ to support compressed. Set to `LLEN for D$
input logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1 : 0] PAdr, // Physical address input logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1 : 0] PAdr, // Physical address
input logic [LINELEN-1:0] ReadDataLine,// Read data of the whole cacheline input logic [LINELEN-1:0] ReadDataLine,// Read data of the whole cacheline
output logic [WORDLEN-1:0] ReadDataWord // read data of selected word. output logic [WORDLEN-1:0] ReadDataWord // read data of selected word.

View File

@ -38,27 +38,27 @@ module ahbcacheinterface #(
)( )(
input logic HCLK, HRESETn, input logic HCLK, HRESETn,
// bus interface controls // bus interface controls
input logic HREADY, // AHB peripheral ready input logic HREADY, // AHB peripheral ready
output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
output logic HWRITE, // AHB 0: Read operation 1: Write operation output logic HWRITE, // AHB 0: Read operation 1: Write operation
output logic [2:0] HSIZE, // AHB transaction width output logic [2:0] HSIZE, // AHB transaction width
output logic [2:0] HBURST, // AHB burst length output logic [2:0] HBURST, // AHB burst length
// bus interface buses // bus interface buses
input logic [`AHBW-1:0] HRDATA, // AHB read data input logic [`AHBW-1:0] HRDATA, // AHB read data
output logic [`PA_BITS-1:0] HADDR, // AHB address output logic [`PA_BITS-1:0] HADDR, // AHB address
output logic [`AHBW-1:0] HWDATA, // AHB write data output logic [`AHBW-1:0] HWDATA, // AHB write data
output logic [`AHBW/8-1:0] HWSTRB, // AHB byte mask output logic [`AHBW/8-1:0] HWSTRB, // AHB byte mask
// cache interface // cache interface
input logic [`PA_BITS-1:0] CacheBusAdr, // Address of cache line input logic [`PA_BITS-1:0] CacheBusAdr, // Address of cache line
input logic [`LLEN-1:0] CacheReadDataWordM, // one word of cache line during a writeback input logic [`LLEN-1:0] CacheReadDataWordM, // One word of cache line during a writeback
input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$ input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$
input logic Cacheable, // Memory operation is cachable input logic Cacheable, // Memory operation is cachable
input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch
output logic CacheBusAck, // Handshack to $ indicating bus transaction completed output logic CacheBusAck, // Handshake to $ indicating bus transaction completed
output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus
output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase
output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr
// uncached interface // uncached interface
input logic [`PA_BITS-1:0] PAdr, // Physical address of uncached memory operation input logic [`PA_BITS-1:0] PAdr, // Physical address of uncached memory operation
@ -77,7 +77,7 @@ module ahbcacheinterface #(
logic [`PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation logic [`PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation
logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage
logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA
logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s
logic [`AHBW-1:0] PreHWDATA; // AHB Address phase write data logic [`AHBW-1:0] PreHWDATA; // AHB Address phase write data
genvar index; genvar index;
@ -107,7 +107,7 @@ module ahbcacheinterface #(
end else assign CacheReadDataWordAHB = CacheReadDataWordM[`AHBW-1:0]; end else assign CacheReadDataWordAHB = CacheReadDataWordM[`AHBW-1:0];
mux2 #(`AHBW) HWDATAMux(.d0(CacheReadDataWordAHB), .d1(WriteDataM[`AHBW-1:0]), mux2 #(`AHBW) HWDATAMux(.d0(CacheReadDataWordAHB), .d1(WriteDataM[`AHBW-1:0]),
.s(~(CacheableOrFlushCacheM)), .y(PreHWDATA)); .s(~(CacheableOrFlushCacheM)), .y(PreHWDATA));
flopen #(`AHBW) wdreg(HCLK, HREADY, PreHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec flopen #(`AHBW) wdreg(HCLK, HREADY, PreHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec
// *** bummer need a second byte mask for bus as it is AHBW rather than LLEN. // *** bummer need a second byte mask for bus as it is AHBW rather than LLEN.
@ -119,5 +119,5 @@ module ahbcacheinterface #(
buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm( buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm(
.HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat, .HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat,
.CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed, .CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed,
.HREADY, .HTRANS, .HWRITE, .HBURST); .HREADY, .HTRANS, .HWRITE, .HBURST);
endmodule endmodule

View File

@ -32,21 +32,21 @@
module ahbinterface #( module ahbinterface #(
parameter LSU = 0 // 1: LSU bus width is `XLEN, 0: IFU bus width is 32 bits parameter LSU = 0 // 1: LSU bus width is `XLEN, 0: IFU bus width is 32 bits
)( )(
input logic HCLK, HRESETn, input logic HCLK, HRESETn,
// bus interface // bus interface
input logic HREADY, // AHB peripheral ready input logic HREADY, // AHB peripheral ready
output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
output logic HWRITE, // AHB 0: Read operation 1: Write operation output logic HWRITE, // AHB 0: Read operation 1: Write operation
input logic [`XLEN-1:0] HRDATA, // AHB read data input logic [`XLEN-1:0] HRDATA, // AHB read data
output logic [`XLEN-1:0] HWDATA, // AHB write data output logic [`XLEN-1:0] HWDATA, // AHB write data
output logic [`XLEN/8-1:0] HWSTRB, // AHB byte mask output logic [`XLEN/8-1:0] HWSTRB, // AHB byte mask
// lsu/ifu interface // lsu/ifu interface
input logic Stall, // Core pipeline is stalled input logic Stall, // Core pipeline is stalled
input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting
input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write
input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word
input logic [`XLEN-1:0] WriteData, // IEU write data for a store input logic [`XLEN-1:0] WriteData, // IEU write data for a store
output logic BusStall, // Bus is busy with an in flight memory operation output logic BusStall, // Bus is busy with an in flight memory operation
output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt
output logic [(LSU ? `XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus output logic [(LSU ? `XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus

View File

@ -40,29 +40,29 @@ module buscachefsm #(
input logic HRESETn, input logic HRESETn,
// IEU interface // IEU interface
input logic Stall, // Core pipeline is stalled input logic Stall, // Core pipeline is stalled
input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting
input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write
output logic BusStall, // Bus is busy with an in flight memory operation output logic BusStall, // Bus is busy with an in flight memory operation
output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt
// ahb cache interface locals. // ahb cache interface locals.
output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA
// cache interface // cache interface
input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch
output logic CacheBusAck, // Handshack to $ indicating bus transaction completed output logic CacheBusAck, // Handshack to $ indicating bus transaction completed
// lsu interface // lsu interface
output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase
output logic [AHBWLOGBWPL-1:0] BeatCountDelayed, // Beat within the cache line in the second (Data) cache stage output logic [AHBWLOGBWPL-1:0] BeatCountDelayed, // Beat within the cache line in the second (Data) cache stage
output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr
// BUS interface // BUS interface
input logic HREADY, // AHB peripheral ready input logic HREADY, // AHB peripheral ready
output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
output logic HWRITE, // AHB 0: Read operation 1: Write operation output logic HWRITE, // AHB 0: Read operation 1: Write operation
output logic [2:0] HBURST // AHB burst length output logic [2:0] HBURST // AHB burst length
); );
typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype; typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype;
@ -78,8 +78,8 @@ module buscachefsm #(
logic CacheAccess; logic CacheAccess;
always_ff @(posedge HCLK) always_ff @(posedge HCLK)
if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE; if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE;
else CurrState <= #1 NextState; else CurrState <= #1 NextState;
always_comb begin always_comb begin
case(CurrState) case(CurrState)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// controller input stage // controllerinput.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: August 31, 2022 // Created: August 31, 2022
@ -36,26 +36,26 @@
module controllerinput #( module controllerinput #(
parameter SAVE_ENABLED = 1 // 1: Save manager inputs if Save = 1, 0: Don't save inputs parameter SAVE_ENABLED = 1 // 1: Save manager inputs if Save = 1, 0: Don't save inputs
)( )(
input logic HCLK, input logic HCLK,
input logic HRESETn, input logic HRESETn,
input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs
input logic Restore, // Restore a saved manager inputs when it is finally granted input logic Restore, // Restore a saved manager inputs when it is finally granted
input logic Disable, // Supress HREADY to the non-granted manager input logic Disable, // Suppress HREADY to the non-granted manager
output logic Request, // This manager is making a request output logic Request, // This manager is making a request
// controller input // controller input
input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation
input logic [2:0] HSIZEIn, // Manager input. AHB transaction width input logic [2:0] HSIZEIn, // Manager input. AHB transaction width
input logic [2:0] HBURSTIn, // Manager input. AHB burst length input logic [2:0] HBURSTIn, // Manager input. AHB burst length
input logic [`PA_BITS-1:0] HADDRIn, // Manager input. AHB address input logic [`PA_BITS-1:0] HADDRIn, // Manager input. AHB address
output logic HREADYOut, // Indicate to manager the peripherial is not busy and another manager does not have priority output logic HREADYOut, // Indicate to manager the peripheral is not busy and another manager does not have priority
// controller output // controller output
output logic [1:0] HTRANSOut, // Aribrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ output logic [1:0] HTRANSOut, // Arbitrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ
output logic HWRITEOut, // Aribrated manager transaction. AHB 0: Read operation 1: Write operation output logic HWRITEOut, // Arbitrated manager transaction. AHB 0: Read operation 1: Write operation
output logic [2:0] HSIZEOut, // Aribrated manager transaction. AHB transaction width output logic [2:0] HSIZEOut, // Arbitrated manager transaction. AHB transaction width
output logic [2:0] HBURSTOut, // Aribrated manager transaction. AHB burst length output logic [2:0] HBURSTOut, // Arbitrated manager transaction. AHB burst length
output logic [`PA_BITS-1:0] HADDROut, // Aribrated manager transaction. AHB address output logic [`PA_BITS-1:0] HADDROut, // Arbitrated manager transaction. AHB address
input logic HREADYIn // Peripherial ready input logic HREADYIn // Peripheral ready
); );
logic HWRITESave; logic HWRITESave;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// ebufsmarb // ebufsmarb.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: 23 January 2023 // Created: 23 January 2023
@ -55,7 +55,7 @@ module ebufsmarb (
logic IFUReqD; // 1 cycle delayed IFU request. Part of arbitration logic IFUReqD; // 1 cycle delayed IFU request. Part of arbitration
logic FinalBeat, FinalBeatD; // Indicates the last beat of a burst logic FinalBeat, FinalBeatD; // Indicates the last beat of a burst
logic BeatCntEn; logic BeatCntEn;
logic [3:0] BeatCount; // Position within a burst transfer logic [3:0] BeatCount; // Position within a burst transfer
logic BeatCntReset; logic BeatCntReset;
logic [3:0] Threshold; // Number of beats derived from HBURST logic [3:0] Threshold; // Number of beats derived from HBURST
@ -86,7 +86,7 @@ module ebufsmarb (
// Controller 1 (LSU) // Controller 1 (LSU)
// When both the IFU and LSU request at the same time, the FSM will go into the arbitrate state. // When both the IFU and LSU request at the same time, the FSM will go into the arbitrate state.
// Once the LSU request is done the fsm returns to IDLE. To prevent the LSU from regaining // Once the LSU request is done the fsm returns to IDLE. To prevent the LSU from regaining
// priority and re issuing the same memroy operation, the delayed IFUReqD squashes the LSU request. // priority and re-issuing the same memory operation, the delayed IFUReqD squashes the LSU request.
// This is necessary because the pipeline is stalled for the entire duration of both transactions, // This is necessary because the pipeline is stalled for the entire duration of both transactions,
// and the LSU memory request will stil be active. // and the LSU memory request will stil be active.
flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqD); flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqD);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// fdivsqrtpreproc.sv // fdivsqrtexpcalc.sv
// //
// Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu // Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu
// Modified:13 January 2022 // Modified:13 January 2022
@ -30,11 +30,11 @@
module fdivsqrtexpcalc( module fdivsqrtexpcalc(
input logic [`FMTBITS-1:0] Fmt, input logic [`FMTBITS-1:0] Fmt,
input logic [`NE-1:0] Xe, Ye, input logic [`NE-1:0] Xe, Ye,
input logic Sqrt, input logic Sqrt,
input logic XZero, input logic XZero,
input logic [`DIVBLEN:0] ell, m, input logic [`DIVBLEN:0] ell, m,
output logic [`NE+1:0] Qe output logic [`NE+1:0] Qe
); );
logic [`NE-2:0] Bias; logic [`NE-2:0] Bias;
logic [`NE+1:0] SXExp; logic [`NE+1:0] SXExp;
@ -42,28 +42,28 @@ module fdivsqrtexpcalc(
logic [`NE+1:0] DExp; logic [`NE+1:0] DExp;
if (`FPSIZES == 1) begin if (`FPSIZES == 1) begin
assign Bias = (`NE-1)'(`BIAS); assign Bias = (`NE-1)'(`BIAS);
end else if (`FPSIZES == 2) begin end else if (`FPSIZES == 2) begin
assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1); assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
end else if (`FPSIZES == 3) begin end else if (`FPSIZES == 3) begin
always_comb always_comb
case (Fmt) case (Fmt)
`FMT: Bias = (`NE-1)'(`BIAS); `FMT: Bias = (`NE-1)'(`BIAS);
`FMT1: Bias = (`NE-1)'(`BIAS1); `FMT1: Bias = (`NE-1)'(`BIAS1);
`FMT2: Bias = (`NE-1)'(`BIAS2); `FMT2: Bias = (`NE-1)'(`BIAS2);
default: Bias = 'x; default: Bias = 'x;
endcase endcase
end else if (`FPSIZES == 4) begin end else if (`FPSIZES == 4) begin
always_comb always_comb
case (Fmt) case (Fmt)
2'h3: Bias = (`NE-1)'(`Q_BIAS); 2'h3: Bias = (`NE-1)'(`Q_BIAS);
2'h1: Bias = (`NE-1)'(`D_BIAS); 2'h1: Bias = (`NE-1)'(`D_BIAS);
2'h0: Bias = (`NE-1)'(`S_BIAS); 2'h0: Bias = (`NE-1)'(`S_BIAS);
2'h2: Bias = (`NE-1)'(`H_BIAS); 2'h2: Bias = (`NE-1)'(`H_BIAS);
endcase endcase
end end
assign SXExp = {2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - (`NE+2)'(`BIAS); assign SXExp = {2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - (`NE+2)'(`BIAS);
assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias}; assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias};

View File

@ -29,7 +29,7 @@
`include "wally-config.vh" `include "wally-config.vh"
module fdivsqrtfgen2 ( module fdivsqrtfgen2 (
input logic up, uz, input logic up, uz,
input logic [`DIVb+3:0] C, U, UM, input logic [`DIVb+3:0] C, U, UM,
output logic [`DIVb+3:0] F output logic [`DIVb+3:0] F
); );

View File

@ -29,7 +29,7 @@
`include "wally-config.vh" `include "wally-config.vh"
module fdivsqrtfgen4 ( module fdivsqrtfgen4 (
input logic [3:0] udigit, input logic [3:0] udigit,
input logic [`DIVb+3:0] C, U, UM, input logic [`DIVb+3:0] C, U, UM,
output logic [`DIVb+3:0] F output logic [`DIVb+3:0] F
); );

View File

@ -29,24 +29,24 @@
`include "wally-config.vh" `include "wally-config.vh"
module fdivsqrtfsm( module fdivsqrtfsm(
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic [`FMTBITS-1:0] FmtE, input logic [`FMTBITS-1:0] FmtE,
input logic XInfE, YInfE, input logic XInfE, YInfE,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic XNaNE, YNaNE, input logic XNaNE, YNaNE,
input logic FDivStartE, IDivStartE, input logic FDivStartE, IDivStartE,
input logic XsE, input logic XsE,
input logic SqrtE, input logic SqrtE,
input logic StallM, input logic StallM,
input logic FlushE, input logic FlushE,
input logic WZeroE, input logic WZeroE,
input logic IntDivE, input logic IntDivE,
input logic [`DIVBLEN:0] nE, input logic [`DIVBLEN:0] nE,
input logic ISpecialCaseE, input logic ISpecialCaseE,
output logic IFDivStartE, output logic IFDivStartE,
output logic FDivBusyE, FDivDoneE, output logic FDivBusyE, FDivDoneE,
output logic SpecialCaseM output logic SpecialCaseM
); );
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype; typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype;

View File

@ -29,10 +29,10 @@
`include "wally-config.vh" `include "wally-config.vh"
module fdivsqrtiter( module fdivsqrtiter(
input logic clk, input logic clk,
input logic IFDivStartE, input logic IFDivStartE,
input logic FDivBusyE, input logic FDivBusyE,
input logic SqrtE, input logic SqrtE,
input logic [`DIVb+3:0] X, input logic [`DIVb+3:0] X,
input logic [`DIVb-1:0] DPreproc, input logic [`DIVb-1:0] DPreproc,
output logic [`DIVb-1:0] D, output logic [`DIVb-1:0] D,

View File

@ -112,7 +112,7 @@ module fdivsqrtpostproc(
// Select quotient or remainder and do normalization shift // Select quotient or remainder and do normalization shift
mux2 #(`DIVBLEN+1) normshiftmux(((`DIVBLEN+1)'(`DIVb) - (nM * (`DIVBLEN+1)'(`LOGR))), (mM + (`DIVBLEN+1)'(`DIVa)), RemOpM, NormShiftM); mux2 #(`DIVBLEN+1) normshiftmux(((`DIVBLEN+1)'(`DIVb) - (nM * (`DIVBLEN+1)'(`LOGR))), (mM + (`DIVBLEN+1)'(`DIVa)), RemOpM, NormShiftM);
mux2 #(`DIVb+4) presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM); mux2 #(`DIVb+4) presresultmux(NormQuotM, NormRemM, RemOpM, PreResultM);
assign PreIntResultM = $signed(PreResultM >>> NormShiftM); assign PreIntResultM = $signed(PreResultM >>> NormShiftM);
// special case logic // special case logic

View File

@ -30,7 +30,7 @@
module fdivsqrtqsel2 ( module fdivsqrtqsel2 (
input logic [3:0] ps, pc, input logic [3:0] ps, pc,
output logic up, uz, un output logic up, uz, un
); );
logic [3:0] p, g; logic [3:0] p, g;

View File

@ -31,7 +31,7 @@
module fdivsqrtstage4 ( module fdivsqrtstage4 (
input logic [`DIVb-1:0] D, input logic [`DIVb-1:0] D,
input logic [`DIVb+3:0] DBar, D2, DBar2, input logic [`DIVb+3:0] DBar, D2, DBar2,
input logic [`DIVb:0] U,UM, input logic [`DIVb:0] U,UM,
input logic [`DIVb+3:0] WS, WC, input logic [`DIVb+3:0] WS, WC,
input logic [`DIVb+1:0] C, input logic [`DIVb+1:0] C,
input logic SqrtE, j1, input logic SqrtE, j1,
@ -58,8 +58,8 @@ module fdivsqrtstage4 (
// 0000 = 0 // 0000 = 0
// 0010 = -1 // 0010 = -1
// 0001 = -2 // 0001 = -2
assign Smsbs = U[`DIVb:`DIVb-4]; assign Smsbs = U[`DIVb:`DIVb-4];
assign Dmsbs = D[`DIVb-1:`DIVb-3]; assign Dmsbs = D[`DIVb-1:`DIVb-3];
assign WCmsbs = WC[`DIVb+3:`DIVb-4]; assign WCmsbs = WC[`DIVb+3:`DIVb-4];
assign WSmsbs = WS[`DIVb+3:`DIVb-4]; assign WSmsbs = WS[`DIVb+3:`DIVb-4];

View File

@ -32,10 +32,10 @@
// Unified OTFC, Radix 2 // // Unified OTFC, Radix 2 //
/////////////////////////////// ///////////////////////////////
module fdivsqrtuotfc2( module fdivsqrtuotfc2(
input logic up, un, input logic up, un,
input logic [`DIVb+1:0] C, input logic [`DIVb+1:0] C,
input logic [`DIVb:0] U, UM, input logic [`DIVb:0] U, UM,
output logic [`DIVb:0] UNext, UMNext output logic [`DIVb:0] UNext, UMNext
); );
// The on-the-fly converter transfers the divsqrt // The on-the-fly converter transfers the divsqrt
// bits to the quotient as they come. // bits to the quotient as they come.

View File

@ -29,7 +29,7 @@
`include "wally-config.vh" `include "wally-config.vh"
module fdivsqrtuotfc4( module fdivsqrtuotfc4(
input logic [3:0] udigit, input logic [3:0] udigit,
input logic [`DIVb:0] U, UM, input logic [`DIVb:0] U, UM,
input logic [`DIVb:0] C, input logic [`DIVb:0] C,
output logic [`DIVb:0] UNext, UMNext output logic [`DIVb:0] UNext, UMNext

View File

@ -24,7 +24,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module lzc #(parameter WIDTH = 1) ( module lzc #(parameter WIDTH = 1) (
input logic [WIDTH-1:0] num, // number to count the leading zeroes of input logic [WIDTH-1:0] num, // number to count the leading zeroes of
output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes output logic [$clog2(WIDTH+1)-1:0] ZeroCnt // the number of leading zeroes
); );

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// oneHotDecoder.sv // onehotdecoder.sv
// //
// Written: ross1728@gmail.com July 09, 2021 // Written: ross1728@gmail.com July 09, 2021
// Modified: // Modified:

View File

@ -30,13 +30,13 @@
module hazard ( module hazard (
// Detect hazards // Detect hazards
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD, input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD,
input logic LSUStallM, IFUStallF, input logic LSUStallM, IFUStallF,
input logic FCvtIntStallD, FPUStallD, input logic FCvtIntStallD, FPUStallD,
input logic DivBusyE, FDivBusyE, input logic DivBusyE, FDivBusyE,
input logic EcallFaultM, BreakpointFaultM, input logic EcallFaultM, BreakpointFaultM,
input logic wfiM, IntPendingM, input logic wfiM, IntPendingM,
// Stall & flush outputs // Stall & flush outputs
output logic StallF, StallD, StallE, StallM, StallW, output logic StallF, StallD, StallE, StallM, StallW,
output logic FlushD, FlushE, FlushM, FlushW output logic FlushD, FlushE, FlushM, FlushW

View File

@ -31,7 +31,7 @@
module byteUnit #(parameter WIDTH=32) ( module byteUnit #(parameter WIDTH=32) (
input logic [WIDTH-1:0] A, // Operands input logic [WIDTH-1:0] A, // Operands
input logic ByteSelect, // LSB of Immediate input logic ByteSelect, // LSB of Immediate
output logic [WIDTH-1:0] ByteResult); // rev8, orcb result output logic [WIDTH-1:0] ByteResult); // rev8, orcb result
logic [WIDTH-1:0] OrcBResult, Rev8Result; logic [WIDTH-1:0] OrcBResult, Rev8Result;

View File

@ -32,8 +32,8 @@
module cnt #(parameter WIDTH = 32) ( module cnt #(parameter WIDTH = 32) (
input logic [WIDTH-1:0] A, RevA, // Operands input logic [WIDTH-1:0] A, RevA, // Operands
input logic [1:0] B, // Last 2 bits of immediate input logic [1:0] B, // Last 2 bits of immediate
input logic W64, // Indicates word operation input logic W64, // Indicates word operation
output logic [WIDTH-1:0] CntResult // count result output logic [WIDTH-1:0] CntResult // count result
); );

View File

@ -32,7 +32,7 @@
module ext #(parameter WIDTH = 32) ( module ext #(parameter WIDTH = 32) (
input logic [WIDTH-1:0] A, // Operands input logic [WIDTH-1:0] A, // Operands
input logic [1:0] ExtSelect, // B[2], B[0] of immediate input logic [1:0] ExtSelect, // B[2], B[0] of immediate
output logic [WIDTH-1:0] ExtResult); // Extend Result output logic [WIDTH-1:0] ExtResult); // Extend Result
logic [WIDTH-1:0] sexthResult, zexthResult, sextbResult; logic [WIDTH-1:0] sexthResult, zexthResult, sextbResult;

View File

@ -27,7 +27,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module popcnt #(parameter WIDTH = 32) ( module popcnt #(parameter WIDTH = 32) (
input logic [WIDTH-1:0] num, // number to count total ones input logic [WIDTH-1:0] num, // number to count total ones
output logic [$clog2(WIDTH):0] PopCnt // the total number of ones output logic [$clog2(WIDTH):0] PopCnt // the total number of ones
); );

View File

@ -29,7 +29,7 @@
`include "wally-config.vh" `include "wally-config.vh"
module ieu ( module ieu (
input logic clk, reset, input logic clk, reset,
// Decode stage signals // Decode stage signals
input logic [31:0] InstrD, // Instruction input logic [31:0] InstrD, // Instruction
input logic IllegalIEUFPUInstrD, // Illegal instruction input logic IllegalIEUFPUInstrD, // Illegal instruction

View File

@ -35,9 +35,9 @@ module shifter (
input logic Right, Rotate, W64, SubArith, // Shift right, rotate, W64-type operation, arithmetic shift input logic Right, Rotate, W64, SubArith, // Shift right, rotate, W64-type operation, arithmetic shift
output logic [`XLEN-1:0] Y); // Shifted result output logic [`XLEN-1:0] Y); // Shifted result
logic [2*`XLEN-2:0] Z, ZShift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits logic [2*`XLEN-2:0] Z, ZShift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits
logic [`LOG_XLEN-1:0] TruncAmt, Offset; // Shift amount adjusted for RV64, right-shift amount logic [`LOG_XLEN-1:0] TruncAmt, Offset; // Shift amount adjusted for RV64, right-shift amount
logic Sign; // Sign bit for sign extension logic Sign; // Sign bit for sign extension
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
if (`XLEN==32) begin // rv32 if (`XLEN==32) begin // rv32

View File

@ -48,25 +48,25 @@ module bpred (
input logic [`XLEN-1:0] PCE, // Execution stage instruction address input logic [`XLEN-1:0] PCE, // Execution stage instruction address
input logic [`XLEN-1:0] PCM, // Memory stage instruction address input logic [`XLEN-1:0] PCM, // Memory stage instruction address
input logic [31:0] PostSpillInstrRawF, // Instruction input logic [31:0] PostSpillInstrRawF, // Instruction
// Branch and jump outcome // Branch and jump outcome
input logic InstrValidD, InstrValidE, input logic InstrValidD, InstrValidE,
input logic BranchD, BranchE, input logic BranchD, BranchE,
input logic JumpD, JumpE, input logic JumpD, JumpE,
input logic PCSrcE, // Executation stage branch is taken input logic PCSrcE, // Executation stage branch is taken
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address
input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as call, return, jr (not return), j, br output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as call, return, jr (not return), j, br
// Report branch prediction status // Report branch prediction status
output logic BPWrongE, // Prediction is wrong output logic BPWrongE, // Prediction is wrong
output logic BPWrongM, // Prediction is wrong output logic BPWrongM, // Prediction is wrong
output logic BPDirPredWrongM, // Prediction direction is wrong output logic BPDirPredWrongM, // Prediction direction is wrong
output logic BTAWrongM, // Prediction target wrong output logic BTAWrongM, // Prediction target wrong
output logic RASPredPCWrongM, // RAS prediction is wrong output logic RASPredPCWrongM, // RAS prediction is wrong
output logic IClassWrongM // Class prediction is wrong output logic IClassWrongM // Class prediction is wrong
); );
logic [1:0] BPDirPredF; logic [1:0] BPDirPredF;
@ -187,7 +187,7 @@ module bpred (
// Correct branch/jump target. // Correct branch/jump target.
mux2 #(`XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE); mux2 #(`XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE);
// If the fence/csrw was predicted as a taken branch then we select PCF, rather PCE. // If the fence/csrw was predicted as a taken branch then we select PCF, rather than PCE.
// Effectively this is PCM+4 or the non-existant PCLinkM // Effectively this is PCM+4 or the non-existant PCLinkM
if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE); if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
else assign NextValidPCE = PCE; else assign NextValidPCE = PCE;
@ -201,11 +201,11 @@ module bpred (
// 3. target ras (ras target wrong / class[2]) // 3. target ras (ras target wrong / class[2])
// 4. direction (br dir wrong / class[0]) // 4. direction (br dir wrong / class[0])
// Unforuantely we can't use PCD to infer the correctness of the BTB or RAS because the class prediction // Unfortunately we can't use PCD to infer the correctness of the BTB or RAS because the class prediction
// could be wrong or the fall through address selected for branch predict not taken. // could be wrong or the fall through address selected for branch predict not taken.
// By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of // By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of
// both without the above inaccuracies. // both without the above inaccuracies.
// **** use BPBTAWrongM from BTB. // **** use BPBTAWrongM from BTB.
assign BTAWrongE = (BPBTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE; assign BTAWrongE = (BPBTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE;
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE; assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE;

View File

@ -1,7 +1,7 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// btb.sv // btb.sv
// //
// Written: Ross Thomposn ross1728@gmail.com // Written: Ross Thompson ross1728@gmail.com
// Created: February 15, 2021 // Created: February 15, 2021
// Modified: 24 January 2023 // Modified: 24 January 2023
// //
@ -34,19 +34,19 @@ module btb #(parameter Depth = 10 ) (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW, input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW,
input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM,// PC at various stages input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, // PC at various stages
output logic [`XLEN-1:0] BPBTAF, // BTB's guess at PC output logic [`XLEN-1:0] BPBTAF, // BTB's guess at PC
output logic [`XLEN-1:0] BPBTAD, output logic [`XLEN-1:0] BPBTAD,
output logic [`XLEN-1:0] BPBTAE, output logic [`XLEN-1:0] BPBTAE,
output logic [3:0] BTBIClassF, // BTB's guess at instruction class output logic [3:0] BTBIClassF, // BTB's guess at instruction class
// update // update
input logic IClassWrongM, // BTB's instruction class guess was wrong input logic IClassWrongM, // BTB's instruction class guess was wrong
input logic IClassWrongE, input logic IClassWrongE,
input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb
input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb
input logic [3:0] InstrClassD, // Instruction class to insert into btb input logic [3:0] InstrClassD, // Instruction class to insert into btb
input logic [3:0] InstrClassE, // Instruction class to insert into btb input logic [3:0] InstrClassE, // Instruction class to insert into btb
input logic [3:0] InstrClassM, // Instruction class to insert into btb input logic [3:0] InstrClassM, // Instruction class to insert into btb
input logic [3:0] InstrClassW input logic [3:0] InstrClassW
); );
@ -73,7 +73,7 @@ module btb #(parameter Depth = 10 ) (
// must output a valid PC and valid bit during reset. Because only PCF, not PCNextF is reset, PCNextF is invalid // must output a valid PC and valid bit during reset. Because only PCF, not PCNextF is reset, PCNextF is invalid
// during reset. The BTB must produce a non X PC1NextF to allow the simulation to run. // during reset. The BTB must produce a non X PC1NextF to allow the simulation to run.
// While thie mux could be included in IFU it is not necessary for the IROM/I$/bus. // While the mux could be included in IFU it is not necessary for the IROM/I$/bus.
// For now it is optimal to leave it here. // For now it is optimal to leave it here.
assign ResetPC = `RESET_VECTOR; assign ResetPC = `RESET_VECTOR;
assign PCNextFIndex = reset ? ResetPC[Depth+1:2] : {PCNextF[Depth+1] ^ PCNextF[1], PCNextF[Depth:2]}; assign PCNextFIndex = reset ? ResetPC[Depth+1:2] : {PCNextF[Depth+1] ^ PCNextF[1], PCNextF[Depth:2]};

View File

@ -52,29 +52,29 @@ module testbench;
string tests[]; string tests[];
logic [3:0] dummy; logic [3:0] dummy;
logic [`AHBW-1:0] HRDATAEXT; logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT; logic HREADYEXT, HRESPEXT;
logic [`PA_BITS-1:0] HADDR; logic [`PA_BITS-1:0] HADDR;
logic [`AHBW-1:0] HWDATA; logic [`AHBW-1:0] HWDATA;
logic [`XLEN/8-1:0] HWSTRB; logic [`XLEN/8-1:0] HWSTRB;
logic HWRITE; logic HWRITE;
logic [2:0] HSIZE; logic [2:0] HSIZE;
logic [2:0] HBURST; logic [2:0] HBURST;
logic [3:0] HPROT; logic [3:0] HPROT;
logic [1:0] HTRANS; logic [1:0] HTRANS;
logic HMASTLOCK; logic HMASTLOCK;
logic HCLK, HRESETn; logic HCLK, HRESETn;
logic [`XLEN-1:0] PCW; logic [`XLEN-1:0] PCW;
string ProgramAddrMapFile, ProgramLabelMapFile; string ProgramAddrMapFile, ProgramLabelMapFile;
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 }; integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
logic DCacheFlushDone, DCacheFlushStart; logic DCacheFlushDone, DCacheFlushStart;
logic riscofTest; logic riscofTest;
logic StartSample, EndSample; logic StartSample, EndSample;
flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); flopenr #(`XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
// check assertions for a legal configuration // check assertions for a legal configuration
riscvassertions riscvassertions(); riscvassertions riscvassertions();
@ -85,62 +85,62 @@ module testbench;
//tests = '{}; //tests = '{};
if (`XLEN == 64) begin // RV64 if (`XLEN == 64) begin // RV64
case (TEST) case (TEST)
"arch64i": tests = arch64i; "arch64i": tests = arch64i;
"arch64priv": tests = arch64priv; "arch64priv": tests = arch64priv;
"arch64c": if (`C_SUPPORTED) "arch64c": if (`C_SUPPORTED)
if (`ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv}; if (`ZICSR_SUPPORTED) tests = {arch64c, arch64cpriv};
else tests = {arch64c}; else tests = {arch64c};
"arch64m": if (`M_SUPPORTED) tests = arch64m; "arch64m": if (`M_SUPPORTED) tests = arch64m;
"arch64f": if (`F_SUPPORTED) tests = arch64f; "arch64f": if (`F_SUPPORTED) tests = arch64f;
"arch64d": if (`D_SUPPORTED) tests = arch64d; "arch64d": if (`D_SUPPORTED) tests = arch64d;
"arch64zi": if (`ZIFENCEI_SUPPORTED) tests = arch64zi; "arch64zi": if (`ZIFENCEI_SUPPORTED) tests = arch64zi;
"imperas64i": tests = imperas64i; "imperas64i": tests = imperas64i;
"imperas64f": if (`F_SUPPORTED) tests = imperas64f; "imperas64f": if (`F_SUPPORTED) tests = imperas64f;
"imperas64d": if (`D_SUPPORTED) tests = imperas64d; "imperas64d": if (`D_SUPPORTED) tests = imperas64d;
"imperas64m": if (`M_SUPPORTED) tests = imperas64m; "imperas64m": if (`M_SUPPORTED) tests = imperas64m;
"wally64a": if (`A_SUPPORTED) tests = wally64a; "wally64a": if (`A_SUPPORTED) tests = wally64a;
"imperas64c": if (`C_SUPPORTED) tests = imperas64c; "imperas64c": if (`C_SUPPORTED) tests = imperas64c;
else tests = imperas64iNOc; else tests = imperas64iNOc;
"custom": tests = custom; "custom": tests = custom;
"wally64i": tests = wally64i; "wally64i": tests = wally64i;
"wally64priv": tests = wally64priv; "wally64priv": tests = wally64priv;
"wally64periph": tests = wally64periph; "wally64periph": tests = wally64periph;
"coremark": tests = coremark; "coremark": tests = coremark;
"fpga": tests = fpga; "fpga": tests = fpga;
"ahb" : tests = ahb; "ahb" : tests = ahb;
"coverage64gc" : tests = coverage64gc; "coverage64gc" : tests = coverage64gc;
"arch64zba": if (`ZBA_SUPPORTED) tests = arch64zba; "arch64zba": if (`ZBA_SUPPORTED) tests = arch64zba;
"arch64zbb": if (`ZBB_SUPPORTED) tests = arch64zbb; "arch64zbb": if (`ZBB_SUPPORTED) tests = arch64zbb;
"arch64zbc": if (`ZBC_SUPPORTED) tests = arch64zbc; "arch64zbc": if (`ZBC_SUPPORTED) tests = arch64zbc;
"arch64zbs": if (`ZBS_SUPPORTED) tests = arch64zbs; "arch64zbs": if (`ZBS_SUPPORTED) tests = arch64zbs;
endcase endcase
end else begin // RV32 end else begin // RV32
case (TEST) case (TEST)
"arch32i": tests = arch32i; "arch32i": tests = arch32i;
"arch32priv": tests = arch32priv; "arch32priv": tests = arch32priv;
"arch32c": if (`C_SUPPORTED) "arch32c": if (`C_SUPPORTED)
if (`ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv}; if (`ZICSR_SUPPORTED) tests = {arch32c, arch32cpriv};
else tests = {arch32c}; else tests = {arch32c};
"arch32m": if (`M_SUPPORTED) tests = arch32m; "arch32m": if (`M_SUPPORTED) tests = arch32m;
"arch32f": if (`F_SUPPORTED) tests = arch32f; "arch32f": if (`F_SUPPORTED) tests = arch32f;
"arch32d": if (`D_SUPPORTED) tests = arch32d; "arch32d": if (`D_SUPPORTED) tests = arch32d;
"arch32zi": if (`ZIFENCEI_SUPPORTED) tests = arch32zi; "arch32zi": if (`ZIFENCEI_SUPPORTED) tests = arch32zi;
"imperas32i": tests = imperas32i; "imperas32i": tests = imperas32i;
"imperas32f": if (`F_SUPPORTED) tests = imperas32f; "imperas32f": if (`F_SUPPORTED) tests = imperas32f;
"imperas32m": if (`M_SUPPORTED) tests = imperas32m; "imperas32m": if (`M_SUPPORTED) tests = imperas32m;
"wally32a": if (`A_SUPPORTED) tests = wally32a; "wally32a": if (`A_SUPPORTED) tests = wally32a;
"imperas32c": if (`C_SUPPORTED) tests = imperas32c; "imperas32c": if (`C_SUPPORTED) tests = imperas32c;
else tests = imperas32iNOc; else tests = imperas32iNOc;
"wally32i": tests = wally32i; "wally32i": tests = wally32i;
"wally32e": tests = wally32e; "wally32e": tests = wally32e;
"wally32priv": tests = wally32priv; "wally32priv": tests = wally32priv;
"wally32periph": tests = wally32periph; "wally32periph": tests = wally32periph;
"embench": tests = embench; "embench": tests = embench;
"coremark": tests = coremark; "coremark": tests = coremark;
"arch32zba": if (`ZBA_SUPPORTED) tests = arch32zba; "arch32zba": if (`ZBA_SUPPORTED) tests = arch32zba;
"arch32zbb": if (`ZBB_SUPPORTED) tests = arch32zbb; "arch32zbb": if (`ZBB_SUPPORTED) tests = arch32zbb;
"arch32zbc": if (`ZBC_SUPPORTED) tests = arch32zbc; "arch32zbc": if (`ZBC_SUPPORTED) tests = arch32zbc;
"arch32zbs": if (`ZBS_SUPPORTED) tests = arch32zbs; "arch32zbs": if (`ZBS_SUPPORTED) tests = arch32zbs;
endcase endcase
end end
if (tests.size() == 0) begin if (tests.size() == 0) begin
@ -149,7 +149,7 @@ module testbench;
end end
end end
string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile; string signame, memfilename, pathname, objdumpfilename, adrstr, outputfile;
integer outputFilePointer; integer outputFilePointer;
logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
@ -160,16 +160,16 @@ module testbench;
logic SDCCmdOut; logic SDCCmdOut;
logic SDCCmdOE; logic SDCCmdOE;
logic [3:0] SDCDatIn; logic [3:0] SDCDatIn;
tri1 [3:0] SDCDat; tri1 [3:0] SDCDat;
tri1 SDCCmd; tri1 SDCCmd;
logic HREADY; logic HREADY;
logic HSELEXT; logic HSELEXT;
logic InitializingMemories; logic InitializingMemories;
integer ResetCount, ResetThreshold; integer ResetCount, ResetThreshold;
logic InReset; logic InReset;
logic Begin; logic BeginSample;
// instantiate device to be tested // instantiate device to be tested
assign GPIOIN = 0; assign GPIOIN = 0;
@ -225,13 +225,14 @@ module testbench;
totalerrors = 0; totalerrors = 0;
testadr = 0; testadr = 0;
testadrNoBase = 0; testadrNoBase = 0;
// riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests and tests[0] == "2" refers to WallyRiscvArchTests // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests
// and tests[0] == "2" refers to WallyRiscvArchTests
riscofTest = tests[0] == "1" | tests[0] == "2"; riscofTest = tests[0] == "1" | tests[0] == "2";
// fill memory with defined values to reduce Xs in simulation // fill memory with defined values to reduce Xs in simulation
// Quick note the memory will need to be initialized. The C library does not // Quick note the memory will need to be initialized. The C library does not
// guarantee the initialized reads. For example a strcmp can read 6 byte // guarantee the initialized reads. For example a strcmp can read 6 byte
// strings, but uses a load double to read them in. If the last 2 bytes are // strings, but uses a load double to read them in. If the last 2 bytes are
// not initialized the compare results in an 'x' which propagates through // not initialized the compare results in an 'x' which propagates through
// the design. // the design.
if (TEST == "coremark") if (TEST == "coremark")
for (i=MemStartAddr; i<MemEndAddr; i = i+1) for (i=MemStartAddr; i<MemEndAddr; i = i+1)
@ -243,7 +244,7 @@ module testbench;
pathname = tvpaths[0]; pathname = tvpaths[0];
else pathname = tvpaths[1]; */ else pathname = tvpaths[1]; */
if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"};
else memfilename = {pathname, tests[test], ".elf.memfile"}; else memfilename = {pathname, tests[test], ".elf.memfile"};
if (`FPGA) begin if (`FPGA) begin
string romfilename, sdcfilename; string romfilename, sdcfilename;
romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"}; romfilename = {"../tests/custom/fpga-test-sdc/bin/fpga-test-sdc.memfile"};
@ -253,9 +254,9 @@ module testbench;
// force sdc timers // force sdc timers
force dut.uncore.uncore.sdc.SDC.LimitTimers = 1; force dut.uncore.uncore.sdc.SDC.LimitTimers = 1;
end else begin end else begin
if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM); if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM);
else if (`BUS_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); else if (`BUS_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM); if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
end end
if (riscofTest) begin if (riscofTest) begin
@ -265,8 +266,9 @@ module testbench;
ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
end end
// declare memory labels that interest us, the updateProgramAddrLabelArray task will find the addr of each label and fill the array // declare memory labels that interest us, the updateProgramAddrLabelArray task will find
// to expand, add more elements to this array and initialize them to zero (also initilaize them to zero at the start of the next test) // the addr of each label and fill the array. To expand, add more elements to this array
// and initialize them to zero (also initilaize them to zero at the start of the next test)
if(!`FPGA) begin if(!`FPGA) begin
updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray); updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
@ -294,99 +296,99 @@ module testbench;
ResetCount = 0; ResetCount = 0;
end end
end else begin end else begin
if (TEST == "coremark") if (TEST == "coremark")
if (dut.core.priv.priv.EcallFaultM) begin if (dut.core.priv.priv.EcallFaultM) begin
$display("Benchmark: coremark is done."); $display("Benchmark: coremark is done.");
$stop; $stop;
end end
// Termination condition (i.e. we finished running current test) // Termination condition (i.e. we finished running current test)
if (DCacheFlushDone) begin if (DCacheFlushDone) begin
integer begin_signature_addr; integer begin_signature_addr;
InReset = 1; InReset = 1;
begin_signature_addr = ProgramAddrLabelArray["begin_signature"]; begin_signature_addr = ProgramAddrLabelArray["begin_signature"];
if (!begin_signature_addr) if (!begin_signature_addr)
$display("begin_signature addr not found in %s", ProgramLabelMapFile); $display("begin_signature addr not found in %s", ProgramLabelMapFile);
testadr = ($unsigned(begin_signature_addr))/(`XLEN/8); testadr = ($unsigned(begin_signature_addr))/(`XLEN/8);
testadrNoBase = (begin_signature_addr - `UNCORE_RAM_BASE)/(`XLEN/8); testadrNoBase = (begin_signature_addr - `UNCORE_RAM_BASE)/(`XLEN/8);
#600; // give time for instructions in pipeline to finish #600; // give time for instructions in pipeline to finish
if (TEST == "embench") begin if (TEST == "embench") begin
// Writes contents of begin_signature to .sim.output file // Writes contents of begin_signature to .sim.output file
// this contains instret and cycles for start and end of test run, used by embench python speed script to calculate embench speed score // this contains instret and cycles for start and end of test run, used by embench
// also begin_signature contains the results of the self checking mechanism, which will be read by the python script for error checking // python speed script to calculate embench speed score.
// also, begin_signature contains the results of the self checking mechanism,
// which will be read by the python script for error checking
$display("Embench Benchmark: %s is done.", tests[test]); $display("Embench Benchmark: %s is done.", tests[test]);
if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"}; if (riscofTest) outputfile = {pathname, tests[test], "/ref/ref.sim.output"};
else outputfile = {pathname, tests[test], ".sim.output"}; else outputfile = {pathname, tests[test], ".sim.output"};
outputFilePointer = $fopen(outputfile); outputFilePointer = $fopen(outputfile);
i = 0; i = 0;
while ($unsigned(i) < $unsigned(5'd5)) begin while ($unsigned(i) < $unsigned(5'd5)) begin
$fdisplayh(outputFilePointer, DCacheFlushFSM.ShadowRAM[testadr+i]); $fdisplayh(outputFilePointer, DCacheFlushFSM.ShadowRAM[testadr+i]);
i = i + 1; i = i + 1;
end end
$fclose(outputFilePointer); $fclose(outputFilePointer);
$display("Embench Benchmark: created output file: %s", outputfile); $display("Embench Benchmark: created output file: %s", outputfile);
end else if (TEST == "coverage64gc") begin end else if (TEST == "coverage64gc") begin
$display("Coverage tests don't get checked"); $display("Coverage tests don't get checked");
end else begin end else begin
// for tests with no self checking mechanism, read .signature.output file and compare to check for errors // for tests with no self checking mechanism, read .signature.output file and compare to check for errors
// clear signature to prevent contamination from previous tests // clear signature to prevent contamination from previous tests
for(i=0; i<SIGNATURESIZE; i=i+1) begin for(i=0; i<SIGNATURESIZE; i=i+1) begin
sig32[i] = 'bx; sig32[i] = 'bx;
end end
if (riscofTest) signame = {pathname, tests[test], "/ref/Reference-sail_c_simulator.signature"}; if (riscofTest) signame = {pathname, tests[test], "/ref/Reference-sail_c_simulator.signature"};
else signame = {pathname, tests[test], ".signature.output"}; else signame = {pathname, tests[test], ".signature.output"};
// read signature, reformat in 64 bits if necessary // read signature, reformat in 64 bits if necessary
$readmemh(signame, sig32); $readmemh(signame, sig32);
i = 0; i = 0;
while (i < SIGNATURESIZE) begin while (i < SIGNATURESIZE) begin
if (`XLEN == 32) begin if (`XLEN == 32) begin
signature[i] = sig32[i]; signature[i] = sig32[i];
i = i+1; i = i+1;
end else begin end else begin
signature[i/2] = {sig32[i+1], sig32[i]}; signature[i/2] = {sig32[i+1], sig32[i]};
i = i + 2; i = i + 2;
end end
if (i >= 4 & sig32[i-4] === 'bx) begin if (i >= 4 & sig32[i-4] === 'bx) begin
if (i == 4) begin if (i == 4) begin
i = SIGNATURESIZE+1; // flag empty file i = SIGNATURESIZE+1; // flag empty file
$display(" Error: empty test file"); $display(" Error: empty test file");
end else i = SIGNATURESIZE; // skip over the rest of the x's for efficiency end else i = SIGNATURESIZE; // skip over the rest of the x's for efficiency
end end
end end
// Check errors // Check errors
errors = (i == SIGNATURESIZE+1); // error if file is empty errors = (i == SIGNATURESIZE+1); // error if file is empty
i = 0; i = 0;
/* verilator lint_off INFINITELOOP */ /* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin while (signature[i] !== 'bx) begin
logic [`XLEN-1:0] sig; logic [`XLEN-1:0] sig;
if (`DTIM_SUPPORTED) sig = dut.core.lsu.dtim.dtim.ram.RAM[testadrNoBase+i]; if (`DTIM_SUPPORTED) sig = dut.core.lsu.dtim.dtim.ram.RAM[testadrNoBase+i];
else if (`UNCORE_RAM_SUPPORTED) sig = dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i]; else if (`UNCORE_RAM_SUPPORTED) sig = dut.uncore.uncore.ram.ram.memory.RAM[testadrNoBase+i];
//$display("signature[%h] = %h sig = %h", i, signature[i], sig); //$display("signature[%h] = %h sig = %h", i, signature[i], sig);
if (signature[i] !== sig & (signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin if (signature[i] !== sig & (signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin
errors = errors+1; errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h", $display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h",
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]); tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]);
$stop;//***debug $stop; //***debug
end end
i = i + 1; i = i + 1;
end end
/* verilator lint_on INFINITELOOP */ /* verilator lint_on INFINITELOOP */
if (errors == 0) begin if (errors == 0) begin
$display("%s succeeded. Brilliant!!!", tests[test]); $display("%s succeeded. Brilliant!!!", tests[test]);
end end else begin
else begin
$display("%s failed with %d errors. :(", tests[test], errors); $display("%s failed with %d errors. :(", tests[test], errors);
totalerrors = totalerrors+1; totalerrors = totalerrors+1;
end end
end end
// move onto the next test, check to see if we're done // move onto the next test, check to see if we're done
test = test + 1; test = test + 1;
if (test == tests.size()) begin if (test == tests.size()) begin
if (totalerrors == 0) $display("SUCCESS! All tests ran without failures."); if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
else $display("FAIL: %d test programs had errors", totalerrors); else $display("FAIL: %d test programs had errors", totalerrors);
$stop; $stop;
end end else begin
else begin
InitializingMemories = 1; InitializingMemories = 1;
// If there are still additional tests to run, read in information for the next test // If there are still additional tests to run, read in information for the next test
//pathname = tvpaths[tests[0]]; //pathname = tvpaths[tests[0]];
@ -394,7 +396,7 @@ module testbench;
else memfilename = {pathname, tests[test], ".elf.memfile"}; else memfilename = {pathname, tests[test], ".elf.memfile"};
//$readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); //$readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM); if (`IROM_SUPPORTED) $readmemh(memfilename, dut.core.ifu.irom.irom.rom.ROM);
else if (`UNCORE_RAM_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); else if (`UNCORE_RAM_SUPPORTED) $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM);
if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM); if (`DTIM_SUPPORTED) $readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
if (riscofTest) begin if (riscofTest) begin
@ -405,22 +407,22 @@ module testbench;
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
end end
ProgramAddrLabelArray = '{ "begin_signature" : 0, "tohost" : 0 }; ProgramAddrLabelArray = '{ "begin_signature" : 0, "tohost" : 0 };
if(!`FPGA) begin if(!`FPGA) begin
updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray); updateProgramAddrLabelArray(ProgramAddrMapFile, ProgramLabelMapFile, ProgramAddrLabelArray);
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);
end end
end end
end // if (DCacheFlushDone) end // if (DCacheFlushDone)
end end
end // always @ (negedge clk) end // always @ (negedge clk)
if(`PrintHPMCounters & `ZICOUNTERS_SUPPORTED) begin : HPMCSample if(`PrintHPMCounters & `ZICOUNTERS_SUPPORTED) begin : HPMCSample
integer HPMCindex; integer HPMCindex;
logic StartSampleFirst; logic StartSampleFirst;
logic StartSampleDelayed, BeginDelayed; logic StartSampleDelayed, BeginDelayed;
logic EndSampleFirst, EndSampleDelayed; logic EndSampleFirst, EndSampleDelayed;
logic [`XLEN-1:0] InitialHPMCOUNTERH[`COUNTERS-1:0]; logic [`XLEN-1:0] InitialHPMCOUNTERH[`COUNTERS-1:0];
string HPMCnames[] = '{"Mcycle", string HPMCnames[] = '{"Mcycle",
"------", "------",
@ -433,8 +435,8 @@ module testbench;
"BP Target Wrong", "BP Target Wrong",
"RAS Wrong", "RAS Wrong",
"Instr Class Wrong", "Instr Class Wrong",
"Load Stall", "Load Stall",
"Store Stall", "Store Stall",
"D Cache Access", "D Cache Access",
"D Cache Miss", "D Cache Miss",
"D Cache Cycles", "D Cache Cycles",
@ -447,56 +449,55 @@ module testbench;
"Interrupt", "Interrupt",
"Exception", "Exception",
"Divide Cycles" "Divide Cycles"
}; };
if(TEST == "embench") begin if(TEST == "embench") begin
// embench runs warmup then runs start_trigger // embench runs warmup then runs start_trigger
// embench end with stop_trigger. // embench end with stop_trigger.
assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_trigger"; assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_trigger";
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_trigger"; assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_trigger";
flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed); flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed);
assign EndSample = EndSampleFirst & ~ EndSampleDelayed; assign EndSample = EndSampleFirst & ~ EndSampleDelayed;
end else if(TEST == "coremark") begin end else if(TEST == "coremark") begin
// embench runs warmup then runs start_trigger // embench runs warmup then runs start_trigger
// embench end with stop_trigger. // embench end with stop_trigger.
assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_time"; assign StartSampleFirst = FunctionName.FunctionName.FunctionName == "start_time";
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_time"; assign EndSampleFirst = FunctionName.FunctionName.FunctionName == "stop_time";
flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed); flopr #(1) EndSampleReg(clk, reset, EndSampleFirst, EndSampleDelayed);
assign EndSample = EndSampleFirst & ~ EndSampleDelayed; assign EndSample = EndSampleFirst & ~ EndSampleDelayed;
end else begin end else begin
// default start condiction is reset // default start condiction is reset
// default end condiction is end of test (DCacheFlushDone) // default end condiction is end of test (DCacheFlushDone)
assign StartSampleFirst = InReset; assign StartSampleFirst = InReset;
flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed); flopr #(1) StartSampleReg(clk, reset, StartSampleFirst, StartSampleDelayed);
assign StartSample = StartSampleFirst & ~ StartSampleDelayed; assign StartSample = StartSampleFirst & ~ StartSampleDelayed;
assign EndSample = DCacheFlushStart & ~DCacheFlushDone; assign EndSample = DCacheFlushStart & ~DCacheFlushDone;
flop #(1) BeginReg(clk, StartSampleFirst, BeginDelayed); flop #(1) BeginReg(clk, StartSampleFirst, BeginDelayed);
assign Begin = StartSampleFirst & ~BeginDelayed; assign BeginSample = StartSampleFirst & ~BeginDelayed;
end end
always @(negedge clk) begin always @(negedge clk) begin
if(StartSample) begin if(StartSample) begin
for(HPMCindex = 0; HPMCindex < 32; HPMCindex += 1) begin for(HPMCindex = 0; HPMCindex < 32; HPMCindex += 1) begin
InitialHPMCOUNTERH[HPMCindex] <= dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex]; InitialHPMCOUNTERH[HPMCindex] <= dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex];
end end
end end
if(EndSample) begin if(EndSample) begin
for(HPMCindex = 0; HPMCindex < HPMCnames.size(); HPMCindex += 1) begin for(HPMCindex = 0; HPMCindex < HPMCnames.size(); HPMCindex += 1) begin
// unlikely to have more than 10M in any counter. // unlikely to have more than 10M in any counter.
$display("Cnt[%2d] = %7d %s", HPMCindex, dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex] - InitialHPMCOUNTERH[HPMCindex], HPMCnames[HPMCindex]); $display("Cnt[%2d] = %7d %s", HPMCindex, dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[HPMCindex] - InitialHPMCOUNTERH[HPMCindex], HPMCnames[HPMCindex]);
end end
end end
end end
end end
@ -535,58 +536,59 @@ module testbench;
if (`BPRED_SUPPORTED) begin if (`BPRED_SUPPORTED) begin
integer adrindex; integer adrindex;
always @(*) begin always @(*) begin
if(reset) begin if(reset) begin
for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin
force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0; force dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex] = 0;
end end
for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin
force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0; force dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex] = 0;
end end
#1; #1;
for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BTB_SIZE; adrindex++) begin
release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex]; release dut.core.ifu.bpred.bpred.TargetPredictor.memory.mem[adrindex];
end end
for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin for(adrindex = 0; adrindex < 2**`BPRED_SIZE; adrindex++) begin
release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex]; release dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PHT.mem[adrindex];
end end
end end
end end
end end
if (`ICACHE_SUPPORTED && `I_CACHE_ADDR_LOGGER) begin : ICacheLogger if (`ICACHE_SUPPORTED && `I_CACHE_ADDR_LOGGER) begin : ICacheLogger
int file; int file;
string LogFile; string LogFile;
logic resetD, resetEdge; logic resetD, resetEdge;
logic Enable, InvalDelayed; logic Enable;
logic InvalDelayed, InvalEdge;
assign Enable = dut.core.ifu.bus.icache.icache.cachefsm.LRUWriteEn & assign Enable = dut.core.ifu.bus.icache.icache.cachefsm.LRUWriteEn &
dut.core.ifu.immu.immu.pmachecker.Cacheable & dut.core.ifu.immu.immu.pmachecker.Cacheable &
~dut.core.ifu.bus.icache.icache.cachefsm.FlushStage & ~dut.core.ifu.bus.icache.icache.cachefsm.FlushStage &
~reset; ~reset;
flop #(1) ResetDReg(clk, reset, resetD); flop #(1) ResetDReg(clk, reset, resetD);
assign resetEdge = ~reset & resetD; assign resetEdge = ~reset & resetD;
flop #(1) InvalReg(clk, dut.core.ifu.InvalidateICacheM, InvalDelayed); flop #(1) InvalReg(clk, dut.core.ifu.InvalidateICacheM, InvalDelayed);
assign InvalEdge = dut.core.ifu.InvalidateICacheM & ~InvalDelayed; assign InvalEdge = dut.core.ifu.InvalidateICacheM & ~InvalDelayed;
initial begin initial begin
LogFile = $psprintf("ICache.log"); LogFile = $psprintf("ICache.log");
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
$fwrite(file, "BEGIN %s\n", memfilename); $fwrite(file, "BEGIN %s\n", memfilename);
end end
string AccessTypeString, HitMissString; string AccessTypeString, HitMissString;
assign HitMissString = dut.core.ifu.bus.icache.icache.CacheHit ? "H" : assign HitMissString = dut.core.ifu.bus.icache.icache.CacheHit ? "H" :
dut.core.ifu.bus.icache.icache.vict.cacheLRU.AllValid ? "E" : "M"; dut.core.ifu.bus.icache.icache.vict.cacheLRU.AllValid ? "E" : "M";
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); if(BeginSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(Enable) begin // only log i cache reads if(Enable) begin // only log i cache reads
$fwrite(file, "%h R %s\n", dut.core.ifu.PCPF, HitMissString); $fwrite(file, "%h R %s\n", dut.core.ifu.PCPF, HitMissString);
end end
if(InvalEdge) $fwrite(file, "0 I X\n"); if(InvalEdge) $fwrite(file, "0 I X\n");
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
@ -615,18 +617,18 @@ end
(AccessTypeString != "NULL"); (AccessTypeString != "NULL");
initial begin initial begin
LogFile = $psprintf("DCache.log"); LogFile = $psprintf("DCache.log");
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
$fwrite(file, "BEGIN %s\n", memfilename); $fwrite(file, "BEGIN %s\n", memfilename);
end end
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(Begin) $fwrite(file, "BEGIN %s\n", memfilename); if(BeginSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(Enabled) begin if(Enabled) begin
$fwrite(file, "%h %s %s\n", dut.core.lsu.PAdrM, AccessTypeString, HitMissString); $fwrite(file, "%h %s %s\n", dut.core.lsu.PAdrM, AccessTypeString, HitMissString);
end end
if(dut.core.lsu.bus.dcache.dcache.cachefsm.FlushFlag) $fwrite(file, "0 F X\n"); if(dut.core.lsu.bus.dcache.dcache.cachefsm.FlushFlag) $fwrite(file, "0 F X\n");
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
@ -634,45 +636,45 @@ end
if (`BPRED_LOGGER) begin if (`BPRED_LOGGER) begin
string direction; string direction;
int file; int file;
logic PCSrcM; logic PCSrcM;
string LogFile; string LogFile;
logic resetD, resetEdge; logic resetD, resetEdge;
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM); flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM);
flop #(1) ResetDReg(clk, reset, resetD); flop #(1) ResetDReg(clk, reset, resetD);
assign resetEdge = ~reset & resetD; assign resetEdge = ~reset & resetD;
initial begin initial begin
LogFile = $psprintf("branch_%s%0d.log", `BPRED_TYPE, `BPRED_SIZE); LogFile = $psprintf("branch_%s%0d.log", `BPRED_TYPE, `BPRED_SIZE);
file = $fopen(LogFile, "w"); file = $fopen(LogFile, "w");
end end
always @(posedge clk) begin always @(posedge clk) begin
if(resetEdge) $fwrite(file, "TRAIN\n"); if(resetEdge) $fwrite(file, "TRAIN\n");
if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename); if(StartSample) $fwrite(file, "BEGIN %s\n", memfilename);
if(dut.core.ifu.InstrClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin if(dut.core.ifu.InstrClassM[0] & ~dut.core.StallW & ~dut.core.FlushW & dut.core.InstrValidM) begin
direction = PCSrcM ? "t" : "n"; direction = PCSrcM ? "t" : "n";
$fwrite(file, "%h %s\n", dut.core.PCM, direction); $fwrite(file, "%h %s\n", dut.core.PCM, direction);
end end
if(EndSample) $fwrite(file, "END %s\n", memfilename); if(EndSample) $fwrite(file, "END %s\n", memfilename);
end end
end end
end end
// check for hange up. // check for hang up.
logic [`XLEN-1:0] OldPCW; logic [`XLEN-1:0] OldPCW;
integer WatchDogTimerCount; integer WatchDogTimerCount;
localparam WatchDogTimerThreshold = 1000000; localparam WatchDogTimerThreshold = 1000000;
logic WatchDogTimeOut; logic WatchDogTimeOut;
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
OldPCW <= PCW; OldPCW <= PCW;
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1; if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
else WatchDogTimerCount = '0; else WatchDogTimerCount = '0;
end end
always_comb begin always_comb begin
WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold; WatchDogTimeOut = WatchDogTimerCount >= WatchDogTimerThreshold;
if(WatchDogTimeOut) begin if(WatchDogTimeOut) begin
$display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount); $display("FAILURE: Watch Dog Time Out triggered. PCW stuck at %x for more than %d cycles", PCW, WatchDogTimerCount);
$stop; $stop;
end end
end end
endmodule endmodule
@ -690,34 +692,34 @@ module DCacheFlushFSM
logic [`XLEN-1:0] ShadowRAM[`UNCORE_RAM_BASE>>(1+`XLEN/32):(`UNCORE_RAM_RANGE+`UNCORE_RAM_BASE)>>1+(`XLEN/32)]; logic [`XLEN-1:0] ShadowRAM[`UNCORE_RAM_BASE>>(1+`XLEN/32):(`UNCORE_RAM_RANGE+`UNCORE_RAM_BASE)>>1+(`XLEN/32)];
if(`DCACHE_SUPPORTED) begin if(`DCACHE_SUPPORTED) begin
localparam numlines = testbench.dut.core.lsu.bus.dcache.dcache.NUMLINES; localparam numlines = testbench.dut.core.lsu.bus.dcache.dcache.NUMLINES;
localparam numways = testbench.dut.core.lsu.bus.dcache.dcache.NUMWAYS; localparam numways = testbench.dut.core.lsu.bus.dcache.dcache.NUMWAYS;
localparam linebytelen = testbench.dut.core.lsu.bus.dcache.dcache.LINEBYTELEN; localparam linebytelen = testbench.dut.core.lsu.bus.dcache.dcache.LINEBYTELEN;
localparam linelen = testbench.dut.core.lsu.bus.dcache.dcache.LINELEN; localparam linelen = testbench.dut.core.lsu.bus.dcache.dcache.LINELEN;
localparam sramlen = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].SRAMLEN; localparam sramlen = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].SRAMLEN;
localparam cachesramwords = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].NUMSRAM; localparam cachesramwords = testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[0].NUMSRAM;
localparam numwords = sramlen/`XLEN; localparam numwords = sramlen/`XLEN;
localparam lognumlines = $clog2(numlines); localparam lognumlines = $clog2(numlines);
localparam loglinebytelen = $clog2(linebytelen); localparam loglinebytelen = $clog2(linebytelen);
localparam lognumways = $clog2(numways); localparam lognumways = $clog2(numways);
localparam tagstart = lognumlines + loglinebytelen; localparam tagstart = lognumlines + loglinebytelen;
genvar index, way, cacheWord; genvar index, way, cacheWord;
logic [sramlen-1:0] CacheData [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [sramlen-1:0] CacheData [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic [sramlen-1:0] cacheline; logic [sramlen-1:0] cacheline;
logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [`XLEN-1:0] CacheTag [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic CacheValid [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic CacheValid [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic CacheDirty [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic CacheDirty [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [cachesramwords-1:0]; logic [`PA_BITS-1:0] CacheAdr [numways-1:0] [numlines-1:0] [cachesramwords-1:0];
for(index = 0; index < numlines; index++) begin for(index = 0; index < numlines; index++) begin
for(way = 0; way < numways; way++) begin for(way = 0; way < numways; way++) begin
for(cacheWord = 0; cacheWord < cachesramwords; cacheWord++) begin for(cacheWord = 0; cacheWord < cachesramwords; cacheWord++) begin
copyShadow #(.tagstart(tagstart), copyShadow #(.tagstart(tagstart),
.loglinebytelen(loglinebytelen), .sramlen(sramlen)) .loglinebytelen(loglinebytelen), .sramlen(sramlen))
copyShadow(.clk, copyShadow(.clk,
.start, .start,
.tag(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].CacheTagMem.RAM[index][`PA_BITS-1-tagstart:0]), .tag(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].CacheTagMem.RAM[index][`PA_BITS-1-tagstart:0]),
.valid(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].ValidBits[index]), .valid(testbench.dut.core.lsu.bus.dcache.dcache.CacheWays[way].ValidBits[index]),
@ -766,18 +768,18 @@ endmodule
module copyShadow module copyShadow
#(parameter tagstart, loglinebytelen, sramlen) #(parameter tagstart, loglinebytelen, sramlen)
(input logic clk, (input logic clk,
input logic start, input logic start,
input logic [`PA_BITS-1:tagstart] tag, input logic [`PA_BITS-1:tagstart] tag,
input logic valid, dirty, input logic valid, dirty,
input logic [sramlen-1:0] data, input logic [sramlen-1:0] data,
input logic [32-1:0] index, input logic [32-1:0] index,
input logic [32-1:0] cacheWord, input logic [32-1:0] cacheWord,
output logic [sramlen-1:0] CacheData, output logic [sramlen-1:0] CacheData,
output logic [`PA_BITS-1:0] CacheAdr, output logic [`PA_BITS-1:0] CacheAdr,
output logic [`XLEN-1:0] CacheTag, output logic [`XLEN-1:0] CacheTag,
output logic CacheValid, output logic CacheValid,
output logic CacheDirty); output logic CacheDirty);
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
@ -806,8 +808,7 @@ task automatic updateProgramAddrLabelArray;
integer returncode; integer returncode;
returncode = $fscanf(ProgramLabelMapFP, "%s\n", label); returncode = $fscanf(ProgramLabelMapFP, "%s\n", label);
returncode = $fscanf(ProgramAddrMapFP, "%s\n", adrstr); returncode = $fscanf(ProgramAddrMapFP, "%s\n", adrstr);
if (ProgramAddrLabelArray.exists(label)) if (ProgramAddrLabelArray.exists(label)) ProgramAddrLabelArray[label] = adrstr.atohex();
ProgramAddrLabelArray[label] = adrstr.atohex();
end end
end end
$fclose(ProgramLabelMapFP); $fclose(ProgramLabelMapFP);