mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 18:25:27 +00:00
Merge branch 'openhwgroup:main' into main
This commit is contained in:
commit
d3b1ce4c23
1
.gitignore
vendored
1
.gitignore
vendored
@ -42,6 +42,7 @@ tests/linux-testgen/buildroot-image-output
|
||||
tests/linux-testgen/buildroot-config-src/main.config.old
|
||||
tests/linux-testgen/buildroot-config-src/linux.config.old
|
||||
tests/linux-testgen/buildroot-config-src/busybox.config.old
|
||||
linux/buildroot
|
||||
linux/testvector-generation/boottrace.S
|
||||
linux/testvector-generation/boottrace_disasm.log
|
||||
sim/slack-notifier/slack-webhook-url.txt
|
||||
|
@ -21,7 +21,7 @@ ROOT := ..
|
||||
LIBRARY_DIRS :=
|
||||
LIBRARY_FILES :=
|
||||
|
||||
MARCH :=-march=rv64imfdc
|
||||
MARCH :=-march=rv64imfdc_zifencei
|
||||
MABI :=-mabi=lp64d
|
||||
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
|
||||
LINKER :=linker.x
|
@ -94,5 +94,5 @@ end_of_bios:
|
||||
.globl _dtb
|
||||
.align 4, 0
|
||||
_dtb:
|
||||
.incbin "wally-vcu118.dtb"
|
||||
#.incbin "wally-vcu118.dtb"
|
||||
|
@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////
|
||||
// SDC.sv
|
||||
//
|
||||
// Written: Ross Thompson September 25, 2021
|
||||
// Written: Rose Thompson September 25, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: driver for sdc reader.
|
@ -222,63 +222,63 @@ if (nightly):
|
||||
|
||||
### branch predictor simulation
|
||||
|
||||
["bpred_TWOBIT_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_TWOBIT_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_TWOBIT_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
|
||||
["bpred_GSHARE_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
|
||||
# btb
|
||||
["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_8_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_12_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# # btb
|
||||
# ["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_8_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_12_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
|
||||
# ras
|
||||
["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_3_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_4_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_6_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_10_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# # ras
|
||||
# ["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_3_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_4_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_6_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_10_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
# ["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
|
||||
|
||||
# enable floating-point tests when lint is fixed
|
||||
["f_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma"]],
|
||||
["fh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32zfh", "arch32zfh_divsqrt"]],
|
||||
["fdh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
|
||||
["fdq_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
|
||||
["fdq_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma"]],
|
||||
["fdqh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
|
||||
["f_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma"]],
|
||||
["fh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64zfh", "arch64zfh_divsqrt"]], # hanging 1/31/24 dh; try again when lint is fixed
|
||||
["fdh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
|
||||
["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
|
||||
["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
|
||||
["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma"]],
|
||||
["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "wally64q"]],
|
||||
|
||||
|
||||
]
|
||||
|
18
src/cache/cache.sv
vendored
18
src/cache/cache.sv
vendored
@ -82,7 +82,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
logic ClearDirty, SetDirty, SetValid, ClearValid;
|
||||
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
|
||||
logic [NUMWAYS-1:0] HitWay, ValidWay;
|
||||
logic CacheHit;
|
||||
logic Hit;
|
||||
logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay;
|
||||
logic LineDirty, HitLineDirty;
|
||||
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0];
|
||||
@ -98,7 +98,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
|
||||
logic SelFetchBuffer;
|
||||
logic CacheEn;
|
||||
logic SelWay;
|
||||
logic SelVictim;
|
||||
logic [LINELEN/8-1:0] LineByteMask;
|
||||
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
||||
genvar index;
|
||||
@ -120,7 +120,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
|
||||
// Array of cache ways, along with victim, hit, dirty, and read merging logic
|
||||
cacheway #(P, PA_BITS, XLEN, NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
|
||||
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelWay,
|
||||
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelVictim,
|
||||
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
|
||||
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
|
||||
|
||||
@ -132,7 +132,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
end else
|
||||
assign VictimWay = 1'b1; // one hot.
|
||||
|
||||
assign CacheHit = |HitWay;
|
||||
assign Hit = |HitWay;
|
||||
assign LineDirty = |DirtyWay;
|
||||
assign HitLineDirty = |HitDirtyWay;
|
||||
|
||||
@ -176,18 +176,18 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
|
||||
logic [LINELEN/8-1:0] BlankByteMask;
|
||||
assign BlankByteMask[WORDLEN/8-1:0] = ByteMask;
|
||||
assign BlankByteMask[LINELEN/8-1:WORDLEN/8] = '0;
|
||||
assign BlankByteMask[LINELEN/8-1:WORDLEN/8] = 0;
|
||||
|
||||
assign DemuxedByteMask = BlankByteMask << ((MUXINTERVAL/8) * WordOffsetAddr);
|
||||
|
||||
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
|
||||
assign FetchBufferByteSel = SetDirty ? ~DemuxedByteMask : '1; // If load miss set all muxes to 1.
|
||||
|
||||
// Merge write data into fetched cache line for store miss
|
||||
for(index = 0; index < LINELEN/8; index++) begin
|
||||
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
||||
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index]));
|
||||
end
|
||||
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
||||
assign LineByteMask = SetDirty ? DemuxedByteMask : '1;
|
||||
end
|
||||
else
|
||||
begin:WriteSelLogic
|
||||
@ -226,8 +226,8 @@ module cache import cvw::*; #(parameter cvw_t P,
|
||||
|
||||
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
|
||||
.FlushStage, .CacheRW, .Stall,
|
||||
.CacheHit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
|
||||
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelWay,
|
||||
.Hit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
|
||||
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelVictim,
|
||||
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
|
||||
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
|
||||
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,
|
||||
|
55
src/cache/cacheLRU.sv
vendored
55
src/cache/cacheLRU.sv
vendored
@ -1,7 +1,7 @@
|
||||
///////////////////////////////////////////
|
||||
// cacheLRU.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com
|
||||
// Written: Rose Thompson ross1728@gmail.com
|
||||
// Created: 20 July 2021
|
||||
// Modified: 20 January 2023
|
||||
//
|
||||
@ -36,8 +36,8 @@ module cacheLRU
|
||||
input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant
|
||||
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
|
||||
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
|
||||
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||
input logic [SETLEN-1:0] PAdr, // Physical address
|
||||
input logic LRUWriteEn, // Update the LRU state
|
||||
input logic SetValid, // Set the dirty bit in the selected way and set
|
||||
@ -51,23 +51,27 @@ module cacheLRU
|
||||
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
|
||||
logic [NUMWAYS-2:0] CurrLRU;
|
||||
logic [NUMWAYS-2:0] NextLRU;
|
||||
logic [NUMWAYS-1:0] Way;
|
||||
logic [LOGNUMWAYS-1:0] WayEncoded;
|
||||
logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
|
||||
logic [NUMWAYS-2:0] WayExpanded;
|
||||
logic AllValid;
|
||||
|
||||
genvar row;
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
// Ross: For some reason verilator does not like this. I checked and it is not a circular path.
|
||||
// Rose: For some reason verilator does not like this. I checked and it is not a circular path.
|
||||
logic [NUMWAYS-2:0] LRUUpdate;
|
||||
logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0];
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
|
||||
logic [NUMWAYS-1:0] FirstZero;
|
||||
logic [LOGNUMWAYS-1:0] FirstZeroWay;
|
||||
logic [LOGNUMWAYS-1:0] VictimWayEnc;
|
||||
|
||||
binencoder #(NUMWAYS) hitwayencoder(HitWay, HitWayEncoded);
|
||||
|
||||
assign AllValid = &ValidWay;
|
||||
|
||||
///// Update replacement bits.
|
||||
|
||||
// coverage off
|
||||
// Excluded from coverage b/c it is untestable without varying NUMWAYS.
|
||||
function integer log2 (integer value);
|
||||
@ -80,8 +84,7 @@ module cacheLRU
|
||||
// coverage on
|
||||
|
||||
// On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay.
|
||||
mux2 #(NUMWAYS) WayMux(HitWay, VictimWay, SetValid, Way);
|
||||
binencoder #(NUMWAYS) encoder(Way, WayEncoded);
|
||||
mux2 #(LOGNUMWAYS) WayMuxEnc(HitWayEncoded, VictimWayEnc, SetValid, Way);
|
||||
|
||||
// bit duplication
|
||||
// expand HitWay as HitWay[3], {{2}{HitWay[2]}}, {{4}{HitWay[1]}, {{8{HitWay[0]}}, ...
|
||||
@ -89,7 +92,7 @@ module cacheLRU
|
||||
localparam integer DuplicationFactor = 2**(LOGNUMWAYS-row-1);
|
||||
localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1;
|
||||
localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2;
|
||||
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{WayEncoded[row]}};
|
||||
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{Way[row]}};
|
||||
end
|
||||
|
||||
genvar node;
|
||||
@ -102,14 +105,14 @@ module cacheLRU
|
||||
localparam r = LOGNUMWAYS - ctr_depth;
|
||||
|
||||
// the child node will be updated if its parent was updated and
|
||||
// the WayEncoded bit was the correct value.
|
||||
// the Way bit was the correct value.
|
||||
// The if statement is only there for coverage since LRUUpdate[root] is always 1.
|
||||
if (node == NUMWAYS-2) begin
|
||||
assign LRUUpdate[lchild] = ~WayEncoded[r];
|
||||
assign LRUUpdate[rchild] = WayEncoded[r];
|
||||
assign LRUUpdate[lchild] = ~Way[r];
|
||||
assign LRUUpdate[rchild] = Way[r];
|
||||
end else begin
|
||||
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
|
||||
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
|
||||
assign LRUUpdate[lchild] = LRUUpdate[node] & ~Way[r];
|
||||
assign LRUUpdate[rchild] = LRUUpdate[node] & Way[r];
|
||||
end
|
||||
end
|
||||
|
||||
@ -129,28 +132,26 @@ module cacheLRU
|
||||
assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0];
|
||||
end
|
||||
|
||||
logic [NUMWAYS-1:0] FirstZero;
|
||||
logic [LOGNUMWAYS-1:0] FirstZeroWay;
|
||||
logic [LOGNUMWAYS-1:0] VictimWayEnc;
|
||||
|
||||
priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero);
|
||||
binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay);
|
||||
mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc);
|
||||
//decoder #(LOGNUMWAYS) decoder (Intermediate[NUMWAYS-2], VictimWay);
|
||||
decoder #(LOGNUMWAYS) decoder (VictimWayEnc, VictimWay);
|
||||
|
||||
// LRU storage must be reset for modelsim to run. However the reset value does not actually matter in practice.
|
||||
// This is a two port memory.
|
||||
// Every cycle must read from CacheSetData and each load/store must write the new LRU.
|
||||
|
||||
// note: Verilator lint doesn't like <= for array initialization (https://verilator.org/warn/BLKLOOPINIT?v=5.021)
|
||||
// Move to = to keep Verilator happy and simulator running fast
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset | (InvalidateCache & ~FlushStage)) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
|
||||
if(CacheEn) begin
|
||||
if(LRUWriteEn)
|
||||
LRUMemory[PAdr] <= NextLRU;
|
||||
if(LRUWriteEn & (PAdr == CacheSetTag))
|
||||
CurrLRU <= NextLRU;
|
||||
else
|
||||
CurrLRU <= LRUMemory[CacheSetTag];
|
||||
if (reset | (InvalidateCache & ~FlushStage))
|
||||
for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = 0; // exclusion-tag: initialize
|
||||
else if(CacheEn) begin
|
||||
// Because we are using blocking assignments, change to LRUMemory must occur after LRUMemory is used so we get the proper value
|
||||
if(LRUWriteEn & (PAdr == CacheSetTag)) CurrLRU = #1 NextLRU;
|
||||
else CurrLRU = #1 LRUMemory[CacheSetTag];
|
||||
if(LRUWriteEn) LRUMemory[PAdr] = NextLRU;
|
||||
end
|
||||
end
|
||||
|
||||
|
76
src/cache/cachefsm.sv
vendored
76
src/cache/cachefsm.sv
vendored
@ -50,7 +50,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
output logic CacheAccess, // Cache access
|
||||
|
||||
// cache internals
|
||||
input logic CacheHit, // Exactly 1 way hits
|
||||
input logic Hit, // Exactly 1 way hits
|
||||
input logic LineDirty, // The selected line and way is dirty
|
||||
input logic HitLineDirty, // The cache hit way is dirty
|
||||
input logic FlushAdrFlag, // On last set of a cache flush
|
||||
@ -63,7 +63,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
||||
output logic LRUWriteEn, // Update the LRU state
|
||||
output logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
|
||||
output logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
|
||||
output logic FlushWayCntEn, // Enable the way counter during a flush
|
||||
output logic FlushCntRst, // Reset both flush counters
|
||||
@ -79,12 +79,12 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
logic CMOZeroNoEviction;
|
||||
logic StallConditions;
|
||||
|
||||
typedef enum logic [3:0]{STATE_READY, // hit states
|
||||
typedef enum logic [3:0]{STATE_ACCESS, // hit states
|
||||
// miss states
|
||||
STATE_FETCH,
|
||||
STATE_WRITEBACK,
|
||||
STATE_WRITE_LINE,
|
||||
STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM
|
||||
STATE_ADDRESS_SETUP, // required for back to back reads. structural hazard on writting SRAM
|
||||
// flush cache
|
||||
STATE_FLUSH,
|
||||
STATE_FLUSH_WRITEBACK
|
||||
@ -92,60 +92,60 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
|
||||
statetype CurrState, NextState;
|
||||
|
||||
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||
assign AnyUpdateHit = (CacheRW[0]) & CacheHit; // exclusion-tag: icache storeAMO1
|
||||
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit
|
||||
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||
assign AnyUpdateHit = (CacheRW[0]) & Hit; // exclusion-tag: icache storeAMO1
|
||||
assign AnyHit = AnyUpdateHit | (CacheRW[1] & Hit); // exclusion-tag: icache AnyUpdateHit
|
||||
assign CMOZeroNoEviction = CMOpM[3] & ~LineDirty; // (hit or miss) with no writeback store zeros now
|
||||
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & CacheHit & HitLineDirty) | CMOpM[3] & LineDirty;
|
||||
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & Hit & HitLineDirty) | CMOpM[3] & LineDirty;
|
||||
|
||||
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
|
||||
|
||||
// outputs for the performance counters.
|
||||
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_READY & ~Stall & ~FlushStage) | (CurrState == STATE_READ_HOLD & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
|
||||
assign CacheMiss = CacheAccess & ~CacheHit;
|
||||
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_ACCESS & ~Stall & ~FlushStage) | (CurrState == STATE_ADDRESS_SETUP & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
|
||||
assign CacheMiss = CacheAccess & ~Hit;
|
||||
|
||||
// special case on reset. When the fsm first exists reset the
|
||||
// special case on reset. When the fsm first exists reset twayhe
|
||||
// PCNextF will no longer be pointing to the correct address.
|
||||
// But PCF will be the reset vector.
|
||||
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if (reset | FlushStage) CurrState <= #1 STATE_READY;
|
||||
if (reset | FlushStage) CurrState <= #1 STATE_ACCESS;
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
always_comb begin
|
||||
NextState = STATE_READY;
|
||||
NextState = STATE_ACCESS;
|
||||
case (CurrState) // exclusion-tag: icache state-case
|
||||
STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck
|
||||
STATE_ACCESS: if(InvalidateCache) NextState = STATE_ACCESS; // exclusion-tag: dcache InvalidateCheck
|
||||
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; // exclusion-tag: icache FLUSHStatement
|
||||
else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement
|
||||
else if((AnyMiss | CMOWriteback) & ~READ_ONLY_CACHE) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
|
||||
else NextState = STATE_READY;
|
||||
else NextState = STATE_ACCESS;
|
||||
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
|
||||
else NextState = STATE_FETCH;
|
||||
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
|
||||
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
|
||||
else NextState = STATE_READY;
|
||||
STATE_WRITE_LINE: NextState = STATE_ADDRESS_SETUP;
|
||||
STATE_ADDRESS_SETUP: if(Stall) NextState = STATE_ADDRESS_SETUP;
|
||||
else NextState = STATE_ACCESS;
|
||||
// exclusion-tag-start: icache case
|
||||
STATE_WRITEBACK: if(CacheBusAck & ~(|CMOpM[3:1])) NextState = STATE_FETCH;
|
||||
else if(CacheBusAck) NextState = STATE_READ_HOLD; // Read_hold lowers CacheStall
|
||||
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP; // Read_hold lowers CacheStall
|
||||
else NextState = STATE_WRITEBACK;
|
||||
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
|
||||
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
|
||||
else if (FlushFlag) NextState = STATE_READ_HOLD;
|
||||
else if (FlushFlag) NextState = STATE_ADDRESS_SETUP;
|
||||
else NextState = STATE_FLUSH;
|
||||
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
|
||||
else if(CacheBusAck) NextState = STATE_READ_HOLD;
|
||||
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP;
|
||||
else NextState = STATE_FLUSH_WRITEBACK;
|
||||
// exclusion-tag-end: icache case
|
||||
default: NextState = STATE_READY;
|
||||
default: NextState = STATE_ACCESS;
|
||||
endcase
|
||||
end
|
||||
|
||||
// com back to CPU
|
||||
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & (CurrState == STATE_READ_HOLD));
|
||||
assign CacheCommitted = (CurrState != STATE_ACCESS) & ~(READ_ONLY_CACHE & (CurrState == STATE_ADDRESS_SETUP));
|
||||
assign StallConditions = FlushCache | AnyMiss | CMOWriteback; // exclusion-tag: icache FlushCache
|
||||
assign CacheStall = (CurrState == STATE_READY & StallConditions) | // exclusion-tag: icache StallStates
|
||||
assign CacheStall = (CurrState == STATE_ACCESS & StallConditions) | // exclusion-tag: icache StallStates
|
||||
(CurrState == STATE_FETCH) |
|
||||
(CurrState == STATE_WRITEBACK) |
|
||||
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
|
||||
@ -153,26 +153,26 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
(CurrState == STATE_FLUSH_WRITEBACK);
|
||||
// write enables internal to cache
|
||||
assign SetValid = CurrState == STATE_WRITE_LINE |
|
||||
(CurrState == STATE_READY & CMOZeroNoEviction) |
|
||||
(CurrState == STATE_ACCESS & CMOZeroNoEviction) |
|
||||
(CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]);
|
||||
assign ClearValid = (CurrState == STATE_READY & CMOpM[0]) |
|
||||
assign ClearValid = (CurrState == STATE_ACCESS & CMOpM[0]) |
|
||||
(CurrState == STATE_WRITEBACK & CMOpM[2] & CacheBusAck);
|
||||
assign LRUWriteEn = (((CurrState == STATE_READY & (AnyHit | CMOZeroNoEviction)) |
|
||||
assign LRUWriteEn = (((CurrState == STATE_ACCESS & (AnyHit | CMOZeroNoEviction)) |
|
||||
(CurrState == STATE_WRITE_LINE)) & ~FlushStage) |
|
||||
(CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck);
|
||||
// exclusion-tag-start: icache flushdirtycontrols
|
||||
assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
|
||||
assign SetDirty = (CurrState == STATE_ACCESS & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
|
||||
(CurrState == STATE_WRITE_LINE & (CacheRW[0])) |
|
||||
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
|
||||
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty
|
||||
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
|
||||
// Flush and eviction controls
|
||||
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
|
||||
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
|
||||
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~CacheHit))) |
|
||||
assign SelVictim = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
|
||||
(CurrState == STATE_ACCESS & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~Hit))) |
|
||||
(CurrState == STATE_WRITE_LINE);
|
||||
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) |
|
||||
(CurrState == STATE_READY & AnyMiss & LineDirty);
|
||||
(CurrState == STATE_ACCESS & AnyMiss & LineDirty);
|
||||
// coverage off -item e 1 -fecexprrow 1
|
||||
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
|
||||
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
|
||||
@ -183,29 +183,29 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
|
||||
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
|
||||
// exclusion-tag-end: icache flushdirtycontrols
|
||||
// Bus interface controls
|
||||
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
|
||||
assign CacheBusRW[1] = (CurrState == STATE_ACCESS & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
|
||||
(CurrState == STATE_FETCH & ~CacheBusAck) |
|
||||
(CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM));
|
||||
|
||||
logic LoadMiss;
|
||||
assign LoadMiss = (CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||
assign LoadMiss = (CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
|
||||
|
||||
assign CacheBusRW[0] = (CurrState == STATE_READY & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
|
||||
assign CacheBusRW[0] = (CurrState == STATE_ACCESS & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
|
||||
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
|
||||
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
|
||||
(CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & ~CacheBusAck);
|
||||
|
||||
assign SelAdrData = (CurrState == STATE_READY & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
|
||||
assign SelAdrData = (CurrState == STATE_ACCESS & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
|
||||
(CurrState == STATE_FETCH) |
|
||||
(CurrState == STATE_WRITEBACK) |
|
||||
(CurrState == STATE_WRITE_LINE) |
|
||||
resetDelay;
|
||||
assign SelAdrTag = (CurrState == STATE_READY & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
|
||||
assign SelAdrTag = (CurrState == STATE_ACCESS & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
|
||||
(CurrState == STATE_FETCH) |
|
||||
(CurrState == STATE_WRITEBACK) |
|
||||
(CurrState == STATE_WRITE_LINE) |
|
||||
resetDelay;
|
||||
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
|
||||
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
|
||||
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_ADDRESS_SETUP;
|
||||
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_ACCESS) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
|
||||
|
||||
endmodule // cachefsm
|
||||
|
39
src/cache/cacheway.sv
vendored
39
src/cache/cacheway.sv
vendored
@ -42,7 +42,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||
input logic SetValid, // Set the valid bit in the selected way and set
|
||||
input logic ClearValid, // Clear the valid bit in the selected way and set
|
||||
input logic SetDirty, // Set the dirty bit in the selected way and set
|
||||
input logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
|
||||
input logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
input logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
||||
input logic VictimWay, // LRU selected this way as victim to evict
|
||||
@ -68,7 +68,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||
logic [LINELEN-1:0] ReadDataLine;
|
||||
logic [TAGLEN-1:0] ReadTag;
|
||||
logic Dirty;
|
||||
logic SelDirty;
|
||||
logic SelecteDirty;
|
||||
logic SelectedWriteWordEn;
|
||||
logic [LINELEN/8-1:0] FinalByteMask;
|
||||
logic SetValidEN, ClearValidEN;
|
||||
@ -77,33 +77,30 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||
logic SetDirtyWay;
|
||||
logic ClearDirtyWay;
|
||||
logic SelNonHit;
|
||||
logic SelData;
|
||||
logic SelectedWay;
|
||||
logic InvalidateCacheDelay;
|
||||
|
||||
if (!READ_ONLY_CACHE) begin:flushlogic
|
||||
logic FlushWayEn;
|
||||
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelDirty);
|
||||
|
||||
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelecteDirty);
|
||||
mux3 #(1) selectedmux(HitWay, FlushWay, VictimWay, {SelVictim, FlushCache}, SelectedWay);
|
||||
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
|
||||
// coverage off -item e 1 -fecexprrow 3
|
||||
// nonzero ways will never see FlushCache=0 while FlushWay=1 since FlushWay only advances on a subset of FlushCache assertion cases.
|
||||
assign FlushWayEn = FlushWay & FlushCache;
|
||||
assign SelNonHit = FlushWayEn | SelWay;
|
||||
end else begin:flushlogic // no flush operation for read-only caches.
|
||||
assign SelDirty = VictimWay;
|
||||
assign SelNonHit = SelWay;
|
||||
assign SelecteDirty = VictimWay;
|
||||
mux2 #(1) selectedwaymux(HitWay, SelecteDirty, SelVictim , SelectedWay);
|
||||
end
|
||||
|
||||
mux2 #(1) selectedwaymux(HitWay, SelDirty, SelNonHit , SelData);
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Write Enable demux
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
assign SetValidWay = SetValid & SelData;
|
||||
assign ClearValidWay = ClearValid & SelData; // exclusion-tag: icache ClearValidWay
|
||||
assign SetDirtyWay = SetDirty & SelData; // exclusion-tag: icache SetDirtyWay
|
||||
assign ClearDirtyWay = ClearDirty & SelData;
|
||||
assign SetValidWay = SetValid & SelectedWay;
|
||||
assign ClearValidWay = ClearValid & SelectedWay; // exclusion-tag: icache ClearValidWay
|
||||
assign SetDirtyWay = SetDirty & SelectedWay; // exclusion-tag: icache SetDirtyWay
|
||||
assign ClearDirtyWay = ClearDirty & SelectedWay;
|
||||
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
|
||||
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
|
||||
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN
|
||||
@ -120,9 +117,9 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
||||
|
||||
// AND portion of distributed tag multiplexer
|
||||
assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux
|
||||
assign TagWay = SelectedWay ? ReadTag : 0; // AND part of AOMux
|
||||
assign HitDirtyWay = Dirty & ValidWay;
|
||||
assign DirtyWay = SelDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
|
||||
assign DirtyWay = SelecteDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
|
||||
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; // exclusion-tag: dcache HitWay
|
||||
|
||||
flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay);
|
||||
@ -152,19 +149,19 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||
end
|
||||
|
||||
// AND portion of distributed read multiplexers
|
||||
assign ReadDataLineWay = SelData ? ReadDataLine : '0; // AND part of AO mux.
|
||||
assign ReadDataLineWay = SelectedWay ? ReadDataLine : 0; // AND part of AO mux.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Valid Bits
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge clk) begin // Valid bit array,
|
||||
if (reset) ValidBits <= #1 '0;
|
||||
if (reset) ValidBits <= #1 0;
|
||||
if(CacheEn) begin
|
||||
ValidWay <= #1 ValidBits[CacheSetTag];
|
||||
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
|
||||
if(InvalidateCache) ValidBits <= #1 0; // exclusion-tag: dcache invalidateway
|
||||
else if (SetValidEN) ValidBits[CacheSetData] <= #1 SetValidWay;
|
||||
else if (ClearValidEN) ValidBits[CacheSetData] <= #1 '0; // exclusion-tag: icache ClearValidBits
|
||||
else if (ClearValidEN) ValidBits[CacheSetData] <= #1 0; // exclusion-tag: icache ClearValidBits
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -62,8 +62,8 @@ module ahbinterface #(
|
||||
flop #(XLEN) wdreg(HCLK, WriteData, HWDATA);
|
||||
flop #(XLEN/8) HWSTRBReg(HCLK, ByteMask, HWSTRB);
|
||||
end else begin
|
||||
assign HWDATA = '0;
|
||||
assign HWSTRB = '0;
|
||||
assign HWDATA = 0;
|
||||
assign HWSTRB = 0;
|
||||
end
|
||||
|
||||
busfsm #(~LSU) busfsm(.HCLK, .HRESETn, .Flush, .BusRW, .BusAtomic,
|
||||
|
@ -111,11 +111,11 @@ module ebu import cvw::*; #(parameter cvw_t P) (
|
||||
.HTRANSOut(LSUHTRANSOut), .HADDROut(LSUHADDROut), .HREADYIn(HREADY));
|
||||
|
||||
// output mux //*** switch to structural implementation
|
||||
assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : '0;
|
||||
assign HSIZE = LSUSelect ? LSUHSIZEOut : IFUSelect ? IFUHSIZEOut: '0;
|
||||
assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : '0; // If doing memory accesses, use LSUburst, else use Instruction burst.
|
||||
assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: '0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
|
||||
assign HWRITE = LSUSelect ? LSUHWRITEOut : IFUSelect ? 1'b0 : '0;
|
||||
assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : 0;
|
||||
assign HSIZE = LSUSelect ? LSUHSIZEOut : IFUSelect ? IFUHSIZEOut: 0;
|
||||
assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : 0; // If doing memory accesses, use LSUburst, else use Instruction burst.
|
||||
assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: 0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
|
||||
assign HWRITE = LSUSelect ? LSUHWRITEOut : 0;
|
||||
assign HPROT = 4'b0011; // not used; see Section 3.7
|
||||
assign HMASTLOCK = 0; // no locking supported
|
||||
|
||||
|
@ -37,7 +37,7 @@ module fdivsqrtfgen2 import cvw::*; #(parameter cvw_t P) (
|
||||
// Generate for both positive and negative quotient digits
|
||||
assign FP = ~(U << 1) & C;
|
||||
assign FN = (UM << 1) | (C & ~(C << 2));
|
||||
assign FZ = '0;
|
||||
assign FZ = 0;
|
||||
|
||||
always_comb // Choose which adder input will be used
|
||||
if (up) F = FP;
|
||||
|
@ -37,7 +37,7 @@ module fdivsqrtfgen4 import cvw::*; #(parameter cvw_t P) (
|
||||
// Generate for both positive and negative digits
|
||||
assign F2 = (~U << 2) & (C << 2); //
|
||||
assign F1 = ~(U << 1) & C;
|
||||
assign F0 = '0;
|
||||
assign F0 = 0;
|
||||
assign FN1 = (UM << 1) | (C & ~(C << 3));
|
||||
assign FN2 = (UM << 2) | ((C << 2) & ~(C << 4));
|
||||
|
||||
|
@ -81,7 +81,7 @@ module fdivsqrtiter import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// C register/initialization mux: C = -R:
|
||||
// C = -4 = 00.000000... (in Q2.DIVb) for radix 4, C = -2 = 10.000000... for radix2
|
||||
if(P.RADIX == 4) assign initC = '0;
|
||||
if(P.RADIX == 4) assign initC = 0;
|
||||
else assign initC = {2'b10, {{P.DIVb{1'b0}}}};
|
||||
mux2 #(P.DIVb+2) cmux(C[P.DIVCOPIES], initC, IFDivStartE, NextC);
|
||||
flopen #(P.DIVb+2) creg(clk, FDivBusyE, NextC, C[0]);
|
||||
|
@ -121,7 +121,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
|
||||
else IntDivResultM = {(P.XLEN){1'b1}};
|
||||
end else if (ALTBM) begin // Numerator is small
|
||||
if (RemOpM) IntDivResultM = AM;
|
||||
else IntDivResultM = '0;
|
||||
else IntDivResultM = 0;
|
||||
end else IntDivResultM = PreIntResultM[P.XLEN-1:0];
|
||||
|
||||
// sign extend result for W64
|
||||
|
@ -58,7 +58,7 @@ module fdivsqrtstage2 import cvw::*; #(parameter cvw_t P) (
|
||||
// Divisor multiple
|
||||
always_comb
|
||||
if (up) Dsel = DBar;
|
||||
else if (uz) Dsel = '0;
|
||||
else if (uz) Dsel = 0;
|
||||
else Dsel = D; // un
|
||||
|
||||
// Residual Update
|
||||
|
@ -68,7 +68,7 @@ module fdivsqrtstage4 import cvw::*; #(parameter cvw_t P) (
|
||||
case (udigit)
|
||||
4'b1000: Dsel = DBar2;
|
||||
4'b0100: Dsel = DBar;
|
||||
4'b0000: Dsel = '0;
|
||||
4'b0000: Dsel = 0;
|
||||
4'b0010: Dsel = D;
|
||||
4'b0001: Dsel = D2;
|
||||
default: Dsel = 'x;
|
||||
|
@ -80,7 +80,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
|
||||
endcase
|
||||
end
|
||||
assign HImmBox = {{(P.FLEN-16){1'b1}}, HImm}; // NaN-box HImm
|
||||
end else assign HImmBox = '0;
|
||||
end else assign HImmBox = 0;
|
||||
|
||||
////////////////////////////
|
||||
// single
|
||||
@ -168,7 +168,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
|
||||
endcase
|
||||
end
|
||||
assign DImmBox = {{(P.FLEN-64){1'b1}}, DImm}; // NaN-box DImm
|
||||
end else assign DImmBox = '0;
|
||||
end else assign DImmBox = 0;
|
||||
|
||||
////////////////////////////
|
||||
// double
|
||||
@ -213,7 +213,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
|
||||
endcase
|
||||
end
|
||||
assign QImmBox = QImm; // NaN-box QImm trivial because Q is longest format
|
||||
end else assign QImmBox = '0;
|
||||
end else assign QImmBox = 0;
|
||||
|
||||
mux4 #(P.FLEN) flimux(SImmBox, DImmBox, HImmBox, QImmBox, Fmt, Imm); // select immediate based on format
|
||||
|
||||
|
@ -51,9 +51,9 @@ module fmaadd import cvw::*; #(parameter cvw_t P) (
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Choose an inverted or non-inverted addend. Put carry into adder/LZA for addition
|
||||
assign AmInv = {3*P.NF+4{InvA}}^Am;
|
||||
assign AmInv = InvA ? ~Am : Am;
|
||||
// Kill the product if the product is too small to effect the addition (determined in fma1.sv)
|
||||
assign PmKilled = {2*P.NF+2{~KillProd}}&Pm;
|
||||
assign PmKilled = KillProd ? 0 : Pm;
|
||||
// Do the addition
|
||||
// - calculate a positive and negative sum in parallel
|
||||
// if there was a small negative number killed in the alignment stage one needs to be subtracted from the sum
|
||||
|
@ -37,6 +37,6 @@ module fmaexpadd import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// kill the exponent if the product is zero - either X or Y is 0
|
||||
assign PZero = XZero | YZero;
|
||||
assign Pe = PZero ? '0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)});
|
||||
assign Pe = PZero ? 0 : ({2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)});
|
||||
|
||||
endmodule
|
||||
|
@ -275,7 +275,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
||||
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, InstrD[19:15], Rs1E);
|
||||
flopenrc #(2) Fmt2EReg(clk, reset, FlushE, ~StallE, InstrD[26:25], Fmt2E);
|
||||
fli #(P) fli(.Rs1(Rs1E), .Fmt(Fmt2E), .Imm(FliResE));
|
||||
end else assign FliResE = '0;
|
||||
end else assign FliResE = 0;
|
||||
|
||||
// fmv.*.x: NaN Box SrcA to extend integer to requested FP size
|
||||
if(P.FPSIZES == 1)
|
||||
|
@ -65,7 +65,7 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// if the shift amount is negative then don't shift (keep sticky bit)
|
||||
// need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES)
|
||||
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : '0;
|
||||
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : 0;
|
||||
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
|
||||
|
||||
// pre-shift the divider result for normalization
|
||||
|
@ -60,7 +60,7 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
end else if (P.FPSIZES == 3) begin
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
P.FMT: BiasCorr = '0;
|
||||
P.FMT: BiasCorr = 0;
|
||||
P.FMT1: BiasCorr = (P.NE+2)'(P.BIAS1-P.BIAS);
|
||||
P.FMT2: BiasCorr = (P.NE+2)'(P.BIAS2-P.BIAS);
|
||||
default: BiasCorr = 'x;
|
||||
@ -70,7 +70,7 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
end else if (P.FPSIZES == 4) begin
|
||||
always_comb begin
|
||||
case (Fmt)
|
||||
2'h3: BiasCorr = '0;
|
||||
2'h3: BiasCorr = 0;
|
||||
2'h1: BiasCorr = (P.NE+2)'(P.D_BIAS-P.Q_BIAS);
|
||||
2'h0: BiasCorr = (P.NE+2)'(P.S_BIAS-P.Q_BIAS);
|
||||
2'h2: BiasCorr = (P.NE+2)'(P.H_BIAS-P.Q_BIAS);
|
||||
|
@ -303,9 +303,9 @@ module round import cvw::*; #(parameter cvw_t P) (
|
||||
case(PostProcSel)
|
||||
2'b10: Me = FmaMe; // fma
|
||||
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt
|
||||
// 2'b01: Me = DivDone ? Ue : '0; // divide
|
||||
// 2'b01: Me = DivDone ? Ue : 0; // divide
|
||||
2'b01: Me = Ue; // divide
|
||||
default: Me = '0;
|
||||
default: Me = 0;
|
||||
endcase
|
||||
|
||||
|
||||
|
@ -88,5 +88,5 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// the quotent is in the range [.5,2) if there is no early termination
|
||||
// if the quotent < 1 and not Subnormal then subtract 1 to account for the normalization shift
|
||||
assign Ue = (DivResSubnorm & DivSubnormShiftPos) ? '0 : DivUe - {(P.NE+1)'(0), ~LZAPlus1};
|
||||
assign Ue = (DivResSubnorm & DivSubnormShiftPos) ? 0 : DivUe - {(P.NE+1)'(0), ~LZAPlus1};
|
||||
endmodule
|
||||
|
@ -339,7 +339,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
if (P.ZFA_SUPPORTED & P.D_SUPPORTED) // fcvtmod.w.d support
|
||||
always_comb begin
|
||||
if (Zfa) OfIntRes2 = '0; // fcvtmod.w.d produces 0 on overflow
|
||||
if (Zfa) OfIntRes2 = 0; // fcvtmod.w.d produces 0 on overflow
|
||||
else OfIntRes2 = OfIntRes;
|
||||
if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]};
|
||||
else Int64Res = CvtNegRes[P.XLEN-1:0];
|
||||
|
@ -43,7 +43,7 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] RAM[DEPTH-1:0];
|
||||
bit [WIDTH-1:0] RAM[DEPTH-1:0];
|
||||
|
||||
// ***************************************************************************
|
||||
// TRUE SRAM macro
|
||||
|
@ -40,7 +40,7 @@ module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] RAM[DEPTH-1:0];
|
||||
bit [WIDTH-1:0] RAM[DEPTH-1:0];
|
||||
|
||||
// ***************************************************************************
|
||||
// TRUE SRAM macro
|
||||
@ -49,19 +49,19 @@ module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
|
||||
// 64 x 128-bit SRAM
|
||||
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||
.A(addr), .D(din),
|
||||
.BWEB('0), .Q(dout));
|
||||
.BWEB(0), .Q(dout));
|
||||
|
||||
end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
|
||||
// 64 x 44-bit SRAM
|
||||
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||
.A(addr), .D(din),
|
||||
.BWEB('0), .Q(dout));
|
||||
.BWEB(0), .Q(dout));
|
||||
|
||||
end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
|
||||
// 64 x 22-bit SRAM
|
||||
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||
.A(addr), .D(din),
|
||||
.BWEB('0), .Q(dout));
|
||||
.BWEB(0), .Q(dout));
|
||||
|
||||
// ***************************************************************************
|
||||
// READ first SRAM model
|
||||
|
@ -43,7 +43,7 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
|
||||
output logic [WIDTH-1:0] rd1
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] mem[DEPTH-1:0];
|
||||
bit [WIDTH-1:0] mem[DEPTH-1:0];
|
||||
localparam SRAMWIDTH = 32;
|
||||
localparam SRAMNUMSETS = SRAMWIDTH/WIDTH;
|
||||
|
||||
@ -55,11 +55,11 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
|
||||
|
||||
ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
|
||||
.CEBA(~ce1), .CEBB(~ce2),
|
||||
.WEBA('0), .WEBB(~we2),
|
||||
.WEBA(0), .WEBB(~we2),
|
||||
.AA(ra1), .AB(wa2),
|
||||
.DA('0),
|
||||
.DA(0),
|
||||
.DB(wd2),
|
||||
.BWEBA('0), .BWEBB('1),
|
||||
.BWEBA(0), .BWEBB('1),
|
||||
.QA(rd1),
|
||||
.QB());
|
||||
|
||||
@ -67,11 +67,11 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
|
||||
|
||||
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
|
||||
.CEBA(~ce1), .CEBB(~ce2),
|
||||
.WEBA('0), .WEBB(~we2),
|
||||
.WEBA(0), .WEBB(~we2),
|
||||
.AA(ra1), .AB(wa2),
|
||||
.DA('0),
|
||||
.DA(0),
|
||||
.DB(wd2),
|
||||
.BWEBA('0), .BWEBB('1),
|
||||
.BWEBA(0), .BWEBB('1),
|
||||
.QA(rd1),
|
||||
.QB());
|
||||
|
||||
@ -95,12 +95,12 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
|
||||
assign rd1 = RD1Sets[RA1Q[$clog2(SRAMWIDTH)-1:0]];
|
||||
ram2p1r1wbe_64x32 memory2(.CLKA(clk), .CLKB(clk),
|
||||
.CEBA(~ce1), .CEBB(~ce2),
|
||||
.WEBA('0), .WEBB(~we2),
|
||||
.WEBA(0), .WEBB(~we2),
|
||||
.AA(ra1[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]),
|
||||
.AB(wa2[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]),
|
||||
.DA('0),
|
||||
.DA(0),
|
||||
.DB(SRAMWriteData),
|
||||
.BWEBA('0), .BWEBB(SRAMBitMask),
|
||||
.BWEBA(0), .BWEBB(SRAMBitMask),
|
||||
.QA(SRAMReadData),
|
||||
.QB());
|
||||
|
||||
@ -110,13 +110,14 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
|
||||
// READ first SRAM model
|
||||
// ***************************************************************************
|
||||
integer i;
|
||||
|
||||
/*
|
||||
initial begin // initialize memory for simulation only; not needed because done in the testbench now
|
||||
integer j;
|
||||
for (j=0; j < DEPTH; j++)
|
||||
mem[j] = '0;
|
||||
mem[j] = 0;
|
||||
end
|
||||
|
||||
*/
|
||||
|
||||
// Read
|
||||
logic [$clog2(DEPTH)-1:0] ra1d;
|
||||
flopen #($clog2(DEPTH)) adrreg(clk, ce1, ra1, ra1d);
|
||||
|
@ -34,7 +34,7 @@ module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
|
||||
);
|
||||
|
||||
// Core Memory
|
||||
logic [DATA_WIDTH-1:0] ROM [(2**ADDR_WIDTH)-1:0];
|
||||
bit [DATA_WIDTH-1:0] ROM [(2**ADDR_WIDTH)-1:0];
|
||||
|
||||
// dh 10/30/23 ROM macros are presently commented out
|
||||
// because they don't point to a generated ROM
|
||||
@ -52,7 +52,7 @@ module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
|
||||
end
|
||||
end
|
||||
|
||||
always @ (posedge clk) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if(ce) dout <= ROM[addr];
|
||||
end
|
||||
|
||||
|
@ -31,7 +31,7 @@ module onehotdecoder #(parameter WIDTH = 2) (
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
decoded = '0;
|
||||
decoded = 0;
|
||||
decoded[bin] = 1'b1;
|
||||
end
|
||||
|
||||
|
@ -82,7 +82,7 @@ module hazard import cvw::*; #(parameter cvw_t P) (
|
||||
// The IFU and LSU stall the entire pipeline on a cache miss, bus access, or other long operation.
|
||||
// The IFU stalls the entire pipeline rather than just Fetch to avoid complications with instructions later in the pipeline causing Exceptions
|
||||
// A trap could be asserted at the start of a IFU/LSU stall, and should flush the memory operation
|
||||
assign StallFCause = '0;
|
||||
assign StallFCause = 0;
|
||||
assign StallDCause = (StructuralStallD | FPUStallD) & ~FlushDCause;
|
||||
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
|
||||
assign StallMCause = WFIStallM & ~FlushMCause;
|
||||
|
@ -57,8 +57,8 @@ module cnt #(parameter WIDTH = 32) (
|
||||
lzc #(WIDTH) lzc(.num(lzcA), .ZeroCnt(czResult[$clog2(WIDTH):0]));
|
||||
popcnt #(WIDTH) popcntw(.num(popcntA), .PopCnt(cpopResult[$clog2(WIDTH):0]));
|
||||
// zero extend these results to fit into width
|
||||
assign czResult[WIDTH-1:$clog2(WIDTH)+1] = '0;
|
||||
assign cpopResult[WIDTH-1:$clog2(WIDTH)+1] = '0;
|
||||
assign czResult[WIDTH-1:$clog2(WIDTH)+1] = 0;
|
||||
assign cpopResult[WIDTH-1:$clog2(WIDTH)+1] = 0;
|
||||
|
||||
mux2 #(WIDTH) cntresultmux(czResult, cpopResult, B[1], CntResult);
|
||||
endmodule
|
||||
|
@ -224,7 +224,7 @@ module bpred import cvw::*; #(parameter cvw_t P) (
|
||||
assign BTAWrongM = BPBTAWrongM & PCSrcM;
|
||||
|
||||
end else begin
|
||||
assign {BTAWrongM, RASPredPCWrongM} = '0;
|
||||
assign {BTAWrongM, RASPredPCWrongM} = 0;
|
||||
end
|
||||
|
||||
// **** Fix me
|
||||
|
@ -65,7 +65,7 @@ module icpred import cvw::*; #(parameter cvw_t P,
|
||||
assign CJumpF = cjal | cj | cjr | cjalr;
|
||||
assign CBranchF = CompressedOpcF[4:1] == 4'h7;
|
||||
end else begin
|
||||
assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = '0;
|
||||
assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = 0;
|
||||
end
|
||||
|
||||
assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;
|
||||
|
@ -116,7 +116,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
|
||||
SpeculativeFlushedF <= #1 FlushedBits[IndexLHRNextF];
|
||||
if (reset | FlushD) FlushedBits <= #1 '1;
|
||||
if(BranchD & ~StallE & ~FlushE) begin
|
||||
FlushedBits[IndexLHRD] <= #1 '0;
|
||||
FlushedBits[IndexLHRD] <= #1 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -194,10 +194,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
|
||||
end else begin
|
||||
assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = '0;
|
||||
assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = 0;
|
||||
assign PCPF = PCFExt[P.PA_BITS-1:0];
|
||||
assign CacheableF = '1;
|
||||
assign SelIROM = '0;
|
||||
assign CacheableF = 1;
|
||||
assign SelIROM = 0;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -234,8 +234,8 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
logic ICacheBusAck;
|
||||
logic [1:0] CacheBusRW, BusRW, CacheRWF;
|
||||
|
||||
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0;
|
||||
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : '0;
|
||||
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : 0;
|
||||
assign CacheRWF = ~ITLBMissF & CacheableF & ~SelIROM ? IFURWF : 0;
|
||||
// *** RT: PAdr and NextSet are replaced with mux between PCPF/IEUAdrM and PCSpillNextF/IEUAdrE.
|
||||
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.ICACHE_LINELENINBITS),
|
||||
.NUMLINES(P.ICACHE_WAYSIZEINBYTES*8/P.ICACHE_LINELENINBITS),
|
||||
@ -271,7 +271,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
end else begin : passthrough
|
||||
assign IFUHADDR = PCPF;
|
||||
logic [1:0] BusRW;
|
||||
assign BusRW = ~ITLBMissF & ~SelIROM ? IFURWF : '0;
|
||||
assign BusRW = ~ITLBMissF & ~SelIROM ? IFURWF : 0;
|
||||
assign IFUHSIZE = 3'b010;
|
||||
|
||||
ahbinterface #(P.XLEN, 1'b0) ahbinterface(.HCLK(clk), .Flush(FlushD), .HRESETn(~reset), .HREADY(IFUHREADY),
|
||||
@ -279,15 +279,15 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
.HWSTRB(), .BusRW, .BusAtomic('0), .ByteMask(), .WriteData('0),
|
||||
.Stall(GatedStallD), .BusStall, .BusCommitted(BusCommittedF), .FetchBuffer(FetchBuffer));
|
||||
|
||||
assign CacheCommittedF = '0;
|
||||
assign CacheCommittedF = 0;
|
||||
if(P.IROM_SUPPORTED) mux2 #(32) UnCachedDataMux2(ShiftUncachedInstr, IROMInstrF, SelIROM, InstrRawF);
|
||||
else assign InstrRawF = ShiftUncachedInstr;
|
||||
assign IFUHBURST = 3'b0;
|
||||
assign {ICacheMiss, ICacheAccess, ICacheStallF} = '0;
|
||||
assign {ICacheMiss, ICacheAccess, ICacheStallF} = 0;
|
||||
end
|
||||
end else begin : nobus // block: bus
|
||||
assign {BusStall, CacheCommittedF} = '0;
|
||||
assign {ICacheStallF, ICacheMiss, ICacheAccess} = '0;
|
||||
assign {BusStall, CacheCommittedF} = 0;
|
||||
assign {ICacheStallF, ICacheMiss, ICacheAccess} = 0;
|
||||
assign InstrRawF = IROMInstrF;
|
||||
end
|
||||
|
||||
@ -355,7 +355,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
.BTBBranchF(1'b0), .BPCallF(), .BPReturnF(), .BPJumpF(), .BPBranchF(), .IClassWrongM,
|
||||
.IClassWrongE(), .BPReturnWrongD());
|
||||
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, BPWrongM);
|
||||
assign RASPredPCWrongM = '0;
|
||||
assign RASPredPCWrongM = 0;
|
||||
assign BPDirPredWrongM = BPWrongM;
|
||||
assign BTAWrongM = BPWrongM;
|
||||
assign InstrClassM = {CallM, ReturnM, JumpM, BranchM};
|
||||
|
@ -37,6 +37,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.XLEN-1:0] IEUAdrM, // 2 byte aligned PC in Fetch stage
|
||||
input logic [P.XLEN-1:0] IEUAdrE, // The next IEUAdrM
|
||||
input logic [2:0] Funct3M, // Size of memory operation
|
||||
input logic FpLoadStoreM, // Floating point Load or Store
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [P.LLEN*2-1:0] DCacheReadDataWordM, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
||||
input logic CacheBusHPWTStall, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
||||
@ -52,7 +53,6 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
output logic [P.XLEN-1:0] IEUAdrSpillE, // The next PCF for one of the two memory addresses of the spill
|
||||
output logic [P.XLEN-1:0] IEUAdrSpillM, // IEUAdrM for one of the two memory addresses of the spill
|
||||
output logic SelSpillE, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||
output logic SelStoreDelay, //*** this is bad. really don't like moving this outside
|
||||
output logic [P.LLEN-1:0] DCacheReadDataWordSpillM, // The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||
output logic SpillStallM);
|
||||
|
||||
@ -72,6 +72,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
logic [P.XLEN-1:0] IEUAdrIncrementM;
|
||||
|
||||
localparam OFFSET_LEN = $clog2(LLENINBYTES);
|
||||
logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM;
|
||||
logic [$clog2(LLENINBYTES)+2:0] ShiftAmount;
|
||||
logic PotentialSpillM;
|
||||
@ -93,22 +94,25 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// compute misalignement
|
||||
always_comb begin
|
||||
case (Funct3M[1:0])
|
||||
2'b00: AccessByteOffsetM = '0; // byte access
|
||||
2'b01: AccessByteOffsetM = {2'b00, IEUAdrM[0]}; // half access
|
||||
2'b10: AccessByteOffsetM = {1'b0, IEUAdrM[1:0]}; // word access
|
||||
2'b11: AccessByteOffsetM = IEUAdrM[2:0]; // double access
|
||||
default: AccessByteOffsetM = IEUAdrM[2:0];
|
||||
case (Funct3M & {FpLoadStoreM, 2'b11})
|
||||
3'b000: AccessByteOffsetM = 0; // byte access
|
||||
3'b001: AccessByteOffsetM = {{OFFSET_LEN-1{1'b0}}, IEUAdrM[0]}; // half access
|
||||
3'b010: AccessByteOffsetM = {{OFFSET_LEN-2{1'b0}}, IEUAdrM[1:0]}; // word access
|
||||
3'b011: if(P.LLEN >= 64) AccessByteOffsetM = {{OFFSET_LEN-3{1'b0}}, IEUAdrM[2:0]}; // double access
|
||||
else AccessByteOffsetM = 0; // shouldn't happen
|
||||
3'b100: if(P.LLEN == 128) AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0]; // quad access
|
||||
else AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0];
|
||||
default: AccessByteOffsetM = 0; // shouldn't happen
|
||||
endcase
|
||||
case (Funct3M[1:0])
|
||||
2'b00: PotentialSpillM = '0; // byte access
|
||||
2'b00: PotentialSpillM = 0; // byte access
|
||||
2'b01: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:1] == '1; // half access
|
||||
2'b10: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:2] == '1; // word access
|
||||
2'b11: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:3] == '1; // double access
|
||||
default: PotentialSpillM = '0;
|
||||
default: PotentialSpillM = 0;
|
||||
endcase
|
||||
end
|
||||
assign MisalignedM = (|MemRWM) & (AccessByteOffsetM != '0);
|
||||
assign MisalignedM = (|MemRWM) & (AccessByteOffsetM != 0);
|
||||
|
||||
assign ValidSpillM = MisalignedM & PotentialSpillM & ~CacheBusHPWTStall; // Don't take the spill if there is a stall
|
||||
|
||||
@ -118,20 +122,17 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
always_comb begin
|
||||
case (CurrState)
|
||||
STATE_READY: if (ValidSpillM & ~MemRWM[0]) NextState = STATE_SPILL; // load spill
|
||||
else if(ValidSpillM) NextState = STATE_STORE_DELAY; // store spill
|
||||
STATE_READY: if (ValidSpillM) NextState = STATE_SPILL; // load spill
|
||||
else NextState = STATE_READY; // no spill
|
||||
STATE_SPILL: if(StallM) NextState = STATE_SPILL;
|
||||
else NextState = STATE_READY;
|
||||
STATE_STORE_DELAY: NextState = STATE_SPILL;
|
||||
default: NextState = STATE_READY;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign SelSpillM = (CurrState == STATE_SPILL | CurrState == STATE_STORE_DELAY);
|
||||
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall) | (CurrState == STATE_STORE_DELAY);
|
||||
assign SelSpillM = CurrState == STATE_SPILL;
|
||||
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall);
|
||||
assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM;
|
||||
assign SelStoreDelay = (CurrState == STATE_STORE_DELAY); // *** Can this be merged into the PreLSURWM logic?
|
||||
assign SpillStallM = SelSpillE;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -147,7 +148,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// shifter (4:1 mux for 32 bit, 8:1 mux for 64 bit)
|
||||
// 8 * is for shifting by bytes not bits
|
||||
assign ShiftAmount = SelHPTW ? '0 : {AccessByteOffsetM, 3'b0}; // AND gate
|
||||
assign ShiftAmount = SelHPTW ? 0 : {AccessByteOffsetM, 3'b0}; // AND gate
|
||||
assign ReadDataWordSpillShiftedM = ReadDataWordSpillAllM >> ShiftAmount;
|
||||
assign DCacheReadDataWordSpillM = ReadDataWordSpillShiftedM[P.LLEN-1:0];
|
||||
|
||||
|
@ -143,7 +143,6 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
logic [(P.LLEN-1)/8:0] ByteMaskExtendedM; // Selects which bytes within a word to write
|
||||
logic [1:0] MemRWSpillM;
|
||||
logic SpillStallM;
|
||||
logic SelStoreDelay;
|
||||
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
@ -164,28 +163,27 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
|
||||
if(MISALIGN_SUPPORT) begin : ziccslm_align
|
||||
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
|
||||
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M,
|
||||
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM,
|
||||
.MemRWM,
|
||||
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
|
||||
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
|
||||
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM,
|
||||
.SelStoreDelay);
|
||||
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM);
|
||||
assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
|
||||
assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
|
||||
end else begin : no_ziccslm_align
|
||||
assign IEUAdrExtM = {2'b00, IEUAdrM};
|
||||
assign IEUAdrExtE = {2'b00, IEUAdrE};
|
||||
assign SelSpillE = '0;
|
||||
assign SelSpillE = 0;
|
||||
assign DCacheReadDataWordSpillM = DCacheReadDataWordM;
|
||||
assign ByteMaskSpillM = ByteMaskM;
|
||||
assign LSUWriteDataSpillM = LSUWriteDataM;
|
||||
assign MemRWSpillM = MemRWM;
|
||||
assign {SpillStallM, SelStoreDelay} = '0;
|
||||
assign {SpillStallM} = 0;
|
||||
end
|
||||
|
||||
if(P.ZICBOZ_SUPPORTED) begin : cboz
|
||||
mux2 #(P.XLEN) writedatacbozmux(WriteDataM, '0, CMOpM[3], WriteDataZM);
|
||||
end else begin : cboz
|
||||
assign WriteDataZM = CMOpM[3] ? 0 : WriteDataM;
|
||||
end else begin : cboz
|
||||
assign WriteDataZM = WriteDataM;
|
||||
end
|
||||
|
||||
@ -218,8 +216,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
|
||||
assign LoadPageFaultM = LSULoadPageFaultM;
|
||||
assign StoreAmoPageFaultM = LSUStoreAmoPageFaultM;
|
||||
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
|
||||
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = '0;
|
||||
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = 0;
|
||||
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = 0;
|
||||
end
|
||||
|
||||
// CommittedM indicates the cache, bus, or HPTW are busy with a multiple cycle operation.
|
||||
@ -255,8 +253,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
|
||||
end else begin // No MMU, so no PMA/page faults and no address translation
|
||||
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
|
||||
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = '0;
|
||||
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = 0;
|
||||
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = 0;
|
||||
assign PAdrM = IHAdrM[P.PA_BITS-1:0];
|
||||
assign CacheableM = 1'b1;
|
||||
assign SelDTIM = P.DTIM_SUPPORTED & ~P.BUS_SUPPORTED; // if no PMA then select dtim if there is a DTIM. If there is
|
||||
@ -281,7 +279,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
||||
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
|
||||
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : 0;
|
||||
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
|
||||
// **** create config to support DTIM with floating point.
|
||||
// Add support for cboz
|
||||
@ -318,22 +316,22 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
if(P.ZICBOZ_SUPPORTED) begin
|
||||
assign BusCMOZero = CMOpM[3] & ~CacheableM;
|
||||
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : '0;
|
||||
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : 0;
|
||||
assign BusAtomic = AtomicM[1] & ~CacheableM;
|
||||
end else begin
|
||||
assign BusCMOZero = '0;
|
||||
assign CacheCMOpM = '0;
|
||||
assign BusAtomic = '0;
|
||||
assign BusCMOZero = 0;
|
||||
assign CacheCMOpM = 0;
|
||||
assign BusAtomic = 0;
|
||||
end
|
||||
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0;
|
||||
assign BusRW = (~CacheableM & ~SelDTIM )? LSURWM : 0;
|
||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0;
|
||||
assign CacheRWM = (CacheableM & ~SelDTIM) ? LSURWM : 0;
|
||||
assign FlushDCache = FlushDCacheM & ~(SelHPTW);
|
||||
|
||||
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
|
||||
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(CACHEWORDLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
|
||||
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
|
||||
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM),
|
||||
.CacheRW(CacheRWM),
|
||||
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
|
||||
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
|
||||
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW,
|
||||
@ -367,7 +365,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
|
||||
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
|
||||
logic [P.XLEN-1:0] FetchBuffer;
|
||||
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||
assign BusRW = (~IgnoreRequestTLB & ~SelDTIM) ? LSURWM : 0;
|
||||
|
||||
assign LSUHADDR = PAdrM;
|
||||
assign LSUHSIZE = LSUFunct3M;
|
||||
@ -381,14 +379,14 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
||||
if(P.DTIM_SUPPORTED) mux2 #(P.XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM[P.XLEN-1:0], SelDTIM, ReadDataWordMuxM[P.XLEN-1:0]);
|
||||
else assign ReadDataWordMuxM[P.XLEN-1:0] = FetchBuffer[P.XLEN-1:0]; // *** bus only does not support double wide floats.
|
||||
assign LSUHBURST = 3'b0;
|
||||
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
|
||||
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = 0;
|
||||
end
|
||||
end else begin: nobus // block: bus, only DTIM
|
||||
assign LSUHWDATA = '0;
|
||||
assign LSUHWDATA = 0;
|
||||
assign ReadDataWordMuxM = DTIMReadDataWordM;
|
||||
assign {BusStall, BusCommittedM} = '0;
|
||||
assign {DCacheMiss, DCacheAccess} = '0;
|
||||
assign {DCacheStallM, DCacheCommittedM} = '0;
|
||||
assign {BusStall, BusCommittedM} = 0;
|
||||
assign {DCacheMiss, DCacheAccess} = 0;
|
||||
assign {DCacheStallM, DCacheCommittedM} = 0;
|
||||
end
|
||||
|
||||
assign LSUBusStallM = BusStall & ~IgnoreRequestTLB;
|
||||
|
@ -29,39 +29,42 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module subwordread import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.LLEN-1:0] ReadDataWordMuxM,
|
||||
input logic [3:0] PAdrM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic FpLoadStoreM,
|
||||
input logic BigEndianM,
|
||||
output logic [P.LLEN-1:0] ReadDataM
|
||||
input logic [P.LLEN-1:0] ReadDataWordMuxM,
|
||||
input logic [3:0] PAdrM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic FpLoadStoreM,
|
||||
input logic BigEndianM,
|
||||
output logic [P.LLEN-1:0] ReadDataM
|
||||
);
|
||||
|
||||
localparam ADRBITS = $clog2(P.LLEN)-3;
|
||||
|
||||
logic [ADRBITS-1:0] PAdrSwapM;
|
||||
logic [7:0] ByteM;
|
||||
logic [15:0] HalfwordM;
|
||||
logic [31:0] WordM;
|
||||
logic [63:0] DblWordM;
|
||||
logic [ADRBITS-1:0] PAdrSwap;
|
||||
// Funct3M[2] is the unsigned bit. mask upper bits.
|
||||
// Funct3M[1:0] is the size of the memory access.
|
||||
if (P.BIGENDIAN_SUPPORTED) assign PAdrSwap = PAdrM[ADRBITS-1:0] ^ {ADRBITS{BigEndianM}};
|
||||
else assign PAdrSwap = PAdrM[ADRBITS-1:0];
|
||||
assign ByteM = ReadDataWordMuxM[PAdrSwap*8 +: 8];
|
||||
assign HalfwordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1:1]*16 +: 16];
|
||||
if (P.LLEN >= 64) assign WordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1:2] * 32 +: 32];
|
||||
else assign WordM = ReadDataWordMuxM;
|
||||
|
||||
if (P.LLEN >= 64) assign DblWordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1] * 64 +: 64];
|
||||
// invert lsbs of address to select appropriate subword for big endian
|
||||
if (P.BIGENDIAN_SUPPORTED) assign PAdrSwapM = PAdrM[ADRBITS-1:0] ^ {ADRBITS{BigEndianM}};
|
||||
else assign PAdrSwapM = PAdrM[ADRBITS-1:0];
|
||||
|
||||
// Use indexed part select to imply muxes to select each size of subword
|
||||
if (P.LLEN == 128) mux2 #(64) dblmux(ReadDataWordMuxM[63:0], ReadDataWordMuxM[127:64], PAdrSwapM[3], DblWordM);
|
||||
else if (P.LLEN == 64) assign DblWordM = ReadDataWordMuxM;
|
||||
if (P.LLEN >= 64) mux2 #(32) wordmux(DblWordM[31:0], DblWordM[63:32], PAdrSwapM[2], WordM);
|
||||
else assign WordM = ReadDataWordMuxM;
|
||||
mux2 #(16) halfwordmux(WordM[15:0], WordM[31:16], PAdrSwapM[1], HalfwordM);
|
||||
mux2 #(8) bytemux(HalfwordM[7:0], HalfwordM[15:8], PAdrSwapM[0], ByteM);
|
||||
|
||||
// sign extension/ NaN boxing
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: ReadDataM = {{(P.LLEN-8){ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{P.LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
|
||||
3'b010: ReadDataM = {{P.LLEN-32{WordM[31]|FpLoadStoreM}}, WordM[31:0]}; // lw/flw
|
||||
3'b011: if (P.LLEN >= 64) ReadDataM = {{P.LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
|
||||
else ReadDataM = ReadDataWordMuxM;
|
||||
3'b000: ReadDataM = {{(P.LLEN-8){ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{P.LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
|
||||
3'b010: ReadDataM = {{P.LLEN-32{WordM[31]|FpLoadStoreM}}, WordM[31:0]}; // lw/flw
|
||||
3'b011: if (P.LLEN >= 64) ReadDataM = {{P.LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
|
||||
else ReadDataM = ReadDataWordMuxM; // shouldn't happen
|
||||
3'b100: if (P.LLEN == 128) ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{P.LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq
|
||||
else ReadDataM = {{P.LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
|
||||
3'b101: ReadDataM = {{P.LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
|
@ -55,9 +55,9 @@ module subwordwrite #(parameter LLEN) (
|
||||
end else begin:sww // 32-bit
|
||||
always_comb
|
||||
case(LSUFunct3M[1:0])
|
||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
|
||||
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
|
||||
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
|
||||
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
|
||||
endcase
|
||||
end
|
||||
|
@ -42,7 +42,7 @@ module swbytemask #(parameter WORDLEN, EXTEND = 0)(
|
||||
assign ByteMaskExtended = ExtendedByteMask[WORDLEN*2/8-1:WORDLEN/8];
|
||||
end else begin
|
||||
assign ByteMask = (('d2**('d2**Size))-'d1) << Adr;
|
||||
assign ByteMaskExtended = '0;
|
||||
assign ByteMaskExtended = 0;
|
||||
end
|
||||
|
||||
/* Equivalent to the following
|
||||
|
@ -148,7 +148,6 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
||||
flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB)
|
||||
assign PRegEn = HPTWRW[1] & ~DCacheBusStallM | UpdatePTE;
|
||||
flopenr #(P.XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache
|
||||
assert property(@(posedge clk) ~PRegEn | reset | NextPTE[0] !== 1'bx); // report writing an x PTE from an uninitialized page table
|
||||
|
||||
// Assign PTE descriptors common across all XLEN values
|
||||
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
|
||||
@ -174,7 +173,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
||||
logic [P.XLEN-1:0] AccessedPTE;
|
||||
|
||||
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
||||
//assign ReadDataNoXM = (ReadDataM[0] === 'x) ? '0 : ReadDataM; // If the PTE.V bit is x because it was read from uninitialized memory set to 0 to avoid x propagation and hanging the simulation.
|
||||
//assign ReadDataNoXM = (ReadDataM[0] === 'x) ? 0 : ReadDataM; // If the PTE.V bit is x because it was read from uninitialized memory set to 0 to avoid x propagation and hanging the simulation.
|
||||
assign ReadDataNoXM = ReadDataM; // *** temporary fix for synthesis; === and x in line above are not synthesizable.
|
||||
mux2 #(P.XLEN) NextPTEMux(ReadDataNoXM, AccessedPTE, UpdatePTE, NextPTE); // NextPTE = ReadDataNoXM when ADUE = 0 because UpdatePTE = 0
|
||||
flopenr #(P.PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
|
||||
@ -214,9 +213,9 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
||||
end else begin // block: hptwwrites
|
||||
assign NextPTE = ReadDataNoXM;
|
||||
assign HPTWAdr = HPTWReadAdr;
|
||||
assign HPTWUpdateDA = '0;
|
||||
assign UpdatePTE = '0;
|
||||
assign HPTWRW[0] = '0;
|
||||
assign HPTWUpdateDA = 0;
|
||||
assign UpdatePTE = 0;
|
||||
assign HPTWRW[0] = 0;
|
||||
end
|
||||
|
||||
// Enable and select signals based on states
|
||||
|
@ -98,6 +98,6 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// Output the hit physical address if translation is currently on.
|
||||
// Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal
|
||||
mux2 #(P.PA_BITS) hitmux('0, {PPNMixed2, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
|
||||
assign TLBPAdr = TLBHit ? {PPNMixed2, Offset} : 0;
|
||||
|
||||
endmodule
|
||||
|
@ -74,11 +74,11 @@ module csri import cvw::*; #(parameter cvw_t P) (
|
||||
assign SIP_WRITE_MASK = 12'h000;
|
||||
assign MIE_WRITE_MASK = 12'h888;
|
||||
end
|
||||
always @(posedge clk)
|
||||
always_ff @(posedge clk)
|
||||
if (reset) MIP_REGW_writeable <= 12'b0;
|
||||
else if (WriteMIPM) MIP_REGW_writeable <= (CSRWriteValM[11:0] & MIP_WRITE_MASK);
|
||||
else if (WriteSIPM) MIP_REGW_writeable <= (CSRWriteValM[11:0] & SIP_WRITE_MASK) | (MIP_REGW_writeable & ~SIP_WRITE_MASK);
|
||||
always @(posedge clk)
|
||||
always_ff @(posedge clk)
|
||||
if (reset) MIE_REGW <= 12'b0;
|
||||
else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields
|
||||
else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields
|
||||
|
@ -163,7 +163,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
|
||||
if (P.U_SUPPORTED) begin: mcounteren // MCOUNTEREN only exists when user mode is supported
|
||||
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
|
||||
end else assign MCOUNTEREN_REGW = '0;
|
||||
end else assign MCOUNTEREN_REGW = 0;
|
||||
|
||||
// MENVCFG register
|
||||
if (P.U_SUPPORTED) begin // menvcfg only exists if there is a lower privilege to control
|
||||
@ -199,7 +199,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
|
||||
// verilator lint_off WIDTH
|
||||
logic [5:0] entry;
|
||||
always_comb begin
|
||||
entry = '0;
|
||||
entry = 0;
|
||||
CSRMReadValM = 0;
|
||||
IllegalCSRMAccessM = !(P.S_SUPPORTED) & (CSRAdrM == MEDELEG | CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode
|
||||
if (CSRAdrM >= PMPADDR0 & CSRAdrM < PMPADDR0 + P.PMP_ENTRIES) // reading a PMP entry
|
||||
|
@ -66,7 +66,7 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||
assign MSTATUSH_REGW = 0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||
end else begin: csrsr32 // RV32
|
||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
|
@ -80,7 +80,7 @@ module privdec import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
if (P.U_SUPPORTED) begin:wfi
|
||||
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
|
||||
assign WFICountPlus1 = wfiM ? '0 : WFICount + 1; // restart counting on WFI
|
||||
assign WFICountPlus1 = wfiM ? WFICount + 1 : '0; // restart counting on WFI
|
||||
flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
|
||||
// coverage off -item e 1 -fecexprrow 1
|
||||
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
|
||||
|
@ -65,8 +65,8 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
||||
assign PendingIntsM = MIP_REGW & MIE_REGW;
|
||||
assign IntPendingM = |PendingIntsM;
|
||||
assign Committed = CommittedM | CommittedF;
|
||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||
assign EnabledIntsM = (MIntGlobalEnM ? PendingIntsM & ~MIDELEG_REGW : 0) | (SIntGlobalEnM ? PendingIntsM & MIDELEG_REGW : 0);
|
||||
assign ValidIntsM = Committed ? 0 : EnabledIntsM;
|
||||
assign InterruptM = (|ValidIntsM) & InstrValidM & (~wfiM | wfiW); // suppress interrupt if the memory system has partially processed a request. Delay interrupt until wfi is in the W stage.
|
||||
// wfiW is to support possible but unlikely back to back wfi instructions. wfiM would be high in the M stage, while also in the W stage.
|
||||
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
||||
|
@ -63,7 +63,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// register access
|
||||
if (P.XLEN==64) begin:clint // 64-bit
|
||||
always @(posedge PCLK) begin
|
||||
always_ff @(posedge PCLK) begin
|
||||
case(entry)
|
||||
16'h0000: PRDATA <= {63'b0, MSIP};
|
||||
16'h4000: PRDATA <= MTIMECMP;
|
||||
@ -97,7 +97,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
||||
MTIME[j*8 +: 8] <= PWDATA[j*8 +: 8];
|
||||
end else MTIME <= MTIME + 1;
|
||||
end else begin:clint // 32-bit
|
||||
always @(posedge PCLK) begin
|
||||
always_ff @(posedge PCLK) begin
|
||||
case(entry)
|
||||
16'h0000: PRDATA <= {31'b0, MSIP};
|
||||
16'h4000: PRDATA <= MTIMECMP[31:0];
|
||||
|
@ -91,7 +91,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
assign memread = ~PWRITE & PSEL; // read at start of access phase. PENABLE hasn't set up before this
|
||||
assign PREADY = 1'b1; // PLIC never takes >1 cycle to respond
|
||||
assign entry = {PADDR[23:2],2'b0};
|
||||
assign One[P.PLIC_NUM_SRC-1:1] = '0; assign One[0] = 1'b1; // Vivado does not like this as a single assignment.
|
||||
assign One[P.PLIC_NUM_SRC-1:1] = 0; assign One[0] = 1'b1; // Vivado does not like this as a single assignment.
|
||||
|
||||
// account for subword read/write circuitry
|
||||
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
|
||||
@ -104,13 +104,13 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
// ==================
|
||||
localparam PLIC_NUM_SRC_MIN_32 = P.PLIC_NUM_SRC < 32 ? P.PLIC_NUM_SRC : 31;
|
||||
|
||||
always @(posedge PCLK) begin
|
||||
always_ff @(posedge PCLK) begin
|
||||
// resetting
|
||||
if (~PRESETn) begin
|
||||
intPriority <= #1 '0;
|
||||
intEn <= #1 '0;
|
||||
intThreshold <= #1 '0;
|
||||
intInProgress <= #1 '0;
|
||||
intPriority <= #1 0;
|
||||
intEn <= #1 0;
|
||||
intThreshold <= #1 0;
|
||||
intInProgress <= #1 0;
|
||||
// writing
|
||||
end else begin
|
||||
if (memwrite)
|
||||
|
@ -520,7 +520,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
||||
intrpending = 0;
|
||||
end
|
||||
end
|
||||
always @(posedge PCLK) INTR <= #1 intrpending; // prevent glitches on interrupt pin
|
||||
always_ff @(posedge PCLK) INTR <= #1 intrpending; // prevent glitches on interrupt pin
|
||||
|
||||
// Side effect of reading LSR is lowering overrun, parity, framing, break intr's
|
||||
assign setSquashRXerrIP = ~MEMRb & (A==3'b101);
|
||||
|
@ -136,7 +136,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
|
||||
ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r");
|
||||
|
||||
// read line by line to count lines
|
||||
if (ProgramAddrMapFP != '0) begin
|
||||
if (ProgramAddrMapFP != 0) begin
|
||||
while (! $feof(ProgramAddrMapFP)) begin
|
||||
status = $fscanf(ProgramAddrMapFP, "%h\n", ProgramAddrMapLine);
|
||||
ProgramAddrMapMemory[ProgramAddrMapLineCount] = ProgramAddrMapLine;
|
||||
@ -154,7 +154,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
|
||||
ProgramLabelMapLineCount = 0;
|
||||
ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r");
|
||||
|
||||
if (ProgramLabelMapFP != '0) begin
|
||||
if (ProgramLabelMapFP != 0) begin
|
||||
while (! $feof(ProgramLabelMapFP)) begin
|
||||
status = $fscanf(ProgramLabelMapFP, "%s\n", ProgramLabelMapLine);
|
||||
ProgramLabelMapMemory[ProgramLabelMapLineCount] = ProgramLabelMapLine;
|
||||
@ -174,7 +174,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
|
||||
logic OrReducedAdr, AnyUnknown;
|
||||
assign OrReducedAdr = |ProgramAddrIndex;
|
||||
assign AnyUnknown = (OrReducedAdr === 1'bx) ? 1'b1 : 1'b0;
|
||||
initial ProgramAddrIndex = '0;
|
||||
initial ProgramAddrIndex = 0;
|
||||
|
||||
always @(*) FunctionName = AnyUnknown ? "Unknown!" : ProgramLabelMapMemory[ProgramAddrIndex];
|
||||
|
||||
|
@ -63,7 +63,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
logic CSRWriteM, CSRWriteW;
|
||||
logic [11:0] CSRAdrM, CSRAdrW;
|
||||
logic wfiM;
|
||||
logic InterruptM;
|
||||
logic InterruptM, InterruptW;
|
||||
|
||||
assign clk = testbench.dut.clk;
|
||||
// assign InstrValidF = testbench.dut.core.ieu.InstrValidF; // not needed yet
|
||||
@ -231,7 +231,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
end
|
||||
|
||||
genvar index;
|
||||
assign rf[0] = '0;
|
||||
assign rf[0] = 0;
|
||||
for(index = 1; index < NUMREGS; index += 1)
|
||||
assign rf[index] = testbench.dut.core.ieu.dp.regf.rf[index];
|
||||
|
||||
@ -239,7 +239,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
assign rf_we3 = testbench.dut.core.ieu.dp.regf.we3;
|
||||
|
||||
always_comb begin
|
||||
rf_wb <= '0;
|
||||
rf_wb <= 0;
|
||||
if(rf_we3)
|
||||
rf_wb[rf_a3] <= 1'b1;
|
||||
end
|
||||
@ -251,7 +251,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
assign frf_we4 = testbench.dut.core.fpu.fpu.fregfile.we4;
|
||||
|
||||
always_comb begin
|
||||
frf_wb <= '0;
|
||||
frf_wb <= 0;
|
||||
if(frf_we4)
|
||||
frf_wb[frf_a4] <= 1'b1;
|
||||
end
|
||||
@ -266,6 +266,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
flopenrc #(P.XLEN)PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
|
||||
flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
|
||||
flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW);
|
||||
flopenrc #(1) InterruptWReg (clk, reset, 1'b0, ~StallW, InterruptM, InterruptW);
|
||||
flopenrc #(1) HaltWReg (clk, reset, 1'b0, ~StallW, HaltM, HaltW);
|
||||
|
||||
// **** remove? are these used?
|
||||
@ -287,9 +288,9 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
assign rvvi.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order
|
||||
assign rvvi.insn[0][0] = InstrRawW;
|
||||
assign rvvi.pc_rdata[0][0] = PCW;
|
||||
assign rvvi.trap[0][0] = 0;
|
||||
assign rvvi.trap[0][0] = TrapW;
|
||||
assign rvvi.halt[0][0] = HaltW;
|
||||
assign rvvi.intr[0][0] = 0;
|
||||
assign rvvi.intr[0][0] = InterruptW;
|
||||
assign rvvi.mode[0][0] = PrivilegeModeW;
|
||||
assign rvvi.ixl[0][0] = PrivilegeModeW == 2'b11 ? 2'b10 :
|
||||
PrivilegeModeW == 2'b01 ? STATUS_SXL : STATUS_UXL;
|
||||
@ -492,7 +493,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
||||
end
|
||||
|
||||
// *** implementation only cancel? so sc does not clear?
|
||||
assign rvvi.lrsc_cancel[0][0] = '0;
|
||||
assign rvvi.lrsc_cancel[0][0] = 0;
|
||||
|
||||
integer index2;
|
||||
|
||||
|
@ -40,7 +40,7 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
|
||||
always_ff @(posedge clk) begin
|
||||
OldPCW <= PCW;
|
||||
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
|
||||
else WatchDogTimerCount = '0;
|
||||
else WatchDogTimerCount = 0;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
|
@ -252,9 +252,9 @@ module testbench;
|
||||
assign SDCCmdIn = SDCCmd;
|
||||
assign SDCDatIn = SDCDat;
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
assign SDCIntr = '0;
|
||||
assign SDCIntr = 0;
|
||||
end else begin
|
||||
assign SDCIntr = '0;
|
||||
assign SDCIntr = 0;
|
||||
end
|
||||
|
||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||
|
@ -335,7 +335,7 @@ module testbench;
|
||||
if (P.UNCORE_RAM_SUPPORTED) begin
|
||||
`ifdef TB_UNCORE_RAM_SUPPORTED
|
||||
for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1)
|
||||
dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = '0;
|
||||
dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = 0;
|
||||
`endif
|
||||
end
|
||||
if(reset) begin // branch predictor must always be reset
|
||||
@ -411,7 +411,7 @@ module testbench;
|
||||
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB);
|
||||
end else begin
|
||||
assign HREADYEXT = 1;
|
||||
assign {HRESPEXT, HRDATAEXT} = '0;
|
||||
assign {HRESPEXT, HRDATAEXT} = 0;
|
||||
end
|
||||
|
||||
if(P.FPGA) begin : sdcard
|
||||
@ -424,8 +424,8 @@ module testbench;
|
||||
assign SDCCmdIn = SDCCmd;
|
||||
assign SDCDatIn = SDCDat;
|
||||
end else begin
|
||||
assign SDCCmd = '0;
|
||||
assign SDCDat = '0;
|
||||
assign SDCCmd = 0;
|
||||
assign SDCDat = 0;
|
||||
end
|
||||
|
||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||
|
@ -124,6 +124,7 @@ module testbench;
|
||||
"imperas64f": if (P.F_SUPPORTED) tests = imperas64f;
|
||||
"imperas64d": if (P.D_SUPPORTED) tests = imperas64d;
|
||||
"imperas64m": if (P.M_SUPPORTED) tests = imperas64m;
|
||||
"wally64q": if (P.Q_SUPPORTED) tests = wally64q;
|
||||
"wally64a": if (P.A_SUPPORTED) tests = wally64a;
|
||||
"imperas64c": if (P.C_SUPPORTED) tests = imperas64c;
|
||||
else tests = imperas64iNOc;
|
||||
@ -440,7 +441,7 @@ module testbench;
|
||||
always @(posedge clk)
|
||||
if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory)
|
||||
for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1)
|
||||
dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = '0;
|
||||
dut.uncore.uncore.ram.ram.memory.RAM[adrindex] = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Actual hardware
|
||||
@ -457,7 +458,7 @@ module testbench;
|
||||
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB);
|
||||
end else begin
|
||||
assign HREADYEXT = 1;
|
||||
assign {HRESPEXT, HRDATAEXT} = '0;
|
||||
assign {HRESPEXT, HRDATAEXT} = 0;
|
||||
end
|
||||
|
||||
if(P.SDC_SUPPORTED) begin : sdcard
|
||||
@ -473,9 +474,9 @@ module testbench;
|
||||
assign SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i;
|
||||
assign SDCDatIn = SDCDat;
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
assign SDCIntr = '0;
|
||||
assign SDCIntr = 0;
|
||||
end else begin
|
||||
assign SDCIntr = '0;
|
||||
assign SDCIntr = 0;
|
||||
end
|
||||
|
||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||
|
@ -869,6 +869,10 @@ string imperas32f[] = '{
|
||||
"rv32i_m/I/XORI-01"
|
||||
};
|
||||
|
||||
string wally64q[] = '{
|
||||
`WALLYTEST,
|
||||
"rv64i_m/Q/src/WALLY-q-01.S"
|
||||
};
|
||||
|
||||
string wally64a[] = '{
|
||||
`WALLYTEST,
|
||||
|
@ -2,12 +2,12 @@ hart_ids: [0]
|
||||
hart0:
|
||||
# ISA: RV64IMAFDCSUZicsr_Zicboz_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
|
||||
# ISA: RV64IMAFDCSUZicsr_Zifencei_Zca_Zcb_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
|
||||
ISA: RV64IMAFDCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
|
||||
ISA: RV64IMAFDQCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
|
||||
physical_addr_sz: 56
|
||||
User_Spec_Version: '2.3'
|
||||
supported_xlen: [64]
|
||||
misa:
|
||||
reset-val: 0x800000000014112D
|
||||
reset-val: 0x800000000015112D
|
||||
rv32:
|
||||
accessible: false
|
||||
rv64:
|
||||
|
@ -0,0 +1,36 @@
|
||||
00000000 # fsq of 1
|
||||
00000000
|
||||
00000000
|
||||
3fff0000
|
||||
dead4000 # fsh of 1
|
||||
deadbeef
|
||||
deadbeef
|
||||
deadbeef
|
||||
00000000 # fsq of 3
|
||||
00000000
|
||||
00000000
|
||||
40008000
|
||||
00000000 # fsq of -1
|
||||
00000000
|
||||
00000000
|
||||
bfff0000
|
||||
00000000 # fsq of 6
|
||||
00000000
|
||||
00000000
|
||||
40018000
|
||||
00000000 # fsq of -4
|
||||
00000000
|
||||
00000000
|
||||
C0010000
|
||||
00000000 # fsq of -2
|
||||
00000000
|
||||
00000000
|
||||
C0000000
|
||||
00000000 # fsq of 4
|
||||
00000000
|
||||
00000000
|
||||
40010000
|
||||
00000000 # fsq of 2
|
||||
00000000
|
||||
00000000
|
||||
40000000
|
@ -0,0 +1,154 @@
|
||||
///////////////////////////////////////////
|
||||
// ../wally-riscv-arch-test/riscv-test-suite/rv64i_m/I/src/WALLY-ADD.S
|
||||
// David_Harris@hmc.edu & Rose Thompson
|
||||
// Created 07 March 2024
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
||||
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work distributed under the
|
||||
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// either express or implied. See the License for the specific language governing permissions
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV64IFDQZfh_Zicsr")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
#ifdef TEST_CASE_1
|
||||
|
||||
RVTEST_CASE(0,"//check ISA:=regex(.*Q.*);def TEST_CASE_1=True;def NO_SAIL=True",flq-align)
|
||||
|
||||
RVTEST_FP_ENABLE()
|
||||
RVTEST_VALBASEUPD(x3,test_dataset_0)
|
||||
RVTEST_SIGBASE(x1,signature_x1_1)
|
||||
|
||||
#endif
|
||||
|
||||
# turn on the floating point unit
|
||||
li x7, 1
|
||||
slli x7, x7, 13
|
||||
csrw mstatus, x7
|
||||
|
||||
li x4, 1 # 3fff 0000 0000 0000 0000 0000 0000 0000
|
||||
li x2, 2 # 4000 0000 0000 0000 0000 0000 0000 0000
|
||||
fcvt.q.w f2, x2
|
||||
fcvt.q.w f4, x4
|
||||
|
||||
fcvt.h.w f5, x2 # 4000
|
||||
|
||||
# test quad load/store
|
||||
fsq f4, 0(x3)
|
||||
flq f7, 0(x3)
|
||||
fsq f7, 0(x1)
|
||||
|
||||
# test half load/store
|
||||
fsh f5, 16(x3)
|
||||
flh f6, 16(x3)
|
||||
fsh f6, 16(x1)
|
||||
|
||||
# 1 + 2 = 3 # 4000 8000 0000 0000 0000 0000 0000 0000
|
||||
fadd.q f8, f2, f4
|
||||
fsq f8, 32(x1)
|
||||
|
||||
# 1 - 2 = -1
|
||||
fsub.q f9, f4, f2 # bfff 0000000000000000000000000000
|
||||
fsq f9, 48(x1)
|
||||
|
||||
# 2 * 3 = 6
|
||||
fmul.q f10, f2, f8 # 4001 8000000000000000000000000000
|
||||
fsq f10, 64(x1)
|
||||
|
||||
# 6 * (-1) + 2 = -4
|
||||
fmadd.q f11, f10, f9, f2 # C001 0000000000000000000000000000
|
||||
fsq f11, 80(x1)
|
||||
|
||||
# -4 / 2 = -2
|
||||
fdiv.q f12, f11, f2 # C000 0000000000000000000000000000
|
||||
fsq f12, 96(x1)
|
||||
|
||||
# sign injection (-4, 1) = 4
|
||||
fsgnj.q f13, f11, f4 # 4001 0000000000000000000000000000
|
||||
fsq f13, 112(x1)
|
||||
|
||||
# sqrt(4) = 2
|
||||
fsqrt.q f14, f13 # 4000 0000000000000000000000000000
|
||||
fsq f14, 128(x1)
|
||||
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
test_dataset_0:
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
.word 0xbabecafe
|
||||
.word 0xabecafeb
|
||||
.word 0xbecafeba
|
||||
.word 0xecafebab
|
||||
test_dataset_1:
|
||||
RVTEST_DATA_END
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
rvtest_sig_begin:
|
||||
|
||||
|
||||
|
||||
|
||||
signature_x1_1:
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
.int 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef
|
||||
rvtest_sig_end:
|
||||
RVMODEL_DATA_END
|
Loading…
Reference in New Issue
Block a user