This commit is contained in:
cturek 2022-12-16 03:41:39 +00:00
commit d7571bb9b1
32 changed files with 192 additions and 158 deletions

1
.gitignore vendored
View File

@ -117,3 +117,4 @@ pipelined/srt/testgen
pipelined/srt/qslc_r4a2
pipelined/srt/qslc_r4a2.sv
pipelined/srt/testvectors
pipelined/regression/wkdir

View File

@ -271,7 +271,7 @@ connect_debug_port u_ila_0/probe51 [get_nets [list wallypipelinedsoc/core/hzu/BP
create_debug_port u_ila_0 probe
set_property port_width 1 [get_debug_ports u_ila_0/probe52]
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe52]
connect_debug_port u_ila_0/probe52 [get_nets [list wallypipelinedsoc/core/hzu/CSRWriteFencePendingDEM ]]
connect_debug_port u_ila_0/probe52 [get_nets [list wallypipelinedsoc/core/hzu/CSRWriteFenceM ]]
create_debug_port u_ila_0 probe
set_property port_width 1 [get_debug_ports u_ila_0/probe53]
@ -356,7 +356,7 @@ connect_debug_port u_ila_0/probe68 [get_nets [list wallypipelinedsoc/core/hzu/St
create_debug_port u_ila_0 probe
set_property port_width 1 [get_debug_ports u_ila_0/probe69]
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe69]
connect_debug_port u_ila_0/probe69 [get_nets [list wallypipelinedsoc/core/hzu/StallD ]]
connect_debug_port u_ila_0/probe69 [get_nets [list wallypipelinedsoc/core/hzu/StallD_inferred_i_2_n_0 ]]
create_debug_port u_ila_0 probe
set_property port_width 1 [get_debug_ports u_ila_0/probe70]

View File

@ -70,8 +70,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 16

View File

@ -72,8 +72,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -71,8 +71,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 1
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 1
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 0

View File

@ -70,8 +70,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -71,8 +71,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -70,8 +70,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 0

View File

@ -74,8 +74,9 @@
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Address space
`define RESET_VECTOR 64'h0000000000001000

View File

@ -72,8 +72,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -72,8 +72,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 64

View File

@ -72,8 +72,9 @@
`define ICACHE_LINELENINBITS 512
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// IDIV_BITSPERCYCLE must be 1, 2, or 4
`define IDIV_BITSPERCYCLE 4
`define IDIV_ON_FPU 0
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 0

View File

@ -10,7 +10,7 @@
# output.
#
##################################
import sys,os
import sys,os,shutil
class bcolors:
HEADER = '\033[95m'
@ -26,6 +26,7 @@ class bcolors:
from collections import namedtuple
regressionDir = os.path.dirname(os.path.abspath(__file__))
os.chdir(regressionDir)
TestCase = namedtuple("TestCase", ['name', 'variant', 'cmd', 'grepstr'])
# name: the name of this test configuration (used in printing human-readable
# output and picking logfile names)
@ -158,9 +159,13 @@ def main():
try:
os.chdir(regressionDir)
os.mkdir("logs")
#print(os.getcwd())
#print(regressionDir)
except:
pass
shutil.rmtree("wkdir")
os.mkdir("wkdir")
if '-makeTests' in sys.argv:
os.chdir(regressionDir)
os.system('./make-tests.sh | tee ./logs/make-tests.log')

View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -94,14 +94,14 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
logic [NUMWAYS-1:0] NextFlushWay;
logic FlushWayCntEn;
logic FlushWayCntRst;
logic SelEvict;
logic SelWriteback;
logic LRUWriteEn;
logic SelFlush;
logic ResetOrFlushAdr, ResetOrFlushWay;
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
logic SelFetchBuffer;
logic ce;
logic CacheEn;
localparam LOGLLENBYTES = $clog2(WORDLEN/8);
localparam CACHEWORDSPERLINE = `DCACHE_LINELENINBITS/WORDLEN;
@ -124,12 +124,12 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
// Array of cache ways, along with victim, hit, dirty, and read merging logic
cacheway #(NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, DCACHE)
CacheWays[NUMWAYS-1:0](.clk, .reset, .ce, .CAdr, .PAdr, .LineWriteData, .LineByteMask,
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelEvict, .VictimWay,
CacheWays[NUMWAYS-1:0](.clk, .reset, .CacheEn, .CAdr, .PAdr, .LineWriteData, .LineByteMask,
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .SelWriteback, .VictimWay,
.FlushWay, .SelFlush, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .TagWay, .FlushStage, .InvalidateCache);
if(NUMWAYS > 1) begin:vict
cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMLINES) cacheLRU(
.clk, .reset, .ce, .FlushStage, .HitWay, .ValidWay, .VictimWay, .CAdr, .LRUWriteEn(LRUWriteEn & ~FlushStage),
.clk, .reset, .CacheEn, .FlushStage, .HitWay, .ValidWay, .VictimWay, .CAdr, .LRUWriteEn(LRUWriteEn & ~FlushStage),
.SetValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache, .FlushCache);
end else assign VictimWay = 1'b1; // one hot.
assign CacheHit = | HitWay;
@ -163,7 +163,8 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
end
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
assign LineByteMask = ~SetValid & ~SetDirty ? '0 : ~SetValid & SetDirty ? DemuxedByteMask : '1; // if store hit only enable the word and subword bytes, else write all bytes.
logic [LINELEN/8-1:0] LineByteMask2;
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
for(index = 0; index < LINELEN/8; index++) begin
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
@ -173,7 +174,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}),
.d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}),
.s({SelFlush, SelEvict}), .y(CacheBusAdr));
.s({SelFlush, SelWriteback}), .y(CacheBusAdr));
/////////////////////////////////////////////////////////////////////////////////////////////
// Flush address and way generation during flush
@ -198,10 +199,10 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
.CacheHit, .LineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdr,
.ClearValid, .ClearDirty, .SetDirty,
.SetValid, .SelEvict, .SelFlush,
.SetValid, .SelWriteback, .SelFlush,
.FlushAdrCntEn, .FlushWayCntEn, .FlushAdrCntRst,
.FlushWayCntRst, .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
.InvalidateCache,
.ce,
.CacheEn,
.LRUWriteEn);
endmodule

View File

@ -32,7 +32,7 @@
module cacheLRU
#(parameter NUMWAYS = 4, SETLEN = 9, OFFSETLEN = 5, NUMLINES = 128)(
input logic clk, reset, ce, FlushStage,
input logic clk, reset, CacheEn, FlushStage,
input logic [NUMWAYS-1:0] HitWay,
input logic [NUMWAYS-1:0] ValidWay,
output logic [NUMWAYS-1:0] VictimWay,
@ -120,7 +120,7 @@ module cacheLRU
// LRU storage must be reset for modelsim to run. However the reset value does not actually matter in practice.
always_ff @(posedge clk) begin
if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
if(ce) begin
if(CacheEn) begin
if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
else if (LRUWriteEn & ~FlushStage) begin
LRUMemory[CAdr] <= NextLRU; ///***** RT: This is not right. Logically should be PAdr, but it breaks linux.

View File

@ -64,7 +64,7 @@ module cachefsm
output logic ClearDirty,
output logic SetDirty,
output logic SetValid,
output logic SelEvict,
output logic SelWriteback,
output logic LRUWriteEn,
output logic SelFlush,
output logic FlushAdrCntEn,
@ -72,7 +72,7 @@ module cachefsm
output logic FlushAdrCntRst,
output logic FlushWayCntRst,
output logic SelFetchBuffer,
output logic ce);
output logic CacheEn);
logic resetDelay;
logic AMO, StoreAMO;
@ -170,7 +170,7 @@ module cachefsm
assign LRUWriteEn = (CurrState == STATE_READY & AnyHit) |
(CurrState == STATE_MISS_WRITE_CACHE_LINE);
// Flush and eviction controls
assign SelEvict = (CurrState == STATE_MISS_EVICT_DIRTY & ~CacheBusAck) |
assign SelWriteback = (CurrState == STATE_MISS_EVICT_DIRTY & ~CacheBusAck) |
(CurrState == STATE_READY & AnyMiss & LineDirty);
assign SelFlush = (CurrState == STATE_FLUSH) | (CurrState == STATE_FLUSH_CHECK) |
(CurrState == STATE_FLUSH_INCR) | (CurrState == STATE_FLUSH_WRITE_BACK);
@ -201,6 +201,6 @@ module cachefsm
resetDelay;
assign SelFetchBuffer = CurrState == STATE_MISS_WRITE_CACHE_LINE | CurrState == STATE_MISS_READ_DELAY;
assign ce = (CurrState == STATE_READY & ~Stall | CacheStall) | (CurrState != STATE_READY) | reset;
assign CacheEn = (CurrState == STATE_READY & ~Stall | CacheStall) | (CurrState != STATE_READY) | reset;
endmodule // cachefsm

View File

@ -33,7 +33,7 @@
module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
parameter OFFSETLEN = 5, parameter INDEXLEN = 9, parameter DIRTY_BITS = 1) (
input logic clk,
input logic ce,
input logic CacheEn,
input logic reset,
input logic [$clog2(NUMLINES)-1:0] CAdr,
input logic [`PA_BITS-1:0] PAdr,
@ -42,7 +42,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
input logic ClearValid,
input logic SetDirty,
input logic ClearDirty,
input logic SelEvict,
input logic SelWriteback,
input logic SelFlush,
input logic VictimWay,
input logic FlushWay,
@ -76,8 +76,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
logic ClearValidWay;
logic SetDirtyWay;
logic ClearDirtyWay;
logic SelectedWay;
logic SelWriteback;
logic SelNonHit;
logic SelData;
logic FlushWayEn, VictimWayEn;
@ -85,28 +84,28 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
// FlushWay and VictimWay are part of a one hot way selection. Must clear them if FlushWay not selected
// or VictimWay not selected.
assign FlushWayEn = FlushWay & SelFlush;
assign VictimWayEn = VictimWay & SelEvict;
assign VictimWayEn = VictimWay & SelWriteback;
assign SelWriteback = FlushWayEn | SetValid | SelEvict;
assign SelNonHit = FlushWayEn | SetValid | SelWriteback;
mux2 #(1) seltagmux(VictimWay, FlushWay, SelFlush, SelTag);
//assign SelTag = VictimWay | FlushWay;
assign SelData = HitWay | FlushWayEn | VictimWayEn;
//assign SelData = HitWay | FlushWayEn | VictimWayEn;
mux2 #(1) selectedwaymux(HitWay, SelTag, SelWriteback , SelectedWay);
mux2 #(1) selectedwaymux(HitWay, SelTag, SelNonHit , SelData);
/////////////////////////////////////////////////////////////////////////////////////////////
// Write Enable demux
/////////////////////////////////////////////////////////////////////////////////////////////
// RT: Can we merge these two muxes? This is also shared in cacheLRU.
//mux3 #(1) selectwaymux(HitWay, VictimWay, FlushWay, {SelFlush, SetValid}, SelectedWay);
//mux3 #(1) selecteddatamux(HitWay, VictimWay, FlushWay, {SelFlush, SelEvict}, SelData);
//mux3 #(1) selectwaymux(HitWay, VictimWay, FlushWay, {SelFlush, SetValid}, SelData);
//mux3 #(1) selecteddatamux(HitWay, VictimWay, FlushWay, {SelFlush, SelNonHit}, SelData);
assign SetValidWay = SetValid & SelectedWay;
assign ClearValidWay = ClearValid & SelectedWay;
assign SetDirtyWay = SetDirty & SelectedWay;
assign ClearDirtyWay = ClearDirty & SelectedWay;
assign SetValidWay = SetValid & SelData;
assign ClearValidWay = ClearValid & SelData;
assign SetDirtyWay = SetDirty & SelData;
assign ClearDirtyWay = ClearDirty & SelData;
// If writing the whole line set all write enables to 1, else only set the correct word.
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage;
@ -117,7 +116,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
// Tag Array
/////////////////////////////////////////////////////////////////////////////////////////////
sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce,
sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
.addr(CAdr), .dout(ReadTag), .bwe('1),
.din(PAdr[`PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
@ -140,7 +139,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
localparam integer LOGNUMSRAM = $clog2(NUMSRAM);
for(words = 0; words < NUMSRAM; words++) begin: word
sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce, .addr(CAdr),
sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CAdr),
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
@ -155,7 +154,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
always_ff @(posedge clk) begin // Valid bit array,
if (reset) ValidBits <= #1 '0;
if(ce) begin
if(CacheEn) begin
ValidWay <= #1 ValidBits[CAdr];
if(InvalidateCache & ~FlushStage) ValidBits <= #1 '0;
else if (SetValidEN | (ClearValidWay & ~FlushStage)) ValidBits[CAdr] <= #1 SetValidWay;
@ -171,7 +170,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
always_ff @(posedge clk) begin
// reset is optional. Consider merging with TAG array in the future.
//if (reset) DirtyBits <= #1 {NUMLINES{1'b0}};
if(ce) begin
if(CacheEn) begin
Dirty <= #1 DirtyBits[CAdr];
if((SetDirtyWay | ClearDirtyWay) & ~FlushStage) DirtyBits[CAdr] <= #1 SetDirtyWay;
end

View File

@ -43,7 +43,7 @@ module fdivsqrt(
input logic FDivStartE, IDivStartE,
input logic StallM,
input logic StallE,
input logic TrapM,
input logic FlushE,
input logic SqrtE, SqrtM,
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
input logic [2:0] Funct3E, Funct3M,
@ -52,7 +52,8 @@ module fdivsqrt(
output logic FDivBusyE, IFDivStartE, FDivDoneE,
// output logic DivDone,
output logic [`NE+1:0] QeM,
output logic [`DIVb:0] QmM
output logic [`DIVb:0] QmM,
output logic [`XLEN-1:0] FPIntDivResultM
// output logic [`XLEN-1:0] RemM,
);
@ -76,7 +77,7 @@ module fdivsqrt(
.ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .Funct3M, .MDUE, .W64E);
fdivsqrtfsm fdivsqrtfsm(
.clk, .reset, .FmtE, .XsE, .SqrtE,
.FDivBusyE, .FDivStartE, .IDivStartE, .IFDivStartE, .FDivDoneE, .StallE, .StallM, .TrapM, /*.DivDone, */ .XZeroE, .YZeroE,
.FDivBusyE, .FDivStartE, .IDivStartE, .IFDivStartE, .FDivDoneE, .StallE, .StallM, .FlushE, /*.DivDone, */ .XZeroE, .YZeroE,
.XNaNE, .YNaNE, .MDUE, .n,
.XInfE, .YInfE, .WZero, .SpecialCaseM);
fdivsqrtiter fdivsqrtiter(
@ -88,5 +89,5 @@ module fdivsqrt(
.WS, .WC, .D, .FirstU, .FirstUM, .FirstC, .Firstun,
.SqrtM, .SpecialCaseM, .RemOpM(Funct3M[1]), .ForwardedSrcAE,
.n, .ALTBM, .m, .BZero, .As,
.QmM, .WZero, .DivSM);
.QmM, .WZero, .DivSM, .FPIntDivResultM);
endmodule

View File

@ -42,7 +42,7 @@ module fdivsqrtfsm(
input logic SqrtE,
input logic StallE,
input logic StallM,
input logic TrapM,
input logic FlushE,
input logic WZero,
input logic MDUE,
input logic [`DIVBLEN:0] n,
@ -107,7 +107,7 @@ module fdivsqrtfsm(
/* verilator lint_on WIDTH */
always_ff @(posedge clk) begin
if (reset | TrapM) begin
if (reset | FlushE) begin
state <= #1 IDLE;
end else if (IFDivStartE) begin
step <= cycles;

View File

@ -43,7 +43,8 @@ module fdivsqrtpostproc(
input logic [`DIVBLEN:0] n, m,
output logic [`DIVb:0] QmM,
output logic WZero,
output logic DivSM
output logic DivSM,
output logic [`XLEN-1:0] FPIntDivResultM
);
logic [`DIVb+3:0] W, Sum, RemDM;
@ -53,7 +54,7 @@ module fdivsqrtpostproc(
logic [`DIVBLEN:0] NormShiftM;
logic [`DIVb:0] IntQuotM, NormQuotM;
logic [`DIVb+3:0] IntRemM, NormRemM;
logic [`DIVb+3:0] PreResultM, ResultM;
logic [`DIVb+3:0] PreResultM, PreFPIntDivResultM;
// check for early termination on an exact result. If the result is not exact, the sticky should be set
aplusbeq0 #(`DIVb+4) wspluswceq0(WS, WC, weq0);
@ -136,8 +137,9 @@ module fdivsqrtpostproc(
// division takes the result from the next cycle, which is shifted to the left one more time so the square root also needs to be shifted
assign ResultM = ($signed(PreResultM) >>> NormShiftM) + {{(`DIVb+3){1'b0}}, (PostIncM & ~RemOpM)};
assign PreFPIntDivResultM = ($signed(PreResultM) >>> NormShiftM) + {{(`DIVb+3){1'b0}}, (PostIncM & ~RemOpM)};
assign FPIntDivResultM = PreFPIntDivResultM[`XLEN-1:0];
assign PreQmM = NegStickyM ? FirstUM : FirstU; // Select U or U-1 depending on negative sticky bit
assign QmM = SqrtM ? (PreQmM << 1) : PreQmM;
endmodule

View File

@ -38,7 +38,7 @@ module fpu (
input logic [`FLEN-1:0] ReadDataW, // Read data (from LSU)
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Integer input (from IEU)
input logic StallE, StallM, StallW, // stall signals (from HZU)
input logic TrapM,
//input logic TrapM,
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
input logic [4:0] RdM, RdW, // which FP register to write to (from IEU)
input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
@ -55,7 +55,8 @@ module fpu (
output logic FCvtIntW, // select FCvtIntRes (to IEU)
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
output logic IllegalFPUInstrM, // Is the instruction an illegal fpu instruction (to privileged unit)
output logic [4:0] SetFflagsM // FPU flags (to privileged unit)
output logic [4:0] SetFflagsM, // FPU flags (to privileged unit)
output logic [`XLEN-1:0] FPIntDivResultW
);
// FPU specifics:
@ -152,6 +153,7 @@ module fpu (
logic [`FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed
logic [`FLEN-1:0] BoxedOneE; // Zero value for Z for multiplication, with NaN boxing if needed
logic StallUnpackedM;
logic [`XLEN-1:0] FPIntDivResultM;
// DECODE STAGE
@ -266,8 +268,8 @@ module fpu (
fdivsqrt fdivsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]),
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .FDivStartE, .IDivStartE, .XsE,
.ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .Funct3M, .MDUE, .W64E,
.StallE, .StallM, .TrapM, .DivSM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .QeM,
.QmM /*, .DivDone(DivDoneM) */);
.StallE, .StallM, .FlushE, .DivSM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .QeM,
.QmM, .FPIntDivResultM /*, .DivDone(DivDoneM) */);
//
// compare
@ -387,7 +389,8 @@ module fpu (
// M/W pipe registers
flopenrc #(`FLEN) MWRegFp(clk, reset, FlushW, ~StallW, FpResM, FpResW);
flopenrc #(`XLEN) MWRegInt(clk, reset, FlushW, ~StallW, FCvtIntResM, FCvtIntResW);
flopenrc #(`XLEN) MWRegIntCvtRes(clk, reset, FlushW, ~StallW, FCvtIntResM, FCvtIntResW);
flopenrc #(`XLEN) MWRegIntDivRes(clk, reset, FlushW, ~StallW, FPIntDivResultM, FPIntDivResultW);
// BEGIN WRITEBACK STAGE

View File

@ -32,13 +32,13 @@
module hazard(
// Detect hazards
(* mark_debug = "true" *) input logic BPPredWrongE, CSRWriteFencePendingDEM, RetM, TrapM,
(* mark_debug = "true" *) input logic BPPredWrongE, CSRWriteFenceM, RetM, TrapM,
(* mark_debug = "true" *) input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD,
(* mark_debug = "true" *) input logic LSUStallM, IFUStallF,
(* mark_debug = "true" *) input logic FCvtIntStallD, FStallD,
(* mark_debug = "true" *) input logic FCvtIntStallD, FStallD,
(* mark_debug = "true" *) input logic DivBusyE,FDivBusyE,
(* mark_debug = "true" *) input logic EcallFaultM, BreakpointFaultM,
(* mark_debug = "true" *) input logic wfiM, IntPendingM,
(* mark_debug = "true" *) input logic wfiM, IntPendingM,
// Stall & flush outputs
(* mark_debug = "true" *) output logic StallF, StallD, StallE, StallM, StallW,
(* mark_debug = "true" *) output logic FlushD, FlushE, FlushM, FlushW
@ -46,6 +46,8 @@ module hazard(
logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause;
logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW;
logic FlushDCause, FlushECause, FlushMCause, FlushWCause;
// stalls and flushes
// loads: stall for one cycle if the subsequent instruction depends on the load
@ -59,23 +61,20 @@ module hazard(
// A stage must stall if the next stage is stalled
// If any stages are stalled, the first stage that isn't stalled must flush.
// *** can stalls be pushed into earlier stages (e.g. no stall after Decode?)
assign FlushDCause = TrapM | RetM | BPPredWrongE | CSRWriteFenceM;
assign FlushECause = TrapM | RetM | (BPPredWrongE & ~(DivBusyE | FDivBusyE)) | CSRWriteFenceM;
assign FlushMCause = TrapM | RetM | CSRWriteFenceM;
// on Trap the memory stage should be flushed going into the W stage,
// except if the instruction causing the Trap is an ecall or ebreak.
assign FlushWCause = TrapM & ~(BreakpointFaultM | EcallFaultM);
// *** consider replacing CSRWriteFencePendingDEM with a flush rather than a stall.
assign StallFCause = CSRWriteFencePendingDEM & ~(TrapM | RetM | BPPredWrongE);
assign StallFCause = '0;
// stall in decode if instruction is a load/mul/csr dependent on previous
assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | FStallD) & ~(TrapM | RetM | BPPredWrongE);
assign StallECause = (DivBusyE | FDivBusyE) & ~(TrapM); // *** can we move to decode stage (KP?)
assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | FStallD) & ~FlushDCause;
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
// WFI terminates if any enabled interrupt is pending, even if global interrupts are disabled. It could also terminate with TW trap
assign StallMCause = ((wfiM) & (~TrapM & ~IntPendingM));
assign StallWCause = ((IFUStallF | LSUStallM) & ~TrapM); // | (FDivBusyE & ~TrapM & ~IntPendingM);
// head version
// assign StallWCause = LSUStallM | IFUStallF | (FDivBusyE & ~TrapM & ~IntPendingM); // *** FDivBusyE should look like DivBusyE
// assign StallMCause = (wfiM & (~TrapM & ~IntPendingM)); // | FDivBusyE;
// assign StallECause = (DivBusyE | FDivBusyE) & ~(TrapM); // *** can we move to decode stage (KP?)
// *** ross: my changes to cache and lsu need to disable ifu/lsu stalls on a Trap.
assign StallWCause = (IFUStallF | LSUStallM) & ~TrapM;
assign #1 StallF = StallFCause | StallD;
assign #1 StallD = StallDCause | StallE;
@ -89,10 +88,8 @@ module hazard(
assign FirstUnstalledW = ~StallW & StallM;
// Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush
assign #1 FlushD = FirstUnstalledD | TrapM | RetM | BPPredWrongE;
assign #1 FlushE = FirstUnstalledE | TrapM | RetM | BPPredWrongE; // *** why is BPPredWrongE here, but not needed in simple processor
assign #1 FlushM = FirstUnstalledM | TrapM | RetM;
// on Trap the memory stage should be flushed going into the W stage,
// except if the instruction causing the Trap is an ecall or ebreak.
assign #1 FlushW = FirstUnstalledW | (TrapM & ~(BreakpointFaultM | EcallFaultM));
assign #1 FlushD = FirstUnstalledD | FlushDCause;
assign #1 FlushE = FirstUnstalledE | FlushECause ; // *** why is BPPredWrongE here, but not needed in simple processor
assign #1 FlushM = FirstUnstalledM | FlushMCause;
assign #1 FlushW = FirstUnstalledW | FlushWCause;
endmodule

View File

@ -65,10 +65,11 @@ module controller(
output logic FWriteIntM,
// Writeback stage control signals
input logic StallW, FlushW,
output logic RegWriteW, // for datapath and Hazard Unit
output logic RegWriteW, DivW, // for datapath and Hazard Unit
output logic [2:0] ResultSrcW,
// Stall during CSRs
output logic CSRWriteFencePendingDEM,
//output logic CSRWriteFencePendingDEM,
output logic CSRWriteFenceM,
output logic StoreStallD
);
@ -92,7 +93,7 @@ module controller(
logic CSRZeroSrcD;
logic CSRReadD;
logic [1:0] AtomicD;
logic FenceD;
logic FenceXD;
logic InvalidateICacheD, FlushDCacheD;
logic CSRWriteD, CSRWriteE;
logic InstrValidD, InstrValidE;
@ -108,7 +109,9 @@ module controller(
logic IEURegWriteE;
logic IllegalERegAdrD;
logic [1:0] AtomicE;
logic FencePendingD, FencePendingE, FencePendingM;
logic FenceD, FenceE, FenceM;
logic SFenceVmaD;
logic DivE, DivM;
// Extract fields
@ -176,11 +179,12 @@ module controller(
assign IllegalBaseInstrFaultD = ControlsD[0] | IllegalERegAdrD;
assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD,
ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, W64D, CSRReadD,
PrivilegedD, FenceD, MDUD, AtomicD, unused} = IllegalIEUInstrFaultD ? `CTRLW'b0 : ControlsD;
PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUInstrFaultD ? `CTRLW'b0 : ControlsD;
assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source?
assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros
assign FencePendingD = PrivilegedD & (InstrD[31:25] == 7'b0001001) | FenceD; // possible sfence.vma or fence.i
assign SFenceVmaD = PrivilegedD & (InstrD[31:25] == 7'b0001001);
assign FenceD = SFenceVmaD | FenceXD; // possible sfence.vma or fence.i
// ALU Decoding is lazy, only using func7[5] to distinguish add/sub and srl/sra
assign sltD = (Funct3D == 3'b010);
@ -195,7 +199,7 @@ module controller(
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
if (`ZIFENCEI_SUPPORTED & `ICACHE) begin:fencei
logic FenceID;
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
assign FenceID = FenceXD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
assign InvalidateICacheD = FenceID;
assign FlushDCacheD = FenceID;
end else begin:fencei
@ -208,8 +212,8 @@ module controller(
// Execute stage pipeline control register and logic
flopenrc #(28) controlregE(clk, reset, FlushE, ~StallE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FencePendingD, InstrValidD},
{IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FencePendingE, InstrValidE});
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD},
{IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE});
// Branch Logic
assign BranchSignedE = ~(Funct3E[2:1] == 2'b11);
@ -222,19 +226,21 @@ module controller(
assign MemReadE = MemRWE[1];
assign SCE = (ResultSrcE == 3'b100);
assign RegWriteE = IEURegWriteE | FWriteIntE; // IRF register writes could come from IEU or FPU controllers
assign DivE = MDUE & Funct3E[2]; // Division operation
// Memory stage pipeline control register
flopenrc #(19) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FencePendingE, InstrValidE},
{RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FencePendingM, InstrValidM});
flopenrc #(20) controlregM(clk, reset, FlushM, ~StallM,
{RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, DivE},
{RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, DivM});
// Writeback stage pipeline control register
flopenrc #(4) controlregW(clk, reset, FlushW, ~StallW,
{RegWriteM, ResultSrcM},
{RegWriteW, ResultSrcW});
flopenrc #(5) controlregW(clk, reset, FlushW, ~StallW,
{RegWriteM, ResultSrcM, DivM},
{RegWriteW, ResultSrcW, DivW});
// Stall pipeline at Fetch if a CSR Write or Fence is pending in the subsequent stages
assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FencePendingD | FencePendingE | FencePendingM;
// Flush F, D, and E stages on a CSR write or Fence.I or SFence.VMA
assign CSRWriteFenceM = CSRWriteM | FenceM;
// assign CSRWriteFencePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM | FenceD | FenceE | FenceM;
// the synchronous DTIM cannot read immediately after write
// a cache cannot read or write immediately after a write

View File

@ -57,14 +57,15 @@ module datapath (
output logic [`XLEN-1:0] WriteDataM,
// Writeback stage signals
input logic StallW, FlushW,
(* mark_debug = "true" *) input logic RegWriteW,
(* mark_debug = "true" *) input logic RegWriteW, DivW,
input logic SquashSCW,
input logic [2:0] ResultSrcW,
input logic [`XLEN-1:0] FCvtIntResW,
input logic [`XLEN-1:0] ReadDataW,
// input logic [`XLEN-1:0] PCLinkW,
input logic [`XLEN-1:0] CSRReadValW, MDUResultW,
// Hazard Unit signals
input logic [`XLEN-1:0] FPIntDivResultW,
// Hazard Unit signals
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
output logic [4:0] RdE, RdM, RdW
);
@ -85,7 +86,7 @@ module datapath (
// Writeback stage signals
logic [`XLEN-1:0] SCResultW;
logic [`XLEN-1:0] ResultW;
logic [`XLEN-1:0] IFResultW, IFCvtResultW;
logic [`XLEN-1:0] IFResultW, IFCvtResultW, MulDivResultW;
// Decode stage
assign Rs1D = InstrD[19:15];
@ -125,10 +126,16 @@ module datapath (
if (`F_SUPPORTED) begin:fpmux
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, IFResultM);
mux2 #(`XLEN) cvtresultmuxW(IFResultW, FCvtIntResW, FCvtIntW, IFCvtResultW);
if (`IDIV_ON_FPU) begin
mux2 #(`XLEN) divresultmuxW(MDUResultW, FPIntDivResultW, DivW, MulDivResultW);
end else begin
assign MulDivResultW = MDUResultW;
end
end else begin:fpmux
assign IFResultM = IEUResultM; assign IFCvtResultW = IFResultW;
assign MulDivResultW = MDUResultW;
end
mux5 #(`XLEN) resultmuxW(IFCvtResultW, ReadDataW, CSRReadValW, MDUResultW, SCResultW, ResultSrcW, ResultW);
mux5 #(`XLEN) resultmuxW(IFCvtResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, ResultW);
// handle Store Conditional result if atomic extension supported
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};

View File

@ -58,6 +58,7 @@ module ieu (
output logic InvalidateICacheM, FlushDCacheM,
// Writeback stage
input logic [`XLEN-1:0] FPIntDivResultW,
input logic [`XLEN-1:0] CSRReadValW, MDUResultW,
input logic [`XLEN-1:0] FCvtIntResW,
output logic [4:0] RdW,
@ -70,7 +71,7 @@ module ieu (
output logic FCvtIntStallD, LoadStallD, MDUStallD, CSRRdStallD,
output logic PCSrcE,
output logic CSRReadM, CSRWriteM, PrivilegedM,
output logic CSRWriteFencePendingDEM,
output logic CSRWriteFenceM,
output logic StoreStallD
);
@ -83,6 +84,7 @@ module ieu (
logic SCE;
logic [4:0] RdE;
logic FWriteIntM;
logic DivW;
// forwarding signals
logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E;
@ -99,15 +101,15 @@ module ieu (
.Funct3E, .MDUE, .W64E, .JumpE, .SCE, .BranchSignedE, .StallM, .FlushM, .MemRWM,
.CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
.RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .ResultSrcW, .CSRWriteFencePendingDEM, .StoreStallD);
.StallW, .FlushW, .RegWriteW, .DivW, .ResultSrcW, .CSRWriteFenceM, .StoreStallD);
datapath dp(
.clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE,
.ALUControlE, .Funct3E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .JumpE, .BranchSignedE,
.PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE,
.StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW,
.StallW, .FlushW, .RegWriteW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW,
.CSRReadValW, .MDUResultW, .Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW);
.StallW, .FlushW, .RegWriteW, .DivW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW,
.CSRReadValW, .MDUResultW, .FPIntDivResultW, .Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW);
forward fw(
.Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW,

View File

@ -55,7 +55,8 @@ module ifu (
input logic RetM, TrapM,
output logic CommittedF,
input logic [`XLEN-1:0] PrivilegedNextPCM,
input logic InvalidateICacheM,
input logic CSRWriteFenceM,
input logic InvalidateICacheM,
output logic [31:0] InstrD, InstrM,
output logic [`XLEN-1:0] PCM,
// branch predictor
@ -288,10 +289,10 @@ module ifu (
assign PrivilegedChangePCM = RetM | TrapM;
mux2 #(`XLEN) pcmux1(.d0(PCNext0F), .d1(PCCorrectE), .s(BPPredWrongE), .y(PCNext1F));
if(`ICACHE)
mux2 #(`XLEN) pcmux2(.d0(PCNext1F), .d1(PCBPWrongInvalidate), .s(InvalidateICacheM),
// if(`ICACHE | `ZICSR_SUPPORTED)
mux2 #(`XLEN) pcmux2(.d0(PCNext1F), .d1(PCBPWrongInvalidate), .s(CSRWriteFenceM),
.y(PCNext2F));
else assign PCNext2F = PCNext1F;
// else assign PCNext2F = PCNext1F;
if(`ZICSR_SUPPORTED)
mux2 #(`XLEN) pcmux3(.d0(PCNext2F), .d1(PrivilegedNextPCM), .s(PrivilegedChangePCM),
.y(UnalignedPCNextF));

View File

@ -36,7 +36,7 @@ module intdivrestoring (
input logic clk,
input logic reset,
input logic StallM,
input logic TrapM,
input logic FlushE,
input logic DivSignedE, W64E,
input logic DivE,
//input logic [`XLEN-1:0] SrcAE, SrcBE,
@ -48,10 +48,10 @@ module intdivrestoring (
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype;
statetype state;
logic [`XLEN-1:0] W[`DIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] XQ[`DIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] W[`IDIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] XQ[`IDIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] DinE, XinE, DnE, DAbsBE, DAbsB, XnE, XInitE, WnM, XQnM;
localparam STEPBITS = $clog2(`XLEN/`DIV_BITSPERCYCLE);
localparam STEPBITS = $clog2(`XLEN/`IDIV_BITSPERCYCLE);
logic [STEPBITS:0] step;
logic Div0E, Div0M;
logic DivStartE, SignXE, SignDE, NegQE, NegWM, NegQM;
@ -91,8 +91,8 @@ module intdivrestoring (
//////////////////////////////
// initialization multiplexers on first cycle of operation
mux2 #(`XLEN) wmux(W[`DIV_BITSPERCYCLE], {`XLEN{1'b0}}, DivStartE, WNext);
mux2 #(`XLEN) xmux(XQ[`DIV_BITSPERCYCLE], XInitE, DivStartE, XQNext);
mux2 #(`XLEN) wmux(W[`IDIV_BITSPERCYCLE], {`XLEN{1'b0}}, DivStartE, WNext);
mux2 #(`XLEN) xmux(XQ[`IDIV_BITSPERCYCLE], XInitE, DivStartE, XQNext);
// registers before division steps
flopen #(`XLEN) wreg(clk, DivBusyE, WNext, W[0]);
@ -101,7 +101,7 @@ module intdivrestoring (
// one copy of divstep for each bit produced per cycle
genvar i;
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
for (i=0; i<`IDIV_BITSPERCYCLE; i = i+1)
intdivrestoringstep divstep(W[i], XQ[i], DAbsB, W[i+1], XQ[i+1]);
//////////////////////////////
@ -122,7 +122,7 @@ module intdivrestoring (
//////////////////////////////
always_ff @(posedge clk)
if (reset | TrapM) begin
if (reset | FlushE) begin
state <= IDLE;
end else if (DivStartE) begin
step <= 1;

View File

@ -42,7 +42,7 @@ module muldiv (
// Divide Done
output logic DivBusyE,
// hazards
input logic StallM, StallW, FlushM, FlushW, TrapM
input logic StallM, StallW, FlushE, FlushM, FlushW
);
logic [`XLEN-1:0] MDUResultM;
@ -59,10 +59,17 @@ module muldiv (
// Divide
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
assign DivE = MDUE & Funct3E[2];
assign DivSignedE = ~Funct3E[0];
intdivrestoring div(.clk, .reset, .StallM, .TrapM, .DivSignedE, .W64E, .DivE,
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
// When F extensions are supported, use the FPU divider instead
if (`IDIV_ON_FPU) begin
assign QuotM = 0;
assign RemM = 0;
assign DivBusyE = 0;
end else begin
assign DivE = MDUE & Funct3E[2];
assign DivSignedE = ~Funct3E[0];
intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE, .W64E, .DivE,
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
end
// Result multiplexer
always_comb

View File

@ -79,7 +79,7 @@ module wallypipelinedcore (
logic StoreAmoMisalignedFaultM, StoreAmoAccessFaultM;
logic InvalidateICacheM, FlushDCacheM;
logic PCSrcE;
logic CSRWriteFencePendingDEM;
logic CSRWriteFenceM;
logic DivBusyE;
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW;
@ -99,6 +99,7 @@ module wallypipelinedcore (
logic FpLoadStoreM;
logic [1:0] FResSelW;
logic [4:0] SetFflagsM;
logic [`XLEN-1:0] FPIntDivResultW;
// memory management unit signals
logic ITLBWriteF;
@ -182,7 +183,7 @@ module wallypipelinedcore (
.BPPredWrongE,
// Mem
.RetM, .TrapM, .CommittedF, .PrivilegedNextPCM, .InvalidateICacheM,
.RetM, .TrapM, .CommittedF, .PrivilegedNextPCM, .InvalidateICacheM, .CSRWriteFenceM,
.InstrD, .InstrM, .PCM, .InstrClassM, .BPPredDirWrongM,
.BTBPredPCWrongM, .RASPredPCWrongM, .BPPredClassNonCFIWrongM,
@ -228,7 +229,7 @@ module wallypipelinedcore (
.RdM, .FIntResM, .InvalidateICacheM, .FlushDCacheM,
// Writeback stage
.CSRReadValW, .MDUResultW,
.CSRReadValW, .MDUResultW, .FPIntDivResultW,
.RdW, .ReadDataW(ReadDataW[`XLEN-1:0]),
.InstrValidM,
.FCvtIntResW,
@ -240,7 +241,7 @@ module wallypipelinedcore (
.FCvtIntStallD, .LoadStallD, .MDUStallD, .CSRRdStallD,
.PCSrcE,
.CSRReadM, .CSRWriteM, .PrivilegedM,
.CSRWriteFencePendingDEM, .StoreStallD
.CSRWriteFenceM, .StoreStallD
); // integer execution unit: integer register file, datapath and controller
@ -316,7 +317,7 @@ module wallypipelinedcore (
hazard hzu(
.BPPredWrongE, .CSRWriteFencePendingDEM, .RetM, .TrapM,
.BPPredWrongE, .CSRWriteFenceM, .RetM, .TrapM,
.LoadStallD, .StoreStallD, .MDUStallD, .CSRRdStallD,
.LSUStallM, .IFUStallF,
.FCvtIntStallD, .FStallD,
@ -374,7 +375,7 @@ module wallypipelinedcore (
.ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .MDUE, .W64E,
.MDUResultW, .DivBusyE,
.StallM, .StallW, .FlushM, .FlushW, .TrapM
.StallM, .StallW, .FlushE, .FlushM, .FlushW
);
end else begin // no M instructions supported
assign MDUResultW = 0;
@ -389,7 +390,7 @@ module wallypipelinedcore (
.ReadDataW(ReadDataW[`FLEN-1:0]),// Read data from memory
.ForwardedSrcAE, // Integer input being processed (from IEU)
.StallE, .StallM, .StallW, // stall signals from HZU
.TrapM,
//.TrapM,
.FlushE, .FlushM, .FlushW, // flush signals from HZU
.RdM, .RdW, // which FP register to write to (from IEU)
.STATUS_FS, // is floating-point enabled?
@ -405,7 +406,8 @@ module wallypipelinedcore (
.FCvtIntW, // fpu result selection
.FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
.IllegalFPUInstrM, // Is the instruction an illegal fpu instruction
.SetFflagsM // FPU flags (to privileged unit)
.SetFflagsM, // FPU flags (to privileged unit)
.FPIntDivResultW
); // floating point unit
end else begin // no F_SUPPORTED or D_SUPPORTED; tie outputs low
assign FStallD = 0;

View File

@ -434,7 +434,7 @@ module riscvassertions;
initial begin
assert (`PMP_ENTRIES == 0 | `PMP_ENTRIES==16 | `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64");
assert (`S_SUPPORTED | `VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support");
assert (`DIV_BITSPERCYCLE == 1 | `DIV_BITSPERCYCLE==2 | `DIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: DIV_BITSPERCYCLE must be 1, 2, or 4");
assert (`IDIV_BITSPERCYCLE == 1 | `IDIV_BITSPERCYCLE==2 | `IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4");
assert (`F_SUPPORTED | ~`D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)");
assert (`D_SUPPORTED | ~`Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)");
assert (`F_SUPPORTED | ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)");
@ -463,6 +463,7 @@ module riscvassertions;
assert ((`DCACHE == 0 & `ICACHE == 0) | `BUS) else $error("Dcache and Icache requires DBUS.");
assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (!`DCACHE)) 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");
assert (`IDIV_ON_FPU == 0 | `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED");
end
// *** DH 8/23/

View File

@ -8,8 +8,7 @@ wally_workdir = $(work)/wally-riscv-arch-test
current_dir = $(shell pwd)
#XLEN ?= 64
all: root fsd_fld_tempfix arch32 wally32 wally32e arch64 wally64
#all: root fsd_fld_tempfix wally32
all: root arch32 wally32 wally32e arch64 wally64
root:
mkdir -p $(work_dir)
@ -20,14 +19,8 @@ root:
sed 's,{0},$(current_dir),g;s,{1},64gc,g' config.ini > config64.ini
sed 's,{0},$(current_dir),g;s,{1},32e,g' config.ini > config32e.ini
fsd_fld_tempfix:
# this is a temporary fix, there's a typo on the rv64i_m/D/src/d_fsd-align-01.S and rv64i_m/D/src/d_fld-align-01.S tests
# https://github.com/riscv-non-isa/riscv-arch-test/issues/266
find ../../addins/riscv-arch-test/riscv-test-suite -type f -name "*d_fld-align*.S" | xargs -I{} sed -i 's,regex(\.\*32\.\*),regex(\.\*64\.\*),g' {}
find ../../addins/riscv-arch-test/riscv-test-suite -type f -name "*d_fsd-align*.S" | xargs -I{} sed -i 's,regex(\.\*32\.\*),regex(\.\*64\.\*),g' {}
arch32:
riscof --verbose debug run --work-dir=$(work_dir) --config=config32.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser
riscof run --work-dir=$(work_dir) --config=config32.ini --suite=$(arch_dir)/riscv-test-suite/ --env=$(arch_dir)/riscv-test-suite/env --no-browser
rsync -a $(work_dir)/rv32i_m/ $(arch_workdir)/rv32i_m/ || echo "error suppressed"
arch64: