mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally
This commit is contained in:
commit
d7571bb9b1
1
.gitignore
vendored
1
.gitignore
vendored
@ -117,3 +117,4 @@ pipelined/srt/testgen
|
||||
pipelined/srt/qslc_r4a2
|
||||
pipelined/srt/qslc_r4a2.sv
|
||||
pipelined/srt/testvectors
|
||||
pipelined/regression/wkdir
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
4
pipelined/regression/wkdir/.gitignore
vendored
4
pipelined/regression/wkdir/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
19
pipelined/src/cache/cache.sv
vendored
19
pipelined/src/cache/cache.sv
vendored
@ -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
|
||||
|
4
pipelined/src/cache/cacheLRU.sv
vendored
4
pipelined/src/cache/cacheLRU.sv
vendored
@ -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.
|
||||
|
8
pipelined/src/cache/cachefsm.sv
vendored
8
pipelined/src/cache/cachefsm.sv
vendored
@ -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
|
||||
|
35
pipelined/src/cache/cacheway.sv
vendored
35
pipelined/src/cache/cacheway.sv
vendored
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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/
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user