Merge branch 'openhwgroup:main' into main

This commit is contained in:
Thomas Kidd 2024-03-09 19:19:24 -06:00 committed by GitHub
commit d3b1ce4c23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
70 changed files with 519 additions and 322 deletions

1
.gitignore vendored
View File

@ -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/main.config.old
tests/linux-testgen/buildroot-config-src/linux.config.old tests/linux-testgen/buildroot-config-src/linux.config.old
tests/linux-testgen/buildroot-config-src/busybox.config.old tests/linux-testgen/buildroot-config-src/busybox.config.old
linux/buildroot
linux/testvector-generation/boottrace.S linux/testvector-generation/boottrace.S
linux/testvector-generation/boottrace_disasm.log linux/testvector-generation/boottrace_disasm.log
sim/slack-notifier/slack-webhook-url.txt sim/slack-notifier/slack-webhook-url.txt

View File

@ -21,7 +21,7 @@ ROOT := ..
LIBRARY_DIRS := LIBRARY_DIRS :=
LIBRARY_FILES := LIBRARY_FILES :=
MARCH :=-march=rv64imfdc MARCH :=-march=rv64imfdc_zifencei
MABI :=-mabi=lp64d MABI :=-mabi=lp64d
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
LINKER :=linker.x LINKER :=linker.x

View File

@ -94,5 +94,5 @@ end_of_bios:
.globl _dtb .globl _dtb
.align 4, 0 .align 4, 0
_dtb: _dtb:
.incbin "wally-vcu118.dtb" #.incbin "wally-vcu118.dtb"

View File

@ -1,7 +1,7 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// SDC.sv // SDC.sv
// //
// Written: Ross Thompson September 25, 2021 // Written: Rose Thompson September 25, 2021
// Modified: // Modified:
// //
// Purpose: driver for sdc reader. // Purpose: driver for sdc reader.

View File

@ -222,63 +222,63 @@ if (nightly):
### branch predictor simulation ### branch predictor simulation
["bpred_TWOBIT_6_16_10_0_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_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_10_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_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_14_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_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_6_16_10_1_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_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_10_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_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_14_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_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_6_16_10_1_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_8_16_10_1_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_10_1_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_12_16_10_1_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_14_16_10_1_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_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], # ["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# btb # # btb
["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], # ["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_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_8_0_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_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_12_0_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"], # ["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ras # # ras
["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], # ["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_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_3_10_0_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_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_4_10_0_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_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_6_10_0_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_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_10_10_0_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"], # ["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# enable floating-point tests when lint is fixed # enable floating-point tests when lint is fixed
["f_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma"]], ["f_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma"]],
["fh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32zfh", "arch32zfh_divsqrt"]], ["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"]], ["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"]], ["fdqh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
["f_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma"]], ["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 ["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"]], ["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"]], ["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"]], ["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "wally64q"]],
] ]

18
src/cache/cache.sv vendored
View File

@ -82,7 +82,7 @@ module cache import cvw::*; #(parameter cvw_t P,
logic ClearDirty, SetDirty, SetValid, ClearValid; logic ClearDirty, SetDirty, SetValid, ClearValid;
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0]; logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
logic [NUMWAYS-1:0] HitWay, ValidWay; logic [NUMWAYS-1:0] HitWay, ValidWay;
logic CacheHit; logic Hit;
logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay; logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay;
logic LineDirty, HitLineDirty; logic LineDirty, HitLineDirty;
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0]; 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 [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
logic SelFetchBuffer; logic SelFetchBuffer;
logic CacheEn; logic CacheEn;
logic SelWay; logic SelVictim;
logic [LINELEN/8-1:0] LineByteMask; logic [LINELEN/8-1:0] LineByteMask;
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr; logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
genvar index; 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 // 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]( 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, .SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache); .FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
@ -132,7 +132,7 @@ module cache import cvw::*; #(parameter cvw_t P,
end else end else
assign VictimWay = 1'b1; // one hot. assign VictimWay = 1'b1; // one hot.
assign CacheHit = |HitWay; assign Hit = |HitWay;
assign LineDirty = |DirtyWay; assign LineDirty = |DirtyWay;
assign HitLineDirty = |HitDirtyWay; assign HitLineDirty = |HitDirtyWay;
@ -176,18 +176,18 @@ module cache import cvw::*; #(parameter cvw_t P,
logic [LINELEN/8-1:0] BlankByteMask; logic [LINELEN/8-1:0] BlankByteMask;
assign BlankByteMask[WORDLEN/8-1:0] = ByteMask; 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 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 // Merge write data into fetched cache line for store miss
for(index = 0; index < LINELEN/8; index++) begin for(index = 0; index < LINELEN/8; index++) begin
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]), mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index])); .d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index]));
end end
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0; assign LineByteMask = SetDirty ? DemuxedByteMask : '1;
end end
else else
begin:WriteSelLogic begin:WriteSelLogic
@ -226,8 +226,8 @@ module cache import cvw::*; #(parameter cvw_t P,
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck, cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
.FlushStage, .CacheRW, .Stall, .FlushStage, .CacheRW, .Stall,
.CacheHit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted, .Hit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelWay, .CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelVictim,
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback, .ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst, .FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer, .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,

55
src/cache/cacheLRU.sv vendored
View File

@ -1,7 +1,7 @@
/////////////////////////////////////////// ///////////////////////////////////////////
// cacheLRU.sv // cacheLRU.sv
// //
// Written: Ross Thompson ross1728@gmail.com // Written: Rose Thompson ross1728@gmail.com
// Created: 20 July 2021 // Created: 20 July 2021
// Modified: 20 January 2023 // 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 CacheEn, // Enable the cache memory arrays. Disable hold read data constant
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
input logic [SETLEN-1:0] CacheSetData, // 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] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] PAdr, // Physical address input logic [SETLEN-1:0] PAdr, // Physical address
input logic LRUWriteEn, // Update the LRU state input logic LRUWriteEn, // Update the LRU state
input logic SetValid, // Set the dirty bit in the selected way and set input logic SetValid, // Set the dirty bit in the selected way and set
@ -51,23 +51,27 @@ module cacheLRU
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0]; logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
logic [NUMWAYS-2:0] CurrLRU; logic [NUMWAYS-2:0] CurrLRU;
logic [NUMWAYS-2:0] NextLRU; logic [NUMWAYS-2:0] NextLRU;
logic [NUMWAYS-1:0] Way; logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
logic [LOGNUMWAYS-1:0] WayEncoded;
logic [NUMWAYS-2:0] WayExpanded; logic [NUMWAYS-2:0] WayExpanded;
logic AllValid; logic AllValid;
genvar row; genvar row;
/* verilator lint_off UNOPTFLAT */ /* 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 [NUMWAYS-2:0] LRUUpdate;
logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0]; logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0];
/* verilator lint_on UNOPTFLAT */ /* 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; assign AllValid = &ValidWay;
///// Update replacement bits. ///// Update replacement bits.
// coverage off // coverage off
// Excluded from coverage b/c it is untestable without varying NUMWAYS. // Excluded from coverage b/c it is untestable without varying NUMWAYS.
function integer log2 (integer value); function integer log2 (integer value);
@ -80,8 +84,7 @@ module cacheLRU
// coverage on // coverage on
// On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay. // On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay.
mux2 #(NUMWAYS) WayMux(HitWay, VictimWay, SetValid, Way); mux2 #(LOGNUMWAYS) WayMuxEnc(HitWayEncoded, VictimWayEnc, SetValid, Way);
binencoder #(NUMWAYS) encoder(Way, WayEncoded);
// bit duplication // bit duplication
// expand HitWay as HitWay[3], {{2}{HitWay[2]}}, {{4}{HitWay[1]}, {{8{HitWay[0]}}, ... // 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 integer DuplicationFactor = 2**(LOGNUMWAYS-row-1);
localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1; localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1;
localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2; localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2;
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{WayEncoded[row]}}; assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{Way[row]}};
end end
genvar node; genvar node;
@ -102,14 +105,14 @@ module cacheLRU
localparam r = LOGNUMWAYS - ctr_depth; localparam r = LOGNUMWAYS - ctr_depth;
// the child node will be updated if its parent was updated and // 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. // The if statement is only there for coverage since LRUUpdate[root] is always 1.
if (node == NUMWAYS-2) begin if (node == NUMWAYS-2) begin
assign LRUUpdate[lchild] = ~WayEncoded[r]; assign LRUUpdate[lchild] = ~Way[r];
assign LRUUpdate[rchild] = WayEncoded[r]; assign LRUUpdate[rchild] = Way[r];
end else begin end else begin
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r]; assign LRUUpdate[lchild] = LRUUpdate[node] & ~Way[r];
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r]; assign LRUUpdate[rchild] = LRUUpdate[node] & Way[r];
end end
end end
@ -129,28 +132,26 @@ module cacheLRU
assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0]; assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0];
end end
logic [NUMWAYS-1:0] FirstZero;
logic [LOGNUMWAYS-1:0] FirstZeroWay;
logic [LOGNUMWAYS-1:0] VictimWayEnc;
priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero); priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero);
binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay); binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay);
mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc); mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc);
//decoder #(LOGNUMWAYS) decoder (Intermediate[NUMWAYS-2], VictimWay);
decoder #(LOGNUMWAYS) decoder (VictimWayEnc, 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. // 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. // This is a two port memory.
// Every cycle must read from CacheSetData and each load/store must write the new LRU. // 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 always_ff @(posedge clk) begin
if (reset | (InvalidateCache & ~FlushStage)) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0; if (reset | (InvalidateCache & ~FlushStage))
if(CacheEn) begin for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = 0; // exclusion-tag: initialize
if(LRUWriteEn) else if(CacheEn) begin
LRUMemory[PAdr] <= NextLRU; // 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)) if(LRUWriteEn & (PAdr == CacheSetTag)) CurrLRU = #1 NextLRU;
CurrLRU <= NextLRU; else CurrLRU = #1 LRUMemory[CacheSetTag];
else if(LRUWriteEn) LRUMemory[PAdr] = NextLRU;
CurrLRU <= LRUMemory[CacheSetTag];
end end
end end

76
src/cache/cachefsm.sv vendored
View File

@ -50,7 +50,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
output logic CacheAccess, // Cache access output logic CacheAccess, // Cache access
// cache internals // 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 LineDirty, // The selected line and way is dirty
input logic HitLineDirty, // The cache hit way is dirty input logic HitLineDirty, // The cache hit way is dirty
input logic FlushAdrFlag, // On last set of a cache flush 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 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 SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
output logic LRUWriteEn, // Update the LRU state 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 FlushAdrCntEn, // Enable the counter for Flush Adr
output logic FlushWayCntEn, // Enable the way counter during a flush output logic FlushWayCntEn, // Enable the way counter during a flush
output logic FlushCntRst, // Reset both flush counters output logic FlushCntRst, // Reset both flush counters
@ -79,12 +79,12 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
logic CMOZeroNoEviction; logic CMOZeroNoEviction;
logic StallConditions; logic StallConditions;
typedef enum logic [3:0]{STATE_READY, // hit states typedef enum logic [3:0]{STATE_ACCESS, // hit states
// miss states // miss states
STATE_FETCH, STATE_FETCH,
STATE_WRITEBACK, STATE_WRITEBACK,
STATE_WRITE_LINE, 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 // flush cache
STATE_FLUSH, STATE_FLUSH,
STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK
@ -92,60 +92,60 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
statetype CurrState, NextState; statetype CurrState, NextState;
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
assign AnyUpdateHit = (CacheRW[0]) & CacheHit; // exclusion-tag: icache storeAMO1 assign AnyUpdateHit = (CacheRW[0]) & Hit; // exclusion-tag: icache storeAMO1
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit 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 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; assign FlushFlag = FlushAdrFlag & FlushWayFlag;
// outputs for the performance counters. // outputs for the performance counters.
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_READY & ~Stall & ~FlushStage) | (CurrState == STATE_READ_HOLD & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW assign CacheAccess = (|CacheRW) & ((CurrState == STATE_ACCESS & ~Stall & ~FlushStage) | (CurrState == STATE_ADDRESS_SETUP & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
assign CacheMiss = CacheAccess & ~CacheHit; 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. // PCNextF will no longer be pointing to the correct address.
// But PCF will be the reset vector. // But PCF will be the reset vector.
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay)); flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
always_ff @(posedge clk) always_ff @(posedge clk)
if (reset | FlushStage) CurrState <= #1 STATE_READY; if (reset | FlushStage) CurrState <= #1 STATE_ACCESS;
else CurrState <= #1 NextState; else CurrState <= #1 NextState;
always_comb begin always_comb begin
NextState = STATE_READY; NextState = STATE_ACCESS;
case (CurrState) // exclusion-tag: icache state-case 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(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 & (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 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; STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else NextState = STATE_FETCH; else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD; STATE_WRITE_LINE: NextState = STATE_ADDRESS_SETUP;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; STATE_ADDRESS_SETUP: if(Stall) NextState = STATE_ADDRESS_SETUP;
else NextState = STATE_READY; else NextState = STATE_ACCESS;
// exclusion-tag-start: icache case // exclusion-tag-start: icache case
STATE_WRITEBACK: if(CacheBusAck & ~(|CMOpM[3:1])) NextState = STATE_FETCH; 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; 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. // 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; 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; else NextState = STATE_FLUSH;
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) 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; else NextState = STATE_FLUSH_WRITEBACK;
// exclusion-tag-end: icache case // exclusion-tag-end: icache case
default: NextState = STATE_READY; default: NextState = STATE_ACCESS;
endcase endcase
end end
// com back to CPU // 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 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_FETCH) |
(CurrState == STATE_WRITEBACK) | (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. (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); (CurrState == STATE_FLUSH_WRITEBACK);
// write enables internal to cache // write enables internal to cache
assign SetValid = CurrState == STATE_WRITE_LINE | assign SetValid = CurrState == STATE_WRITE_LINE |
(CurrState == STATE_READY & CMOZeroNoEviction) | (CurrState == STATE_ACCESS & CMOZeroNoEviction) |
(CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]); (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); (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_WRITE_LINE)) & ~FlushStage) |
(CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck); (CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck);
// exclusion-tag-start: icache flushdirtycontrols // 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_WRITE_LINE & (CacheRW[0])) |
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck)); (CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty 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. (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 // Flush and eviction controls
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck; CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) | assign SelVictim = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~CacheHit))) | (CurrState == STATE_ACCESS & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~Hit))) |
(CurrState == STATE_WRITE_LINE); (CurrState == STATE_WRITE_LINE);
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) | 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 // coverage off -item e 1 -fecexprrow 1
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck) // (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & 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); (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
// exclusion-tag-end: icache flushdirtycontrols // exclusion-tag-end: icache flushdirtycontrols
// Bus interface controls // 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_FETCH & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM)); (CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM));
logic LoadMiss; 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_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) | (CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & ~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_FETCH) |
(CurrState == STATE_WRITEBACK) | (CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) | (CurrState == STATE_WRITE_LINE) |
resetDelay; 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_FETCH) |
(CurrState == STATE_WRITEBACK) | (CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) | (CurrState == STATE_WRITE_LINE) |
resetDelay; resetDelay;
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD; assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_ADDRESS_SETUP;
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_ACCESS) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
endmodule // cachefsm endmodule // cachefsm

39
src/cache/cacheway.sv vendored
View File

@ -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 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 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 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 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 FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
input logic VictimWay, // LRU selected this way as victim to evict 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 [LINELEN-1:0] ReadDataLine;
logic [TAGLEN-1:0] ReadTag; logic [TAGLEN-1:0] ReadTag;
logic Dirty; logic Dirty;
logic SelDirty; logic SelecteDirty;
logic SelectedWriteWordEn; logic SelectedWriteWordEn;
logic [LINELEN/8-1:0] FinalByteMask; logic [LINELEN/8-1:0] FinalByteMask;
logic SetValidEN, ClearValidEN; logic SetValidEN, ClearValidEN;
@ -77,33 +77,30 @@ module cacheway import cvw::*; #(parameter cvw_t P,
logic SetDirtyWay; logic SetDirtyWay;
logic ClearDirtyWay; logic ClearDirtyWay;
logic SelNonHit; logic SelNonHit;
logic SelData; logic SelectedWay;
logic InvalidateCacheDelay; logic InvalidateCacheDelay;
if (!READ_ONLY_CACHE) begin:flushlogic if (!READ_ONLY_CACHE) begin:flushlogic
logic FlushWayEn; mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelecteDirty);
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelDirty); 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. // FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
// coverage off -item e 1 -fecexprrow 3 // 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. // 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. end else begin:flushlogic // no flush operation for read-only caches.
assign SelDirty = VictimWay; assign SelecteDirty = VictimWay;
assign SelNonHit = SelWay; mux2 #(1) selectedwaymux(HitWay, SelecteDirty, SelVictim , SelectedWay);
end end
mux2 #(1) selectedwaymux(HitWay, SelDirty, SelNonHit , SelData);
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Write Enable demux // Write Enable demux
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
assign SetValidWay = SetValid & SelData; assign SetValidWay = SetValid & SelectedWay;
assign ClearValidWay = ClearValid & SelData; // exclusion-tag: icache ClearValidWay assign ClearValidWay = ClearValid & SelectedWay; // exclusion-tag: icache ClearValidWay
assign SetDirtyWay = SetDirty & SelData; // exclusion-tag: icache SetDirtyWay assign SetDirtyWay = SetDirty & SelectedWay; // exclusion-tag: icache SetDirtyWay
assign ClearDirtyWay = ClearDirty & SelData; assign ClearDirtyWay = ClearDirty & SelectedWay;
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN 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)); .din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
// AND portion of distributed tag multiplexer // 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 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 assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; // exclusion-tag: dcache HitWay
flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay); flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay);
@ -152,19 +149,19 @@ module cacheway import cvw::*; #(parameter cvw_t P,
end end
// AND portion of distributed read multiplexers // 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 // Valid Bits
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
always_ff @(posedge clk) begin // Valid bit array, always_ff @(posedge clk) begin // Valid bit array,
if (reset) ValidBits <= #1 '0; if (reset) ValidBits <= #1 0;
if(CacheEn) begin if(CacheEn) begin
ValidWay <= #1 ValidBits[CacheSetTag]; 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 (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
end end

View File

@ -62,8 +62,8 @@ module ahbinterface #(
flop #(XLEN) wdreg(HCLK, WriteData, HWDATA); flop #(XLEN) wdreg(HCLK, WriteData, HWDATA);
flop #(XLEN/8) HWSTRBReg(HCLK, ByteMask, HWSTRB); flop #(XLEN/8) HWSTRBReg(HCLK, ByteMask, HWSTRB);
end else begin end else begin
assign HWDATA = '0; assign HWDATA = 0;
assign HWSTRB = '0; assign HWSTRB = 0;
end end
busfsm #(~LSU) busfsm(.HCLK, .HRESETn, .Flush, .BusRW, .BusAtomic, busfsm #(~LSU) busfsm(.HCLK, .HRESETn, .Flush, .BusRW, .BusAtomic,

View File

@ -111,11 +111,11 @@ module ebu import cvw::*; #(parameter cvw_t P) (
.HTRANSOut(LSUHTRANSOut), .HADDROut(LSUHADDROut), .HREADYIn(HREADY)); .HTRANSOut(LSUHTRANSOut), .HADDROut(LSUHADDROut), .HREADYIn(HREADY));
// output mux //*** switch to structural implementation // output mux //*** switch to structural implementation
assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : '0; assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : 0;
assign HSIZE = LSUSelect ? LSUHSIZEOut : IFUSelect ? IFUHSIZEOut: '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 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 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 HWRITE = LSUSelect ? LSUHWRITEOut : 0;
assign HPROT = 4'b0011; // not used; see Section 3.7 assign HPROT = 4'b0011; // not used; see Section 3.7
assign HMASTLOCK = 0; // no locking supported assign HMASTLOCK = 0; // no locking supported

View File

@ -37,7 +37,7 @@ module fdivsqrtfgen2 import cvw::*; #(parameter cvw_t P) (
// Generate for both positive and negative quotient digits // Generate for both positive and negative quotient digits
assign FP = ~(U << 1) & C; assign FP = ~(U << 1) & C;
assign FN = (UM << 1) | (C & ~(C << 2)); assign FN = (UM << 1) | (C & ~(C << 2));
assign FZ = '0; assign FZ = 0;
always_comb // Choose which adder input will be used always_comb // Choose which adder input will be used
if (up) F = FP; if (up) F = FP;

View File

@ -37,7 +37,7 @@ module fdivsqrtfgen4 import cvw::*; #(parameter cvw_t P) (
// Generate for both positive and negative digits // Generate for both positive and negative digits
assign F2 = (~U << 2) & (C << 2); // assign F2 = (~U << 2) & (C << 2); //
assign F1 = ~(U << 1) & C; assign F1 = ~(U << 1) & C;
assign F0 = '0; assign F0 = 0;
assign FN1 = (UM << 1) | (C & ~(C << 3)); assign FN1 = (UM << 1) | (C & ~(C << 3));
assign FN2 = (UM << 2) | ((C << 2) & ~(C << 4)); assign FN2 = (UM << 2) | ((C << 2) & ~(C << 4));

View File

@ -81,7 +81,7 @@ module fdivsqrtiter import cvw::*; #(parameter cvw_t P) (
// C register/initialization mux: C = -R: // C register/initialization mux: C = -R:
// C = -4 = 00.000000... (in Q2.DIVb) for radix 4, C = -2 = 10.000000... for radix2 // 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}}}}; else assign initC = {2'b10, {{P.DIVb{1'b0}}}};
mux2 #(P.DIVb+2) cmux(C[P.DIVCOPIES], initC, IFDivStartE, NextC); mux2 #(P.DIVb+2) cmux(C[P.DIVCOPIES], initC, IFDivStartE, NextC);
flopen #(P.DIVb+2) creg(clk, FDivBusyE, NextC, C[0]); flopen #(P.DIVb+2) creg(clk, FDivBusyE, NextC, C[0]);

View File

@ -121,7 +121,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
else IntDivResultM = {(P.XLEN){1'b1}}; else IntDivResultM = {(P.XLEN){1'b1}};
end else if (ALTBM) begin // Numerator is small end else if (ALTBM) begin // Numerator is small
if (RemOpM) IntDivResultM = AM; if (RemOpM) IntDivResultM = AM;
else IntDivResultM = '0; else IntDivResultM = 0;
end else IntDivResultM = PreIntResultM[P.XLEN-1:0]; end else IntDivResultM = PreIntResultM[P.XLEN-1:0];
// sign extend result for W64 // sign extend result for W64

View File

@ -58,7 +58,7 @@ module fdivsqrtstage2 import cvw::*; #(parameter cvw_t P) (
// Divisor multiple // Divisor multiple
always_comb always_comb
if (up) Dsel = DBar; if (up) Dsel = DBar;
else if (uz) Dsel = '0; else if (uz) Dsel = 0;
else Dsel = D; // un else Dsel = D; // un
// Residual Update // Residual Update

View File

@ -68,7 +68,7 @@ module fdivsqrtstage4 import cvw::*; #(parameter cvw_t P) (
case (udigit) case (udigit)
4'b1000: Dsel = DBar2; 4'b1000: Dsel = DBar2;
4'b0100: Dsel = DBar; 4'b0100: Dsel = DBar;
4'b0000: Dsel = '0; 4'b0000: Dsel = 0;
4'b0010: Dsel = D; 4'b0010: Dsel = D;
4'b0001: Dsel = D2; 4'b0001: Dsel = D2;
default: Dsel = 'x; default: Dsel = 'x;

View File

@ -80,7 +80,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
endcase endcase
end end
assign HImmBox = {{(P.FLEN-16){1'b1}}, HImm}; // NaN-box HImm assign HImmBox = {{(P.FLEN-16){1'b1}}, HImm}; // NaN-box HImm
end else assign HImmBox = '0; end else assign HImmBox = 0;
//////////////////////////// ////////////////////////////
// single // single
@ -168,7 +168,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
endcase endcase
end end
assign DImmBox = {{(P.FLEN-64){1'b1}}, DImm}; // NaN-box DImm assign DImmBox = {{(P.FLEN-64){1'b1}}, DImm}; // NaN-box DImm
end else assign DImmBox = '0; end else assign DImmBox = 0;
//////////////////////////// ////////////////////////////
// double // double
@ -213,7 +213,7 @@ module fli import cvw::*; #(parameter cvw_t P) (
endcase endcase
end end
assign QImmBox = QImm; // NaN-box QImm trivial because Q is longest format 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 mux4 #(P.FLEN) flimux(SImmBox, DImmBox, HImmBox, QImmBox, Fmt, Imm); // select immediate based on format

View File

@ -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 // 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) // 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 // Do the addition
// - calculate a positive and negative sum in parallel // - 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 // if there was a small negative number killed in the alignment stage one needs to be subtracted from the sum

View File

@ -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 // kill the exponent if the product is zero - either X or Y is 0
assign PZero = XZero | YZero; 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 endmodule

View File

@ -275,7 +275,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, InstrD[19:15], Rs1E); flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, InstrD[19:15], Rs1E);
flopenrc #(2) Fmt2EReg(clk, reset, FlushE, ~StallE, InstrD[26:25], Fmt2E); flopenrc #(2) Fmt2EReg(clk, reset, FlushE, ~StallE, InstrD[26:25], Fmt2E);
fli #(P) fli(.Rs1(Rs1E), .Fmt(Fmt2E), .Imm(FliResE)); 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 // fmv.*.x: NaN Box SrcA to extend integer to requested FP size
if(P.FPSIZES == 1) if(P.FPSIZES == 1)

View File

@ -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) // 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) // 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; assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
// pre-shift the divider result for normalization // pre-shift the divider result for normalization

View File

@ -60,7 +60,7 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 3) begin end else if (P.FPSIZES == 3) begin
always_comb begin always_comb begin
case (Fmt) case (Fmt)
P.FMT: BiasCorr = '0; P.FMT: BiasCorr = 0;
P.FMT1: BiasCorr = (P.NE+2)'(P.BIAS1-P.BIAS); P.FMT1: BiasCorr = (P.NE+2)'(P.BIAS1-P.BIAS);
P.FMT2: BiasCorr = (P.NE+2)'(P.BIAS2-P.BIAS); P.FMT2: BiasCorr = (P.NE+2)'(P.BIAS2-P.BIAS);
default: BiasCorr = 'x; default: BiasCorr = 'x;
@ -70,7 +70,7 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
end else if (P.FPSIZES == 4) begin end else if (P.FPSIZES == 4) begin
always_comb begin always_comb begin
case (Fmt) case (Fmt)
2'h3: BiasCorr = '0; 2'h3: BiasCorr = 0;
2'h1: BiasCorr = (P.NE+2)'(P.D_BIAS-P.Q_BIAS); 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'h0: BiasCorr = (P.NE+2)'(P.S_BIAS-P.Q_BIAS);
2'h2: BiasCorr = (P.NE+2)'(P.H_BIAS-P.Q_BIAS); 2'h2: BiasCorr = (P.NE+2)'(P.H_BIAS-P.Q_BIAS);

View File

@ -303,9 +303,9 @@ module round import cvw::*; #(parameter cvw_t P) (
case(PostProcSel) case(PostProcSel)
2'b10: Me = FmaMe; // fma 2'b10: Me = FmaMe; // fma
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt 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 2'b01: Me = Ue; // divide
default: Me = '0; default: Me = 0;
endcase endcase

View File

@ -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 // 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 // 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 endmodule

View File

@ -339,7 +339,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
if (P.ZFA_SUPPORTED & P.D_SUPPORTED) // fcvtmod.w.d support if (P.ZFA_SUPPORTED & P.D_SUPPORTED) // fcvtmod.w.d support
always_comb begin 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; else OfIntRes2 = OfIntRes;
if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]}; if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]};
else Int64Res = CvtNegRes[P.XLEN-1:0]; else Int64Res = CvtNegRes[P.XLEN-1:0];

View File

@ -43,7 +43,7 @@ module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRE
output logic [WIDTH-1:0] dout 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 // TRUE SRAM macro

View File

@ -40,7 +40,7 @@ module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
output logic [WIDTH-1:0] dout 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 // TRUE SRAM macro
@ -49,19 +49,19 @@ module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
// 64 x 128-bit SRAM // 64 x 128-bit SRAM
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .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 end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
// 64 x 44-bit SRAM // 64 x 44-bit SRAM
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .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 end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
// 64 x 22-bit SRAM // 64 x 22-bit SRAM
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we), ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
.A(addr), .D(din), .A(addr), .D(din),
.BWEB('0), .Q(dout)); .BWEB(0), .Q(dout));
// *************************************************************************** // ***************************************************************************
// READ first SRAM model // READ first SRAM model

View File

@ -43,7 +43,7 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
output logic [WIDTH-1:0] rd1 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 SRAMWIDTH = 32;
localparam SRAMNUMSETS = SRAMWIDTH/WIDTH; 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), ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2), .CEBA(~ce1), .CEBB(~ce2),
.WEBA('0), .WEBB(~we2), .WEBA(0), .WEBB(~we2),
.AA(ra1), .AB(wa2), .AA(ra1), .AB(wa2),
.DA('0), .DA(0),
.DB(wd2), .DB(wd2),
.BWEBA('0), .BWEBB('1), .BWEBA(0), .BWEBB('1),
.QA(rd1), .QA(rd1),
.QB()); .QB());
@ -67,11 +67,11 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk), ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2), .CEBA(~ce1), .CEBB(~ce2),
.WEBA('0), .WEBB(~we2), .WEBA(0), .WEBB(~we2),
.AA(ra1), .AB(wa2), .AA(ra1), .AB(wa2),
.DA('0), .DA(0),
.DB(wd2), .DB(wd2),
.BWEBA('0), .BWEBB('1), .BWEBA(0), .BWEBB('1),
.QA(rd1), .QA(rd1),
.QB()); .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]]; assign rd1 = RD1Sets[RA1Q[$clog2(SRAMWIDTH)-1:0]];
ram2p1r1wbe_64x32 memory2(.CLKA(clk), .CLKB(clk), ram2p1r1wbe_64x32 memory2(.CLKA(clk), .CLKB(clk),
.CEBA(~ce1), .CEBB(~ce2), .CEBA(~ce1), .CEBB(~ce2),
.WEBA('0), .WEBB(~we2), .WEBA(0), .WEBB(~we2),
.AA(ra1[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), .AA(ra1[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]),
.AB(wa2[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), .AB(wa2[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]),
.DA('0), .DA(0),
.DB(SRAMWriteData), .DB(SRAMWriteData),
.BWEBA('0), .BWEBB(SRAMBitMask), .BWEBA(0), .BWEBB(SRAMBitMask),
.QA(SRAMReadData), .QA(SRAMReadData),
.QB()); .QB());
@ -110,13 +110,14 @@ module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68)
// READ first SRAM model // READ first SRAM model
// *************************************************************************** // ***************************************************************************
integer i; integer i;
/*
initial begin // initialize memory for simulation only; not needed because done in the testbench now initial begin // initialize memory for simulation only; not needed because done in the testbench now
integer j; integer j;
for (j=0; j < DEPTH; j++) for (j=0; j < DEPTH; j++)
mem[j] = '0; mem[j] = 0;
end end
*/
// Read // Read
logic [$clog2(DEPTH)-1:0] ra1d; logic [$clog2(DEPTH)-1:0] ra1d;
flopen #($clog2(DEPTH)) adrreg(clk, ce1, ra1, ra1d); flopen #($clog2(DEPTH)) adrreg(clk, ce1, ra1, ra1d);

View File

@ -34,7 +34,7 @@ module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
); );
// Core Memory // 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 // dh 10/30/23 ROM macros are presently commented out
// because they don't point to a generated ROM // 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
end end
always @ (posedge clk) begin always_ff @ (posedge clk) begin
if(ce) dout <= ROM[addr]; if(ce) dout <= ROM[addr];
end end

View File

@ -31,7 +31,7 @@ module onehotdecoder #(parameter WIDTH = 2) (
); );
always_comb begin always_comb begin
decoded = '0; decoded = 0;
decoded[bin] = 1'b1; decoded[bin] = 1'b1;
end end

View File

@ -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 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 // 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 // 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 StallDCause = (StructuralStallD | FPUStallD) & ~FlushDCause;
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause; assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
assign StallMCause = WFIStallM & ~FlushMCause; assign StallMCause = WFIStallM & ~FlushMCause;

View File

@ -57,8 +57,8 @@ module cnt #(parameter WIDTH = 32) (
lzc #(WIDTH) lzc(.num(lzcA), .ZeroCnt(czResult[$clog2(WIDTH):0])); lzc #(WIDTH) lzc(.num(lzcA), .ZeroCnt(czResult[$clog2(WIDTH):0]));
popcnt #(WIDTH) popcntw(.num(popcntA), .PopCnt(cpopResult[$clog2(WIDTH):0])); popcnt #(WIDTH) popcntw(.num(popcntA), .PopCnt(cpopResult[$clog2(WIDTH):0]));
// zero extend these results to fit into width // zero extend these results to fit into width
assign czResult[WIDTH-1:$clog2(WIDTH)+1] = '0; assign czResult[WIDTH-1:$clog2(WIDTH)+1] = 0;
assign cpopResult[WIDTH-1:$clog2(WIDTH)+1] = '0; assign cpopResult[WIDTH-1:$clog2(WIDTH)+1] = 0;
mux2 #(WIDTH) cntresultmux(czResult, cpopResult, B[1], CntResult); mux2 #(WIDTH) cntresultmux(czResult, cpopResult, B[1], CntResult);
endmodule endmodule

View File

@ -224,7 +224,7 @@ module bpred import cvw::*; #(parameter cvw_t P) (
assign BTAWrongM = BPBTAWrongM & PCSrcM; assign BTAWrongM = BPBTAWrongM & PCSrcM;
end else begin end else begin
assign {BTAWrongM, RASPredPCWrongM} = '0; assign {BTAWrongM, RASPredPCWrongM} = 0;
end end
// **** Fix me // **** Fix me

View File

@ -65,7 +65,7 @@ module icpred import cvw::*; #(parameter cvw_t P,
assign CJumpF = cjal | cj | cjr | cjalr; assign CJumpF = cjal | cj | cjr | cjalr;
assign CBranchF = CompressedOpcF[4:1] == 4'h7; assign CBranchF = CompressedOpcF[4:1] == 4'h7;
end else begin end else begin
assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = '0; assign {cjal, cj, cjr, cjalr, CJumpF, CBranchF} = 0;
end end
assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F; assign NCJumpF = PostSpillInstrRawF[6:0] == 7'h67 | PostSpillInstrRawF[6:0] == 7'h6F;

View File

@ -116,7 +116,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
SpeculativeFlushedF <= #1 FlushedBits[IndexLHRNextF]; SpeculativeFlushedF <= #1 FlushedBits[IndexLHRNextF];
if (reset | FlushD) FlushedBits <= #1 '1; if (reset | FlushD) FlushedBits <= #1 '1;
if(BranchD & ~StallE & ~FlushE) begin if(BranchD & ~StallE & ~FlushE) begin
FlushedBits[IndexLHRD] <= #1 '0; FlushedBits[IndexLHRD] <= #1 0;
end end
end end

View File

@ -194,10 +194,10 @@ module ifu import cvw::*; #(parameter cvw_t P) (
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin end else begin
assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = '0; assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = 0;
assign PCPF = PCFExt[P.PA_BITS-1:0]; assign PCPF = PCFExt[P.PA_BITS-1:0];
assign CacheableF = '1; assign CacheableF = 1;
assign SelIROM = '0; assign SelIROM = 0;
end end
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
@ -234,8 +234,8 @@ module ifu import cvw::*; #(parameter cvw_t P) (
logic ICacheBusAck; logic ICacheBusAck;
logic [1:0] CacheBusRW, BusRW, CacheRWF; logic [1:0] CacheBusRW, BusRW, CacheRWF;
assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : '0; assign BusRW = ~ITLBMissF & ~CacheableF & ~SelIROM ? IFURWF : 0;
assign CacheRWF = ~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. // *** 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), cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.ICACHE_LINELENINBITS),
.NUMLINES(P.ICACHE_WAYSIZEINBYTES*8/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 end else begin : passthrough
assign IFUHADDR = PCPF; assign IFUHADDR = PCPF;
logic [1:0] BusRW; logic [1:0] BusRW;
assign BusRW = ~ITLBMissF & ~SelIROM ? IFURWF : '0; assign BusRW = ~ITLBMissF & ~SelIROM ? IFURWF : 0;
assign IFUHSIZE = 3'b010; assign IFUHSIZE = 3'b010;
ahbinterface #(P.XLEN, 1'b0) ahbinterface(.HCLK(clk), .Flush(FlushD), .HRESETn(~reset), .HREADY(IFUHREADY), 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), .HWSTRB(), .BusRW, .BusAtomic('0), .ByteMask(), .WriteData('0),
.Stall(GatedStallD), .BusStall, .BusCommitted(BusCommittedF), .FetchBuffer(FetchBuffer)); .Stall(GatedStallD), .BusStall, .BusCommitted(BusCommittedF), .FetchBuffer(FetchBuffer));
assign CacheCommittedF = '0; assign CacheCommittedF = 0;
if(P.IROM_SUPPORTED) mux2 #(32) UnCachedDataMux2(ShiftUncachedInstr, IROMInstrF, SelIROM, InstrRawF); if(P.IROM_SUPPORTED) mux2 #(32) UnCachedDataMux2(ShiftUncachedInstr, IROMInstrF, SelIROM, InstrRawF);
else assign InstrRawF = ShiftUncachedInstr; else assign InstrRawF = ShiftUncachedInstr;
assign IFUHBURST = 3'b0; assign IFUHBURST = 3'b0;
assign {ICacheMiss, ICacheAccess, ICacheStallF} = '0; assign {ICacheMiss, ICacheAccess, ICacheStallF} = 0;
end end
end else begin : nobus // block: bus end else begin : nobus // block: bus
assign {BusStall, CacheCommittedF} = '0; assign {BusStall, CacheCommittedF} = 0;
assign {ICacheStallF, ICacheMiss, ICacheAccess} = '0; assign {ICacheStallF, ICacheMiss, ICacheAccess} = 0;
assign InstrRawF = IROMInstrF; assign InstrRawF = IROMInstrF;
end end
@ -355,7 +355,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
.BTBBranchF(1'b0), .BPCallF(), .BPReturnF(), .BPJumpF(), .BPBranchF(), .IClassWrongM, .BTBBranchF(1'b0), .BPCallF(), .BPReturnF(), .BPJumpF(), .BPBranchF(), .IClassWrongM,
.IClassWrongE(), .BPReturnWrongD()); .IClassWrongE(), .BPReturnWrongD());
flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, BPWrongM); flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, BPWrongM);
assign RASPredPCWrongM = '0; assign RASPredPCWrongM = 0;
assign BPDirPredWrongM = BPWrongM; assign BPDirPredWrongM = BPWrongM;
assign BTAWrongM = BPWrongM; assign BTAWrongM = BPWrongM;
assign InstrClassM = {CallM, ReturnM, JumpM, BranchM}; assign InstrClassM = {CallM, ReturnM, JumpM, BranchM};

View File

@ -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] IEUAdrM, // 2 byte aligned PC in Fetch stage
input logic [P.XLEN-1:0] IEUAdrE, // The next IEUAdrM input logic [P.XLEN-1:0] IEUAdrE, // The next IEUAdrM
input logic [2:0] Funct3M, // Size of memory operation input logic [2:0] Funct3M, // Size of memory operation
input logic FpLoadStoreM, // Floating point Load or Store
input logic [1:0] MemRWM, 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 [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 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] 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 [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 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 [P.LLEN-1:0] DCacheReadDataWordSpillM, // The final 32 bit instruction after merging the two spilled fetches into 1 instruction
output logic SpillStallM); output logic SpillStallM);
@ -72,6 +72,7 @@ module align import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] IEUAdrIncrementM; logic [P.XLEN-1:0] IEUAdrIncrementM;
localparam OFFSET_LEN = $clog2(LLENINBYTES);
logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM; logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM;
logic [$clog2(LLENINBYTES)+2:0] ShiftAmount; logic [$clog2(LLENINBYTES)+2:0] ShiftAmount;
logic PotentialSpillM; logic PotentialSpillM;
@ -93,22 +94,25 @@ module align import cvw::*; #(parameter cvw_t P) (
// compute misalignement // compute misalignement
always_comb begin always_comb begin
case (Funct3M[1:0]) case (Funct3M & {FpLoadStoreM, 2'b11})
2'b00: AccessByteOffsetM = '0; // byte access 3'b000: AccessByteOffsetM = 0; // byte access
2'b01: AccessByteOffsetM = {2'b00, IEUAdrM[0]}; // half access 3'b001: AccessByteOffsetM = {{OFFSET_LEN-1{1'b0}}, IEUAdrM[0]}; // half access
2'b10: AccessByteOffsetM = {1'b0, IEUAdrM[1:0]}; // word access 3'b010: AccessByteOffsetM = {{OFFSET_LEN-2{1'b0}}, IEUAdrM[1:0]}; // word access
2'b11: AccessByteOffsetM = IEUAdrM[2:0]; // double access 3'b011: if(P.LLEN >= 64) AccessByteOffsetM = {{OFFSET_LEN-3{1'b0}}, IEUAdrM[2:0]}; // double access
default: AccessByteOffsetM = IEUAdrM[2:0]; 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 endcase
case (Funct3M[1:0]) 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'b01: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:1] == '1; // half access
2'b10: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:2] == '1; // word 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 2'b11: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:3] == '1; // double access
default: PotentialSpillM = '0; default: PotentialSpillM = 0;
endcase endcase
end 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 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 always_comb begin
case (CurrState) case (CurrState)
STATE_READY: if (ValidSpillM & ~MemRWM[0]) NextState = STATE_SPILL; // load spill STATE_READY: if (ValidSpillM) NextState = STATE_SPILL; // load spill
else if(ValidSpillM) NextState = STATE_STORE_DELAY; // store spill
else NextState = STATE_READY; // no spill else NextState = STATE_READY; // no spill
STATE_SPILL: if(StallM) NextState = STATE_SPILL; STATE_SPILL: if(StallM) NextState = STATE_SPILL;
else NextState = STATE_READY; else NextState = STATE_READY;
STATE_STORE_DELAY: NextState = STATE_SPILL;
default: NextState = STATE_READY; default: NextState = STATE_READY;
endcase endcase
end end
assign SelSpillM = (CurrState == STATE_SPILL | CurrState == STATE_STORE_DELAY); assign SelSpillM = CurrState == STATE_SPILL;
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall) | (CurrState == STATE_STORE_DELAY); assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall);
assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM; assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM;
assign SelStoreDelay = (CurrState == STATE_STORE_DELAY); // *** Can this be merged into the PreLSURWM logic?
assign SpillStallM = SelSpillE; 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) // shifter (4:1 mux for 32 bit, 8:1 mux for 64 bit)
// 8 * is for shifting by bytes not bits // 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 ReadDataWordSpillShiftedM = ReadDataWordSpillAllM >> ShiftAmount;
assign DCacheReadDataWordSpillM = ReadDataWordSpillShiftedM[P.LLEN-1:0]; assign DCacheReadDataWordSpillM = ReadDataWordSpillShiftedM[P.LLEN-1:0];

View File

@ -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 [(P.LLEN-1)/8:0] ByteMaskExtendedM; // Selects which bytes within a word to write
logic [1:0] MemRWSpillM; logic [1:0] MemRWSpillM;
logic SpillStallM; logic SpillStallM;
logic SelStoreDelay;
logic DTLBMissM; // DTLB miss causes HPTW walk logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB 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); flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
if(MISALIGN_SUPPORT) begin : ziccslm_align if(MISALIGN_SUPPORT) begin : ziccslm_align
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM; 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, .MemRWM,
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW, .DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM, .ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM, .IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM);
.SelStoreDelay);
assign IEUAdrExtM = {2'b00, IEUAdrSpillM}; assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
assign IEUAdrExtE = {2'b00, IEUAdrSpillE}; assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
end else begin : no_ziccslm_align end else begin : no_ziccslm_align
assign IEUAdrExtM = {2'b00, IEUAdrM}; assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE}; assign IEUAdrExtE = {2'b00, IEUAdrE};
assign SelSpillE = '0; assign SelSpillE = 0;
assign DCacheReadDataWordSpillM = DCacheReadDataWordM; assign DCacheReadDataWordSpillM = DCacheReadDataWordM;
assign ByteMaskSpillM = ByteMaskM; assign ByteMaskSpillM = ByteMaskM;
assign LSUWriteDataSpillM = LSUWriteDataM; assign LSUWriteDataSpillM = LSUWriteDataM;
assign MemRWSpillM = MemRWM; assign MemRWSpillM = MemRWM;
assign {SpillStallM, SelStoreDelay} = '0; assign {SpillStallM} = 0;
end end
if(P.ZICBOZ_SUPPORTED) begin : cboz if(P.ZICBOZ_SUPPORTED) begin : cboz
mux2 #(P.XLEN) writedatacbozmux(WriteDataM, '0, CMOpM[3], WriteDataZM); assign WriteDataZM = CMOpM[3] ? 0 : WriteDataM;
end else begin : cboz end else begin : cboz
assign WriteDataZM = WriteDataM; assign WriteDataZM = WriteDataM;
end end
@ -218,8 +216,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM; assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
assign LoadPageFaultM = LSULoadPageFaultM; assign LoadPageFaultM = LSULoadPageFaultM;
assign StoreAmoPageFaultM = LSUStoreAmoPageFaultM; assign StoreAmoPageFaultM = LSUStoreAmoPageFaultM;
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0; assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = 0;
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = '0; assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = 0;
end end
// CommittedM indicates the cache, bus, or HPTW are busy with a multiple cycle operation. // 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); .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin // No MMU, so no PMA/page faults and no address translation end else begin // No MMU, so no PMA/page faults and no address translation
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0; assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = 0;
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = '0; assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = 0;
assign PAdrM = IHAdrM[P.PA_BITS-1:0]; assign PAdrM = IHAdrM[P.PA_BITS-1:0];
assign CacheableM = 1'b1; 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 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. // 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); 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. // **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point. // **** create config to support DTIM with floating point.
// Add support for cboz // Add support for cboz
@ -318,22 +316,22 @@ module lsu import cvw::*; #(parameter cvw_t P) (
if(P.ZICBOZ_SUPPORTED) begin if(P.ZICBOZ_SUPPORTED) begin
assign BusCMOZero = CMOpM[3] & ~CacheableM; assign BusCMOZero = CMOpM[3] & ~CacheableM;
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : '0; assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : 0;
assign BusAtomic = AtomicM[1] & ~CacheableM; assign BusAtomic = AtomicM[1] & ~CacheableM;
end else begin end else begin
assign BusCMOZero = '0; assign BusCMOZero = 0;
assign CacheCMOpM = '0; assign CacheCMOpM = 0;
assign BusAtomic = '0; assign BusAtomic = 0;
end end
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0; assign BusRW = (~CacheableM & ~SelDTIM )? LSURWM : 0;
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM; assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0; assign CacheRWM = (CacheableM & ~SelDTIM) ? LSURWM : 0;
assign FlushDCache = FlushDCacheM & ~(SelHPTW); 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), 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( .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), .clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM), .CacheRW(CacheRWM),
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM), .FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]), .ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW, .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 end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
logic [P.XLEN-1:0] FetchBuffer; logic [P.XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0; assign BusRW = (~IgnoreRequestTLB & ~SelDTIM) ? LSURWM : 0;
assign LSUHADDR = PAdrM; assign LSUHADDR = PAdrM;
assign LSUHSIZE = LSUFunct3M; 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]); 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. 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 LSUHBURST = 3'b0;
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0; assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = 0;
end end
end else begin: nobus // block: bus, only DTIM end else begin: nobus // block: bus, only DTIM
assign LSUHWDATA = '0; assign LSUHWDATA = 0;
assign ReadDataWordMuxM = DTIMReadDataWordM; assign ReadDataWordMuxM = DTIMReadDataWordM;
assign {BusStall, BusCommittedM} = '0; assign {BusStall, BusCommittedM} = 0;
assign {DCacheMiss, DCacheAccess} = '0; assign {DCacheMiss, DCacheAccess} = 0;
assign {DCacheStallM, DCacheCommittedM} = '0; assign {DCacheStallM, DCacheCommittedM} = 0;
end end
assign LSUBusStallM = BusStall & ~IgnoreRequestTLB; assign LSUBusStallM = BusStall & ~IgnoreRequestTLB;

View File

@ -29,39 +29,42 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module subwordread import cvw::*; #(parameter cvw_t P) ( module subwordread import cvw::*; #(parameter cvw_t P) (
input logic [P.LLEN-1:0] ReadDataWordMuxM, input logic [P.LLEN-1:0] ReadDataWordMuxM,
input logic [3:0] PAdrM, input logic [3:0] PAdrM,
input logic [2:0] Funct3M, input logic [2:0] Funct3M,
input logic FpLoadStoreM, input logic FpLoadStoreM,
input logic BigEndianM, input logic BigEndianM,
output logic [P.LLEN-1:0] ReadDataM output logic [P.LLEN-1:0] ReadDataM
); );
localparam ADRBITS = $clog2(P.LLEN)-3; localparam ADRBITS = $clog2(P.LLEN)-3;
logic [ADRBITS-1:0] PAdrSwapM;
logic [7:0] ByteM; logic [7:0] ByteM;
logic [15:0] HalfwordM; logic [15:0] HalfwordM;
logic [31:0] WordM; logic [31:0] WordM;
logic [63:0] DblWordM; 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 // sign extension/ NaN boxing
always_comb always_comb
case(Funct3M) case(Funct3M)
3'b000: ReadDataM = {{(P.LLEN-8){ByteM[7]}}, ByteM}; // lb 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'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'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 3'b011: if (P.LLEN >= 64) ReadDataM = {{P.LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
else ReadDataM = ReadDataWordMuxM; 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 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 else ReadDataM = {{P.LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {{P.LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu 3'b101: ReadDataM = {{P.LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu

View File

@ -55,9 +55,9 @@ module subwordwrite #(parameter LLEN) (
end else begin:sww // 32-bit end else begin:sww // 32-bit
always_comb always_comb
case(LSUFunct3M[1:0]) case(LSUFunct3M[1:0])
2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb 2'b00: LittleEndianWriteDataM = {4{IMAFWriteDataM[7:0]}}; // sb
2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh 2'b01: LittleEndianWriteDataM = {2{IMAFWriteDataM[15:0]}}; // sh
2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw 2'b10: LittleEndianWriteDataM = IMAFWriteDataM; // sw
default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen default: LittleEndianWriteDataM = IMAFWriteDataM; // shouldn't happen
endcase endcase
end end

View File

@ -42,7 +42,7 @@ module swbytemask #(parameter WORDLEN, EXTEND = 0)(
assign ByteMaskExtended = ExtendedByteMask[WORDLEN*2/8-1:WORDLEN/8]; assign ByteMaskExtended = ExtendedByteMask[WORDLEN*2/8-1:WORDLEN/8];
end else begin end else begin
assign ByteMask = (('d2**('d2**Size))-'d1) << Adr; assign ByteMask = (('d2**('d2**Size))-'d1) << Adr;
assign ByteMaskExtended = '0; assign ByteMaskExtended = 0;
end end
/* Equivalent to the following /* Equivalent to the following

View File

@ -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) 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; assign PRegEn = HPTWRW[1] & ~DCacheBusStallM | UpdatePTE;
flopenr #(P.XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache 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 // 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 // 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; 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 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. 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 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); 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 end else begin // block: hptwwrites
assign NextPTE = ReadDataNoXM; assign NextPTE = ReadDataNoXM;
assign HPTWAdr = HPTWReadAdr; assign HPTWAdr = HPTWReadAdr;
assign HPTWUpdateDA = '0; assign HPTWUpdateDA = 0;
assign UpdatePTE = '0; assign UpdatePTE = 0;
assign HPTWRW[0] = '0; assign HPTWRW[0] = 0;
end end
// Enable and select signals based on states // Enable and select signals based on states

View File

@ -98,6 +98,6 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
// Output the hit physical address if translation is currently on. // 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 // 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 endmodule

View File

@ -74,11 +74,11 @@ module csri import cvw::*; #(parameter cvw_t P) (
assign SIP_WRITE_MASK = 12'h000; assign SIP_WRITE_MASK = 12'h000;
assign MIE_WRITE_MASK = 12'h888; assign MIE_WRITE_MASK = 12'h888;
end end
always @(posedge clk) always_ff @(posedge clk)
if (reset) MIP_REGW_writeable <= 12'b0; if (reset) MIP_REGW_writeable <= 12'b0;
else if (WriteMIPM) MIP_REGW_writeable <= (CSRWriteValM[11:0] & MIP_WRITE_MASK); 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); 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; 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 (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 else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222 & MIDELEG_REGW) | (MIE_REGW & 12'h888); // only S fields

View File

@ -163,7 +163,7 @@ module csrm import cvw::*; #(parameter cvw_t P) (
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); 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 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); 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 // MENVCFG register
if (P.U_SUPPORTED) begin // menvcfg only exists if there is a lower privilege to control 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 // verilator lint_off WIDTH
logic [5:0] entry; logic [5:0] entry;
always_comb begin always_comb begin
entry = '0; entry = 0;
CSRMReadValM = 0; CSRMReadValM = 0;
IllegalCSRMAccessM = !(P.S_SUPPORTED) & (CSRAdrM == MEDELEG | CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode 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 if (CSRAdrM >= PMPADDR0 & CSRAdrM < PMPADDR0 + P.PMP_ENTRIES) // reading a PMP entry

View File

@ -66,7 +66,7 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0}; /*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 end else begin: csrsr32 // RV32
assign MSTATUS_REGW = {STATUS_SD, 8'b0, assign MSTATUS_REGW = {STATUS_SD, 8'b0,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,

View File

@ -80,7 +80,7 @@ module privdec import cvw::*; #(parameter cvw_t P) (
if (P.U_SUPPORTED) begin:wfi if (P.U_SUPPORTED) begin:wfi
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1; 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 flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
// coverage off -item e 1 -fecexprrow 1 // 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. // 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.

View File

@ -65,8 +65,8 @@ module trap import cvw::*; #(parameter cvw_t P) (
assign PendingIntsM = MIP_REGW & MIE_REGW; assign PendingIntsM = MIP_REGW & MIE_REGW;
assign IntPendingM = |PendingIntsM; assign IntPendingM = |PendingIntsM;
assign Committed = CommittedM | CommittedF; assign Committed = CommittedM | CommittedF;
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); assign EnabledIntsM = (MIntGlobalEnM ? PendingIntsM & ~MIDELEG_REGW : 0) | (SIntGlobalEnM ? PendingIntsM & MIDELEG_REGW : 0);
assign ValidIntsM = {12{~Committed}} & EnabledIntsM; 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. 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. // 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]) & assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &

View File

@ -63,7 +63,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
// register access // register access
if (P.XLEN==64) begin:clint // 64-bit if (P.XLEN==64) begin:clint // 64-bit
always @(posedge PCLK) begin always_ff @(posedge PCLK) begin
case(entry) case(entry)
16'h0000: PRDATA <= {63'b0, MSIP}; 16'h0000: PRDATA <= {63'b0, MSIP};
16'h4000: PRDATA <= MTIMECMP; 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]; MTIME[j*8 +: 8] <= PWDATA[j*8 +: 8];
end else MTIME <= MTIME + 1; end else MTIME <= MTIME + 1;
end else begin:clint // 32-bit end else begin:clint // 32-bit
always @(posedge PCLK) begin always_ff @(posedge PCLK) begin
case(entry) case(entry)
16'h0000: PRDATA <= {31'b0, MSIP}; 16'h0000: PRDATA <= {31'b0, MSIP};
16'h4000: PRDATA <= MTIMECMP[31:0]; 16'h4000: PRDATA <= MTIMECMP[31:0];

View File

@ -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 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 PREADY = 1'b1; // PLIC never takes >1 cycle to respond
assign entry = {PADDR[23:2],2'b0}; 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 // account for subword read/write circuitry
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW. // -- 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; 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 // resetting
if (~PRESETn) begin if (~PRESETn) begin
intPriority <= #1 '0; intPriority <= #1 0;
intEn <= #1 '0; intEn <= #1 0;
intThreshold <= #1 '0; intThreshold <= #1 0;
intInProgress <= #1 '0; intInProgress <= #1 0;
// writing // writing
end else begin end else begin
if (memwrite) if (memwrite)

View File

@ -520,7 +520,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
intrpending = 0; intrpending = 0;
end end
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 // Side effect of reading LSR is lowering overrun, parity, framing, break intr's
assign setSquashRXerrIP = ~MEMRb & (A==3'b101); assign setSquashRXerrIP = ~MEMRb & (A==3'b101);

View File

@ -136,7 +136,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r"); ProgramAddrMapFP = $fopen(ProgramAddrMapFile, "r");
// read line by line to count lines // read line by line to count lines
if (ProgramAddrMapFP != '0) begin if (ProgramAddrMapFP != 0) begin
while (! $feof(ProgramAddrMapFP)) begin while (! $feof(ProgramAddrMapFP)) begin
status = $fscanf(ProgramAddrMapFP, "%h\n", ProgramAddrMapLine); status = $fscanf(ProgramAddrMapFP, "%h\n", ProgramAddrMapLine);
ProgramAddrMapMemory[ProgramAddrMapLineCount] = ProgramAddrMapLine; ProgramAddrMapMemory[ProgramAddrMapLineCount] = ProgramAddrMapLine;
@ -154,7 +154,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
ProgramLabelMapLineCount = 0; ProgramLabelMapLineCount = 0;
ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r"); ProgramLabelMapFP = $fopen(ProgramLabelMapFile, "r");
if (ProgramLabelMapFP != '0) begin if (ProgramLabelMapFP != 0) begin
while (! $feof(ProgramLabelMapFP)) begin while (! $feof(ProgramLabelMapFP)) begin
status = $fscanf(ProgramLabelMapFP, "%s\n", ProgramLabelMapLine); status = $fscanf(ProgramLabelMapFP, "%s\n", ProgramLabelMapLine);
ProgramLabelMapMemory[ProgramLabelMapLineCount] = ProgramLabelMapLine; ProgramLabelMapMemory[ProgramLabelMapLineCount] = ProgramLabelMapLine;
@ -174,7 +174,7 @@ module FunctionName import cvw::*; #(parameter cvw_t P) (
logic OrReducedAdr, AnyUnknown; logic OrReducedAdr, AnyUnknown;
assign OrReducedAdr = |ProgramAddrIndex; assign OrReducedAdr = |ProgramAddrIndex;
assign AnyUnknown = (OrReducedAdr === 1'bx) ? 1'b1 : 1'b0; assign AnyUnknown = (OrReducedAdr === 1'bx) ? 1'b1 : 1'b0;
initial ProgramAddrIndex = '0; initial ProgramAddrIndex = 0;
always @(*) FunctionName = AnyUnknown ? "Unknown!" : ProgramLabelMapMemory[ProgramAddrIndex]; always @(*) FunctionName = AnyUnknown ? "Unknown!" : ProgramLabelMapMemory[ProgramAddrIndex];

View File

@ -63,7 +63,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
logic CSRWriteM, CSRWriteW; logic CSRWriteM, CSRWriteW;
logic [11:0] CSRAdrM, CSRAdrW; logic [11:0] CSRAdrM, CSRAdrW;
logic wfiM; logic wfiM;
logic InterruptM; logic InterruptM, InterruptW;
assign clk = testbench.dut.clk; assign clk = testbench.dut.clk;
// assign InstrValidF = testbench.dut.core.ieu.InstrValidF; // not needed yet // 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 end
genvar index; genvar index;
assign rf[0] = '0; assign rf[0] = 0;
for(index = 1; index < NUMREGS; index += 1) for(index = 1; index < NUMREGS; index += 1)
assign rf[index] = testbench.dut.core.ieu.dp.regf.rf[index]; 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; assign rf_we3 = testbench.dut.core.ieu.dp.regf.we3;
always_comb begin always_comb begin
rf_wb <= '0; rf_wb <= 0;
if(rf_we3) if(rf_we3)
rf_wb[rf_a3] <= 1'b1; rf_wb[rf_a3] <= 1'b1;
end 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; assign frf_we4 = testbench.dut.core.fpu.fpu.fregfile.we4;
always_comb begin always_comb begin
frf_wb <= '0; frf_wb <= 0;
if(frf_we4) if(frf_we4)
frf_wb[frf_a4] <= 1'b1; frf_wb[frf_a4] <= 1'b1;
end 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 #(P.XLEN)PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW); flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW); 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); flopenrc #(1) HaltWReg (clk, reset, 1'b0, ~StallW, HaltM, HaltW);
// **** remove? are these used? // **** 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.order[0][0] = CSRArray[12'hB02]; // TODO: IMPERAS Should be event order
assign rvvi.insn[0][0] = InstrRawW; assign rvvi.insn[0][0] = InstrRawW;
assign rvvi.pc_rdata[0][0] = PCW; 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.halt[0][0] = HaltW;
assign rvvi.intr[0][0] = 0; assign rvvi.intr[0][0] = InterruptW;
assign rvvi.mode[0][0] = PrivilegeModeW; assign rvvi.mode[0][0] = PrivilegeModeW;
assign rvvi.ixl[0][0] = PrivilegeModeW == 2'b11 ? 2'b10 : assign rvvi.ixl[0][0] = PrivilegeModeW == 2'b11 ? 2'b10 :
PrivilegeModeW == 2'b01 ? STATUS_SXL : STATUS_UXL; PrivilegeModeW == 2'b01 ? STATUS_SXL : STATUS_UXL;
@ -492,7 +493,7 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
end end
// *** implementation only cancel? so sc does not clear? // *** implementation only cancel? so sc does not clear?
assign rvvi.lrsc_cancel[0][0] = '0; assign rvvi.lrsc_cancel[0][0] = 0;
integer index2; integer index2;

View File

@ -40,7 +40,7 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
OldPCW <= PCW; OldPCW <= PCW;
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1; if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
else WatchDogTimerCount = '0; else WatchDogTimerCount = 0;
end end
always_comb begin always_comb begin

View File

@ -252,9 +252,9 @@ module testbench;
assign SDCCmdIn = SDCCmd; assign SDCCmdIn = SDCCmd;
assign SDCDatIn = SDCDat; assign SDCDatIn = SDCDat;
-----/\----- EXCLUDED -----/\----- */ -----/\----- EXCLUDED -----/\----- */
assign SDCIntr = '0; assign SDCIntr = 0;
end else begin end else begin
assign SDCIntr = '0; assign SDCIntr = 0;
end end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,

View File

@ -335,7 +335,7 @@ module testbench;
if (P.UNCORE_RAM_SUPPORTED) begin if (P.UNCORE_RAM_SUPPORTED) begin
`ifdef TB_UNCORE_RAM_SUPPORTED `ifdef TB_UNCORE_RAM_SUPPORTED
for (adrindex=0; adrindex<(P.UNCORE_RAM_RANGE>>1+(P.XLEN/32)); adrindex = adrindex+1) 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 `endif
end end
if(reset) begin // branch predictor must always be reset if(reset) begin // branch predictor must always be reset
@ -411,7 +411,7 @@ module testbench;
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB); .HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB);
end else begin end else begin
assign HREADYEXT = 1; assign HREADYEXT = 1;
assign {HRESPEXT, HRDATAEXT} = '0; assign {HRESPEXT, HRDATAEXT} = 0;
end end
if(P.FPGA) begin : sdcard if(P.FPGA) begin : sdcard
@ -424,8 +424,8 @@ module testbench;
assign SDCCmdIn = SDCCmd; assign SDCCmdIn = SDCCmd;
assign SDCDatIn = SDCDat; assign SDCDatIn = SDCDat;
end else begin end else begin
assign SDCCmd = '0; assign SDCCmd = 0;
assign SDCDat = '0; assign SDCDat = 0;
end end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,

View File

@ -124,6 +124,7 @@ module testbench;
"imperas64f": if (P.F_SUPPORTED) tests = imperas64f; "imperas64f": if (P.F_SUPPORTED) tests = imperas64f;
"imperas64d": if (P.D_SUPPORTED) tests = imperas64d; "imperas64d": if (P.D_SUPPORTED) tests = imperas64d;
"imperas64m": if (P.M_SUPPORTED) tests = imperas64m; "imperas64m": if (P.M_SUPPORTED) tests = imperas64m;
"wally64q": if (P.Q_SUPPORTED) tests = wally64q;
"wally64a": if (P.A_SUPPORTED) tests = wally64a; "wally64a": if (P.A_SUPPORTED) tests = wally64a;
"imperas64c": if (P.C_SUPPORTED) tests = imperas64c; "imperas64c": if (P.C_SUPPORTED) tests = imperas64c;
else tests = imperas64iNOc; else tests = imperas64iNOc;
@ -440,7 +441,7 @@ module testbench;
always @(posedge clk) always @(posedge clk)
if (ResetMem) // program memory is sometimes reset (e.g. for CoreMark, which needs zeroed memory) 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) 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 // Actual hardware
@ -457,7 +458,7 @@ module testbench;
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB); .HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB);
end else begin end else begin
assign HREADYEXT = 1; assign HREADYEXT = 1;
assign {HRESPEXT, HRDATAEXT} = '0; assign {HRESPEXT, HRDATAEXT} = 0;
end end
if(P.SDC_SUPPORTED) begin : sdcard 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 SDCDat = sd_dat_reg_t ? sd_dat_reg_o : sd_dat_i;
assign SDCDatIn = SDCDat; assign SDCDatIn = SDCDat;
-----/\----- EXCLUDED -----/\----- */ -----/\----- EXCLUDED -----/\----- */
assign SDCIntr = '0; assign SDCIntr = 0;
end else begin end else begin
assign SDCIntr = '0; assign SDCIntr = 0;
end end
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,

View File

@ -869,6 +869,10 @@ string imperas32f[] = '{
"rv32i_m/I/XORI-01" "rv32i_m/I/XORI-01"
}; };
string wally64q[] = '{
`WALLYTEST,
"rv64i_m/Q/src/WALLY-q-01.S"
};
string wally64a[] = '{ string wally64a[] = '{
`WALLYTEST, `WALLYTEST,

View File

@ -2,12 +2,12 @@ hart_ids: [0]
hart0: hart0:
# ISA: RV64IMAFDCSUZicsr_Zicboz_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb # ISA: RV64IMAFDCSUZicsr_Zicboz_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
# ISA: RV64IMAFDCSUZicsr_Zifencei_Zca_Zcb_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 physical_addr_sz: 56
User_Spec_Version: '2.3' User_Spec_Version: '2.3'
supported_xlen: [64] supported_xlen: [64]
misa: misa:
reset-val: 0x800000000014112D reset-val: 0x800000000015112D
rv32: rv32:
accessible: false accessible: false
rv64: rv64:

View File

@ -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

View File

@ -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