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

View File

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

View File

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

View File

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

View File

@ -222,63 +222,63 @@ if (nightly):
### branch predictor simulation
["bpred_TWOBIT_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_TWOBIT_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_TWOBIT_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# btb
["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_8_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_12_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# # btb
# ["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_8_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_12_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ras
["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_3_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_4_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_6_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_10_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# # ras
# ["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_3_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_4_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_6_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_10_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# ["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"],
# enable floating-point tests when lint is fixed
["f_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma"]],
["fh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32zfh", "arch32zfh_divsqrt"]],
["fdh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
["fdq_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
["fdq_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma"]],
["fdqh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]],
["f_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma"]],
["fh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64zfh", "arch64zfh_divsqrt"]], # hanging 1/31/24 dh; try again when lint is fixed
["fdh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]],
["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma"]],
["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt", "wally64q"]],
]

18
src/cache/cache.sv vendored
View File

@ -82,7 +82,7 @@ module cache import cvw::*; #(parameter cvw_t P,
logic ClearDirty, SetDirty, SetValid, ClearValid;
logic [LINELEN-1:0] ReadDataLineWay [NUMWAYS-1:0];
logic [NUMWAYS-1:0] HitWay, ValidWay;
logic CacheHit;
logic Hit;
logic [NUMWAYS-1:0] VictimWay, DirtyWay, HitDirtyWay;
logic LineDirty, HitLineDirty;
logic [TAGLEN-1:0] TagWay [NUMWAYS-1:0];
@ -98,7 +98,7 @@ module cache import cvw::*; #(parameter cvw_t P,
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
logic SelFetchBuffer;
logic CacheEn;
logic SelWay;
logic SelVictim;
logic [LINELEN/8-1:0] LineByteMask;
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
genvar index;
@ -120,7 +120,7 @@ module cache import cvw::*; #(parameter cvw_t P,
// Array of cache ways, along with victim, hit, dirty, and read merging logic
cacheway #(P, PA_BITS, XLEN, NUMLINES, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelWay,
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelVictim,
.SetValid, .ClearValid, .SetDirty, .ClearDirty, .VictimWay,
.FlushWay, .FlushCache, .ReadDataLineWay, .HitWay, .ValidWay, .DirtyWay, .HitDirtyWay, .TagWay, .FlushStage, .InvalidateCache);
@ -132,7 +132,7 @@ module cache import cvw::*; #(parameter cvw_t P,
end else
assign VictimWay = 1'b1; // one hot.
assign CacheHit = |HitWay;
assign Hit = |HitWay;
assign LineDirty = |DirtyWay;
assign HitLineDirty = |HitDirtyWay;
@ -176,18 +176,18 @@ module cache import cvw::*; #(parameter cvw_t P,
logic [LINELEN/8-1:0] BlankByteMask;
assign BlankByteMask[WORDLEN/8-1:0] = ByteMask;
assign BlankByteMask[LINELEN/8-1:WORDLEN/8] = '0;
assign BlankByteMask[LINELEN/8-1:WORDLEN/8] = 0;
assign DemuxedByteMask = BlankByteMask << ((MUXINTERVAL/8) * WordOffsetAddr);
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
assign FetchBufferByteSel = SetDirty ? ~DemuxedByteMask : '1; // If load miss set all muxes to 1.
// Merge write data into fetched cache line for store miss
for(index = 0; index < LINELEN/8; index++) begin
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index] & ~CMOpM[3]), .y(LineWriteData[8*index+7:8*index]));
end
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
assign LineByteMask = SetDirty ? DemuxedByteMask : '1;
end
else
begin:WriteSelLogic
@ -226,8 +226,8 @@ module cache import cvw::*; #(parameter cvw_t P,
cachefsm #(P, READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck,
.FlushStage, .CacheRW, .Stall,
.CacheHit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelWay,
.Hit, .LineDirty, .HitLineDirty, .CacheStall, .CacheCommitted,
.CacheMiss, .CacheAccess, .SelAdrData, .SelAdrTag, .SelVictim,
.ClearDirty, .SetDirty, .SetValid, .ClearValid, .SelWriteback,
.FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst,
.FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer,

55
src/cache/cacheLRU.sv vendored
View File

@ -1,7 +1,7 @@
///////////////////////////////////////////
// cacheLRU.sv
//
// Written: Ross Thompson ross1728@gmail.com
// Written: Rose Thompson ross1728@gmail.com
// Created: 20 July 2021
// Modified: 20 January 2023
//
@ -36,8 +36,8 @@ module cacheLRU
input logic CacheEn, // Enable the cache memory arrays. Disable hold read data constant
input logic [NUMWAYS-1:0] HitWay, // Which way is valid and matches PAdr's tag
input logic [NUMWAYS-1:0] ValidWay, // Which ways for a particular set are valid, ignores tag
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
input logic [SETLEN-1:0] PAdr, // Physical address
input logic LRUWriteEn, // Update the LRU state
input logic SetValid, // Set the dirty bit in the selected way and set
@ -51,23 +51,27 @@ module cacheLRU
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
logic [NUMWAYS-2:0] CurrLRU;
logic [NUMWAYS-2:0] NextLRU;
logic [NUMWAYS-1:0] Way;
logic [LOGNUMWAYS-1:0] WayEncoded;
logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
logic [NUMWAYS-2:0] WayExpanded;
logic AllValid;
genvar row;
/* verilator lint_off UNOPTFLAT */
// Ross: For some reason verilator does not like this. I checked and it is not a circular path.
// Rose: For some reason verilator does not like this. I checked and it is not a circular path.
logic [NUMWAYS-2:0] LRUUpdate;
logic [LOGNUMWAYS-1:0] Intermediate [NUMWAYS-2:0];
/* verilator lint_on UNOPTFLAT */
logic [NUMWAYS-1:0] FirstZero;
logic [LOGNUMWAYS-1:0] FirstZeroWay;
logic [LOGNUMWAYS-1:0] VictimWayEnc;
binencoder #(NUMWAYS) hitwayencoder(HitWay, HitWayEncoded);
assign AllValid = &ValidWay;
///// Update replacement bits.
// coverage off
// Excluded from coverage b/c it is untestable without varying NUMWAYS.
function integer log2 (integer value);
@ -80,8 +84,7 @@ module cacheLRU
// coverage on
// On a miss we need to ignore HitWay and derive the new replacement bits with the VictimWay.
mux2 #(NUMWAYS) WayMux(HitWay, VictimWay, SetValid, Way);
binencoder #(NUMWAYS) encoder(Way, WayEncoded);
mux2 #(LOGNUMWAYS) WayMuxEnc(HitWayEncoded, VictimWayEnc, SetValid, Way);
// bit duplication
// expand HitWay as HitWay[3], {{2}{HitWay[2]}}, {{4}{HitWay[1]}, {{8{HitWay[0]}}, ...
@ -89,7 +92,7 @@ module cacheLRU
localparam integer DuplicationFactor = 2**(LOGNUMWAYS-row-1);
localparam StartIndex = NUMWAYS-2 - DuplicationFactor + 1;
localparam EndIndex = NUMWAYS-2 - 2 * DuplicationFactor + 2;
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{WayEncoded[row]}};
assign WayExpanded[StartIndex : EndIndex] = {{DuplicationFactor}{Way[row]}};
end
genvar node;
@ -102,14 +105,14 @@ module cacheLRU
localparam r = LOGNUMWAYS - ctr_depth;
// the child node will be updated if its parent was updated and
// the WayEncoded bit was the correct value.
// the Way bit was the correct value.
// The if statement is only there for coverage since LRUUpdate[root] is always 1.
if (node == NUMWAYS-2) begin
assign LRUUpdate[lchild] = ~WayEncoded[r];
assign LRUUpdate[rchild] = WayEncoded[r];
assign LRUUpdate[lchild] = ~Way[r];
assign LRUUpdate[rchild] = Way[r];
end else begin
assign LRUUpdate[lchild] = LRUUpdate[node] & ~WayEncoded[r];
assign LRUUpdate[rchild] = LRUUpdate[node] & WayEncoded[r];
assign LRUUpdate[lchild] = LRUUpdate[node] & ~Way[r];
assign LRUUpdate[rchild] = LRUUpdate[node] & Way[r];
end
end
@ -129,28 +132,26 @@ module cacheLRU
assign Intermediate[node] = CurrLRU[node] ? int1[LOGNUMWAYS-1:0] : int0[LOGNUMWAYS-1:0];
end
logic [NUMWAYS-1:0] FirstZero;
logic [LOGNUMWAYS-1:0] FirstZeroWay;
logic [LOGNUMWAYS-1:0] VictimWayEnc;
priorityonehot #(NUMWAYS) FirstZeroEncoder(~ValidWay, FirstZero);
binencoder #(NUMWAYS) FirstZeroWayEncoder(FirstZero, FirstZeroWay);
mux2 #(LOGNUMWAYS) VictimMux(FirstZeroWay, Intermediate[NUMWAYS-2], AllValid, VictimWayEnc);
//decoder #(LOGNUMWAYS) decoder (Intermediate[NUMWAYS-2], VictimWay);
decoder #(LOGNUMWAYS) decoder (VictimWayEnc, VictimWay);
// LRU storage must be reset for modelsim to run. However the reset value does not actually matter in practice.
// This is a two port memory.
// Every cycle must read from CacheSetData and each load/store must write the new LRU.
// note: Verilator lint doesn't like <= for array initialization (https://verilator.org/warn/BLKLOOPINIT?v=5.021)
// Move to = to keep Verilator happy and simulator running fast
always_ff @(posedge clk) begin
if (reset | (InvalidateCache & ~FlushStage)) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
if(CacheEn) begin
if(LRUWriteEn)
LRUMemory[PAdr] <= NextLRU;
if(LRUWriteEn & (PAdr == CacheSetTag))
CurrLRU <= NextLRU;
else
CurrLRU <= LRUMemory[CacheSetTag];
if (reset | (InvalidateCache & ~FlushStage))
for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = 0; // exclusion-tag: initialize
else if(CacheEn) begin
// Because we are using blocking assignments, change to LRUMemory must occur after LRUMemory is used so we get the proper value
if(LRUWriteEn & (PAdr == CacheSetTag)) CurrLRU = #1 NextLRU;
else CurrLRU = #1 LRUMemory[CacheSetTag];
if(LRUWriteEn) LRUMemory[PAdr] = NextLRU;
end
end

76
src/cache/cachefsm.sv vendored
View File

@ -50,7 +50,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
output logic CacheAccess, // Cache access
// cache internals
input logic CacheHit, // Exactly 1 way hits
input logic Hit, // Exactly 1 way hits
input logic LineDirty, // The selected line and way is dirty
input logic HitLineDirty, // The cache hit way is dirty
input logic FlushAdrFlag, // On last set of a cache flush
@ -63,7 +63,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
output logic ClearDirty, // Clear the dirty bit in the selected way and set
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
output logic LRUWriteEn, // Update the LRU state
output logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
output logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
output logic FlushWayCntEn, // Enable the way counter during a flush
output logic FlushCntRst, // Reset both flush counters
@ -79,12 +79,12 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
logic CMOZeroNoEviction;
logic StallConditions;
typedef enum logic [3:0]{STATE_READY, // hit states
typedef enum logic [3:0]{STATE_ACCESS, // hit states
// miss states
STATE_FETCH,
STATE_WRITEBACK,
STATE_WRITE_LINE,
STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM
STATE_ADDRESS_SETUP, // required for back to back reads. structural hazard on writting SRAM
// flush cache
STATE_FLUSH,
STATE_FLUSH_WRITEBACK
@ -92,60 +92,60 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
statetype CurrState, NextState;
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
assign AnyUpdateHit = (CacheRW[0]) & CacheHit; // exclusion-tag: icache storeAMO1
assign AnyHit = AnyUpdateHit | (CacheRW[1] & CacheHit); // exclusion-tag: icache AnyUpdateHit
assign AnyMiss = (CacheRW[0] | CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
assign AnyUpdateHit = (CacheRW[0]) & Hit; // exclusion-tag: icache storeAMO1
assign AnyHit = AnyUpdateHit | (CacheRW[1] & Hit); // exclusion-tag: icache AnyUpdateHit
assign CMOZeroNoEviction = CMOpM[3] & ~LineDirty; // (hit or miss) with no writeback store zeros now
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & CacheHit & HitLineDirty) | CMOpM[3] & LineDirty;
assign CMOWriteback = ((CMOpM[1] | CMOpM[2]) & Hit & HitLineDirty) | CMOpM[3] & LineDirty;
assign FlushFlag = FlushAdrFlag & FlushWayFlag;
// outputs for the performance counters.
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_READY & ~Stall & ~FlushStage) | (CurrState == STATE_READ_HOLD & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
assign CacheMiss = CacheAccess & ~CacheHit;
assign CacheAccess = (|CacheRW) & ((CurrState == STATE_ACCESS & ~Stall & ~FlushStage) | (CurrState == STATE_ADDRESS_SETUP & ~Stall & ~FlushStage)); // exclusion-tag: icache CacheW
assign CacheMiss = CacheAccess & ~Hit;
// special case on reset. When the fsm first exists reset the
// special case on reset. When the fsm first exists reset twayhe
// PCNextF will no longer be pointing to the correct address.
// But PCF will be the reset vector.
flop #(1) resetDelayReg(.clk, .d(reset), .q(resetDelay));
always_ff @(posedge clk)
if (reset | FlushStage) CurrState <= #1 STATE_READY;
if (reset | FlushStage) CurrState <= #1 STATE_ACCESS;
else CurrState <= #1 NextState;
always_comb begin
NextState = STATE_READY;
NextState = STATE_ACCESS;
case (CurrState) // exclusion-tag: icache state-case
STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck
STATE_ACCESS: if(InvalidateCache) NextState = STATE_ACCESS; // exclusion-tag: dcache InvalidateCheck
else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; // exclusion-tag: icache FLUSHStatement
else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement
else if((AnyMiss | CMOWriteback) & ~READ_ONLY_CACHE) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement
else NextState = STATE_READY;
else NextState = STATE_ACCESS;
STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE;
else NextState = STATE_FETCH;
STATE_WRITE_LINE: NextState = STATE_READ_HOLD;
STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD;
else NextState = STATE_READY;
STATE_WRITE_LINE: NextState = STATE_ADDRESS_SETUP;
STATE_ADDRESS_SETUP: if(Stall) NextState = STATE_ADDRESS_SETUP;
else NextState = STATE_ACCESS;
// exclusion-tag-start: icache case
STATE_WRITEBACK: if(CacheBusAck & ~(|CMOpM[3:1])) NextState = STATE_FETCH;
else if(CacheBusAck) NextState = STATE_READ_HOLD; // Read_hold lowers CacheStall
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP; // Read_hold lowers CacheStall
else NextState = STATE_WRITEBACK;
// eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack.
STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK;
else if (FlushFlag) NextState = STATE_READ_HOLD;
else if (FlushFlag) NextState = STATE_ADDRESS_SETUP;
else NextState = STATE_FLUSH;
STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH;
else if(CacheBusAck) NextState = STATE_READ_HOLD;
else if(CacheBusAck) NextState = STATE_ADDRESS_SETUP;
else NextState = STATE_FLUSH_WRITEBACK;
// exclusion-tag-end: icache case
default: NextState = STATE_READY;
default: NextState = STATE_ACCESS;
endcase
end
// com back to CPU
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & (CurrState == STATE_READ_HOLD));
assign CacheCommitted = (CurrState != STATE_ACCESS) & ~(READ_ONLY_CACHE & (CurrState == STATE_ADDRESS_SETUP));
assign StallConditions = FlushCache | AnyMiss | CMOWriteback; // exclusion-tag: icache FlushCache
assign CacheStall = (CurrState == STATE_READY & StallConditions) | // exclusion-tag: icache StallStates
assign CacheStall = (CurrState == STATE_ACCESS & StallConditions) | // exclusion-tag: icache StallStates
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) | // this cycle writes the sram, must keep stalling so the next cycle can read the next hit/miss unless its a write.
@ -153,26 +153,26 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
(CurrState == STATE_FLUSH_WRITEBACK);
// write enables internal to cache
assign SetValid = CurrState == STATE_WRITE_LINE |
(CurrState == STATE_READY & CMOZeroNoEviction) |
(CurrState == STATE_ACCESS & CMOZeroNoEviction) |
(CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]);
assign ClearValid = (CurrState == STATE_READY & CMOpM[0]) |
assign ClearValid = (CurrState == STATE_ACCESS & CMOpM[0]) |
(CurrState == STATE_WRITEBACK & CMOpM[2] & CacheBusAck);
assign LRUWriteEn = (((CurrState == STATE_READY & (AnyHit | CMOZeroNoEviction)) |
assign LRUWriteEn = (((CurrState == STATE_ACCESS & (AnyHit | CMOZeroNoEviction)) |
(CurrState == STATE_WRITE_LINE)) & ~FlushStage) |
(CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck);
// exclusion-tag-start: icache flushdirtycontrols
assign SetDirty = (CurrState == STATE_READY & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
assign SetDirty = (CurrState == STATE_ACCESS & (AnyUpdateHit | CMOZeroNoEviction)) | // exclusion-tag: icache SetDirty
(CurrState == STATE_WRITE_LINE & (CacheRW[0])) |
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
// Flush and eviction controls
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
assign SelWay = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
(CurrState == STATE_READY & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~CacheHit))) |
assign SelVictim = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
(CurrState == STATE_ACCESS & ((AnyMiss & LineDirty) | (CMOZeroNoEviction & ~Hit))) |
(CurrState == STATE_WRITE_LINE);
assign SelWriteback = (CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2] | ~CacheBusAck)) |
(CurrState == STATE_READY & AnyMiss & LineDirty);
(CurrState == STATE_ACCESS & AnyMiss & LineDirty);
// coverage off -item e 1 -fecexprrow 1
// (state is always FLUSH_WRITEBACK when FlushWayFlag & CacheBusAck)
assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) |
@ -183,29 +183,29 @@ module cachefsm import cvw::*; #(parameter cvw_t P,
(CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck);
// exclusion-tag-end: icache flushdirtycontrols
// Bus interface controls
assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
assign CacheBusRW[1] = (CurrState == STATE_ACCESS & AnyMiss & ~LineDirty) | // exclusion-tag: icache CacheBusRCauses
(CurrState == STATE_FETCH & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM));
logic LoadMiss;
assign LoadMiss = (CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
assign LoadMiss = (CacheRW[1]) & ~Hit & ~InvalidateCache; // exclusion-tag: cache AnyMiss
assign CacheBusRW[0] = (CurrState == STATE_READY & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
assign CacheBusRW[0] = (CurrState == STATE_ACCESS & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW
(CurrState == STATE_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_FLUSH_WRITEBACK & ~CacheBusAck) |
(CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & ~CacheBusAck);
assign SelAdrData = (CurrState == STATE_READY & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
assign SelAdrData = (CurrState == STATE_ACCESS & (CacheRW[0] | AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) |
resetDelay;
assign SelAdrTag = (CurrState == STATE_READY & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
assign SelAdrTag = (CurrState == STATE_ACCESS & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed
(CurrState == STATE_FETCH) |
(CurrState == STATE_WRITEBACK) |
(CurrState == STATE_WRITE_LINE) |
resetDelay;
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_READ_HOLD;
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_READY) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
assign SelFetchBuffer = CurrState == STATE_WRITE_LINE | CurrState == STATE_ADDRESS_SETUP;
assign CacheEn = (~Stall | StallConditions) | (CurrState != STATE_ACCESS) | reset | InvalidateCache; // exclusion-tag: dcache CacheEn
endmodule // cachefsm

39
src/cache/cacheway.sv vendored
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 ClearValid, // Clear the valid bit in the selected way and set
input logic SetDirty, // Set the dirty bit in the selected way and set
input logic SelWay, // Controls which way to select a way data and tag, 00 = hitway, 10 = victimway, 11 = flushway
input logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
input logic ClearDirty, // Clear the dirty bit in the selected way and set
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
input logic VictimWay, // LRU selected this way as victim to evict
@ -68,7 +68,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
logic [LINELEN-1:0] ReadDataLine;
logic [TAGLEN-1:0] ReadTag;
logic Dirty;
logic SelDirty;
logic SelecteDirty;
logic SelectedWriteWordEn;
logic [LINELEN/8-1:0] FinalByteMask;
logic SetValidEN, ClearValidEN;
@ -77,33 +77,30 @@ module cacheway import cvw::*; #(parameter cvw_t P,
logic SetDirtyWay;
logic ClearDirtyWay;
logic SelNonHit;
logic SelData;
logic SelectedWay;
logic InvalidateCacheDelay;
if (!READ_ONLY_CACHE) begin:flushlogic
logic FlushWayEn;
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelDirty);
mux2 #(1) seltagmux(VictimWay, FlushWay, FlushCache, SelecteDirty);
mux3 #(1) selectedmux(HitWay, FlushWay, VictimWay, {SelVictim, FlushCache}, SelectedWay);
// FlushWay is part of a one hot way selection. Must clear it if FlushWay not selected.
// coverage off -item e 1 -fecexprrow 3
// nonzero ways will never see FlushCache=0 while FlushWay=1 since FlushWay only advances on a subset of FlushCache assertion cases.
assign FlushWayEn = FlushWay & FlushCache;
assign SelNonHit = FlushWayEn | SelWay;
end else begin:flushlogic // no flush operation for read-only caches.
assign SelDirty = VictimWay;
assign SelNonHit = SelWay;
assign SelecteDirty = VictimWay;
mux2 #(1) selectedwaymux(HitWay, SelecteDirty, SelVictim , SelectedWay);
end
mux2 #(1) selectedwaymux(HitWay, SelDirty, SelNonHit , SelData);
/////////////////////////////////////////////////////////////////////////////////////////////
// Write Enable demux
/////////////////////////////////////////////////////////////////////////////////////////////
assign SetValidWay = SetValid & SelData;
assign ClearValidWay = ClearValid & SelData; // exclusion-tag: icache ClearValidWay
assign SetDirtyWay = SetDirty & SelData; // exclusion-tag: icache SetDirtyWay
assign ClearDirtyWay = ClearDirty & SelData;
assign SetValidWay = SetValid & SelectedWay;
assign ClearValidWay = ClearValid & SelectedWay; // exclusion-tag: icache ClearValidWay
assign SetDirtyWay = SetDirty & SelectedWay; // exclusion-tag: icache SetDirtyWay
assign ClearDirtyWay = ClearDirty & SelectedWay;
assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn
assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN
assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN
@ -120,9 +117,9 @@ module cacheway import cvw::*; #(parameter cvw_t P,
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
// AND portion of distributed tag multiplexer
assign TagWay = SelData ? ReadTag : '0; // AND part of AOMux
assign TagWay = SelectedWay ? ReadTag : 0; // AND part of AOMux
assign HitDirtyWay = Dirty & ValidWay;
assign DirtyWay = SelDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
assign DirtyWay = SelecteDirty & HitDirtyWay; // exclusion-tag: icache DirtyWay
assign HitWay = ValidWay & (ReadTag == PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]) & ~InvalidateCacheDelay; // exclusion-tag: dcache HitWay
flop #(1) InvalidateCacheReg(clk, InvalidateCache, InvalidateCacheDelay);
@ -152,19 +149,19 @@ module cacheway import cvw::*; #(parameter cvw_t P,
end
// AND portion of distributed read multiplexers
assign ReadDataLineWay = SelData ? ReadDataLine : '0; // AND part of AO mux.
assign ReadDataLineWay = SelectedWay ? ReadDataLine : 0; // AND part of AO mux.
/////////////////////////////////////////////////////////////////////////////////////////////
// Valid Bits
/////////////////////////////////////////////////////////////////////////////////////////////
always_ff @(posedge clk) begin // Valid bit array,
if (reset) ValidBits <= #1 '0;
if (reset) ValidBits <= #1 0;
if(CacheEn) begin
ValidWay <= #1 ValidBits[CacheSetTag];
if(InvalidateCache) ValidBits <= #1 '0; // exclusion-tag: dcache invalidateway
if(InvalidateCache) ValidBits <= #1 0; // exclusion-tag: dcache invalidateway
else if (SetValidEN) ValidBits[CacheSetData] <= #1 SetValidWay;
else if (ClearValidEN) ValidBits[CacheSetData] <= #1 '0; // exclusion-tag: icache ClearValidBits
else if (ClearValidEN) ValidBits[CacheSetData] <= #1 0; // exclusion-tag: icache ClearValidBits
end
end

View File

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

View File

@ -111,11 +111,11 @@ module ebu import cvw::*; #(parameter cvw_t P) (
.HTRANSOut(LSUHTRANSOut), .HADDROut(LSUHADDROut), .HREADYIn(HREADY));
// output mux //*** switch to structural implementation
assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : '0;
assign HSIZE = LSUSelect ? LSUHSIZEOut : IFUSelect ? IFUHSIZEOut: '0;
assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : '0; // If doing memory accesses, use LSUburst, else use Instruction burst.
assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: '0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
assign HWRITE = LSUSelect ? LSUHWRITEOut : IFUSelect ? 1'b0 : '0;
assign HADDR = LSUSelect ? LSUHADDROut : IFUSelect ? IFUHADDROut : 0;
assign HSIZE = LSUSelect ? LSUHSIZEOut : IFUSelect ? IFUHSIZEOut: 0;
assign HBURST = LSUSelect ? LSUHBURSTOut : IFUSelect ? IFUHBURSTOut : 0; // If doing memory accesses, use LSUburst, else use Instruction burst.
assign HTRANS = LSUSelect ? LSUHTRANSOut : IFUSelect ? IFUHTRANSOut: 0; // SEQ if not first read or write, NONSEQ if first read or write, IDLE otherwise
assign HWRITE = LSUSelect ? LSUHWRITEOut : 0;
assign HPROT = 4'b0011; // not used; see Section 3.7
assign HMASTLOCK = 0; // no locking supported

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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
assign AmInv = {3*P.NF+4{InvA}}^Am;
assign AmInv = InvA ? ~Am : Am;
// Kill the product if the product is too small to effect the addition (determined in fma1.sv)
assign PmKilled = {2*P.NF+2{~KillProd}}&Pm;
assign PmKilled = KillProd ? 0 : Pm;
// Do the addition
// - calculate a positive and negative sum in parallel
// if there was a small negative number killed in the alignment stage one needs to be subtracted from the sum

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

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 #(2) Fmt2EReg(clk, reset, FlushE, ~StallE, InstrD[26:25], Fmt2E);
fli #(P) fli(.Rs1(Rs1E), .Fmt(Fmt2E), .Imm(FliResE));
end else assign FliResE = '0;
end else assign FliResE = 0;
// fmv.*.x: NaN Box SrcA to extend integer to requested FP size
if(P.FPSIZES == 1)

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)
// need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES)
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : '0;
assign DivSubnormShiftAmt = DivSubnormShiftPos ? DivSubnormShift[P.LOGNORMSHIFTSZ-1:0] : 0;
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
// pre-shift the divider result for normalization

View File

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

View File

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

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

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
always_comb begin
if (Zfa) OfIntRes2 = '0; // fcvtmod.w.d produces 0 on overflow
if (Zfa) OfIntRes2 = 0; // fcvtmod.w.d produces 0 on overflow
else OfIntRes2 = OfIntRes;
if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]};
else Int64Res = CvtNegRes[P.XLEN-1:0];

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

View File

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

View File

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

View File

@ -31,7 +31,7 @@ module onehotdecoder #(parameter WIDTH = 2) (
);
always_comb begin
decoded = '0;
decoded = 0;
decoded[bin] = 1'b1;
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 stalls the entire pipeline rather than just Fetch to avoid complications with instructions later in the pipeline causing Exceptions
// A trap could be asserted at the start of a IFU/LSU stall, and should flush the memory operation
assign StallFCause = '0;
assign StallFCause = 0;
assign StallDCause = (StructuralStallD | FPUStallD) & ~FlushDCause;
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
assign StallMCause = WFIStallM & ~FlushMCause;

View File

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

View File

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

View File

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

View File

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

View File

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

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] IEUAdrE, // The next IEUAdrM
input logic [2:0] Funct3M, // Size of memory operation
input logic FpLoadStoreM, // Floating point Load or Store
input logic [1:0] MemRWM,
input logic [P.LLEN*2-1:0] DCacheReadDataWordM, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
input logic CacheBusHPWTStall, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
@ -52,7 +53,6 @@ module align import cvw::*; #(parameter cvw_t P) (
output logic [P.XLEN-1:0] IEUAdrSpillE, // The next PCF for one of the two memory addresses of the spill
output logic [P.XLEN-1:0] IEUAdrSpillM, // IEUAdrM for one of the two memory addresses of the spill
output logic SelSpillE, // During the transition between the two spill operations, the IFU should stall the pipeline
output logic SelStoreDelay, //*** this is bad. really don't like moving this outside
output logic [P.LLEN-1:0] DCacheReadDataWordSpillM, // The final 32 bit instruction after merging the two spilled fetches into 1 instruction
output logic SpillStallM);
@ -72,6 +72,7 @@ module align import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] IEUAdrIncrementM;
localparam OFFSET_LEN = $clog2(LLENINBYTES);
logic [$clog2(LLENINBYTES)-1:0] AccessByteOffsetM;
logic [$clog2(LLENINBYTES)+2:0] ShiftAmount;
logic PotentialSpillM;
@ -93,22 +94,25 @@ module align import cvw::*; #(parameter cvw_t P) (
// compute misalignement
always_comb begin
case (Funct3M[1:0])
2'b00: AccessByteOffsetM = '0; // byte access
2'b01: AccessByteOffsetM = {2'b00, IEUAdrM[0]}; // half access
2'b10: AccessByteOffsetM = {1'b0, IEUAdrM[1:0]}; // word access
2'b11: AccessByteOffsetM = IEUAdrM[2:0]; // double access
default: AccessByteOffsetM = IEUAdrM[2:0];
case (Funct3M & {FpLoadStoreM, 2'b11})
3'b000: AccessByteOffsetM = 0; // byte access
3'b001: AccessByteOffsetM = {{OFFSET_LEN-1{1'b0}}, IEUAdrM[0]}; // half access
3'b010: AccessByteOffsetM = {{OFFSET_LEN-2{1'b0}}, IEUAdrM[1:0]}; // word access
3'b011: if(P.LLEN >= 64) AccessByteOffsetM = {{OFFSET_LEN-3{1'b0}}, IEUAdrM[2:0]}; // double access
else AccessByteOffsetM = 0; // shouldn't happen
3'b100: if(P.LLEN == 128) AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0]; // quad access
else AccessByteOffsetM = IEUAdrM[OFFSET_LEN-1:0];
default: AccessByteOffsetM = 0; // shouldn't happen
endcase
case (Funct3M[1:0])
2'b00: PotentialSpillM = '0; // byte access
2'b00: PotentialSpillM = 0; // byte access
2'b01: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:1] == '1; // half access
2'b10: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:2] == '1; // word access
2'b11: PotentialSpillM = IEUAdrM[OFFSET_BIT_POS-1:3] == '1; // double access
default: PotentialSpillM = '0;
default: PotentialSpillM = 0;
endcase
end
assign MisalignedM = (|MemRWM) & (AccessByteOffsetM != '0);
assign MisalignedM = (|MemRWM) & (AccessByteOffsetM != 0);
assign ValidSpillM = MisalignedM & PotentialSpillM & ~CacheBusHPWTStall; // Don't take the spill if there is a stall
@ -118,20 +122,17 @@ module align import cvw::*; #(parameter cvw_t P) (
always_comb begin
case (CurrState)
STATE_READY: if (ValidSpillM & ~MemRWM[0]) NextState = STATE_SPILL; // load spill
else if(ValidSpillM) NextState = STATE_STORE_DELAY; // store spill
STATE_READY: if (ValidSpillM) NextState = STATE_SPILL; // load spill
else NextState = STATE_READY; // no spill
STATE_SPILL: if(StallM) NextState = STATE_SPILL;
else NextState = STATE_READY;
STATE_STORE_DELAY: NextState = STATE_SPILL;
default: NextState = STATE_READY;
endcase
end
assign SelSpillM = (CurrState == STATE_SPILL | CurrState == STATE_STORE_DELAY);
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall) | (CurrState == STATE_STORE_DELAY);
assign SelSpillM = CurrState == STATE_SPILL;
assign SelSpillE = (CurrState == STATE_READY & ValidSpillM) | (CurrState == STATE_SPILL & CacheBusHPWTStall);
assign SpillSaveM = (CurrState == STATE_READY) & ValidSpillM & ~FlushM;
assign SelStoreDelay = (CurrState == STATE_STORE_DELAY); // *** Can this be merged into the PreLSURWM logic?
assign SpillStallM = SelSpillE;
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -147,7 +148,7 @@ module align import cvw::*; #(parameter cvw_t P) (
// shifter (4:1 mux for 32 bit, 8:1 mux for 64 bit)
// 8 * is for shifting by bytes not bits
assign ShiftAmount = SelHPTW ? '0 : {AccessByteOffsetM, 3'b0}; // AND gate
assign ShiftAmount = SelHPTW ? 0 : {AccessByteOffsetM, 3'b0}; // AND gate
assign ReadDataWordSpillShiftedM = ReadDataWordSpillAllM >> ShiftAmount;
assign DCacheReadDataWordSpillM = ReadDataWordSpillShiftedM[P.LLEN-1:0];

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 [1:0] MemRWSpillM;
logic SpillStallM;
logic SelStoreDelay;
logic DTLBMissM; // DTLB miss causes HPTW walk
logic DTLBWriteM; // Writes PTE and PageType to DTLB
@ -164,28 +163,27 @@ module lsu import cvw::*; #(parameter cvw_t P) (
flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
if(MISALIGN_SUPPORT) begin : ziccslm_align
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M,
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM,
.MemRWM,
.DCacheReadDataWordM, .CacheBusHPWTStall, .SelHPTW,
.ByteMaskM, .ByteMaskExtendedM, .LSUWriteDataM, .ByteMaskSpillM, .LSUWriteDataSpillM,
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM,
.SelStoreDelay);
.IEUAdrSpillE, .IEUAdrSpillM, .SelSpillE, .DCacheReadDataWordSpillM, .SpillStallM);
assign IEUAdrExtM = {2'b00, IEUAdrSpillM};
assign IEUAdrExtE = {2'b00, IEUAdrSpillE};
end else begin : no_ziccslm_align
assign IEUAdrExtM = {2'b00, IEUAdrM};
assign IEUAdrExtE = {2'b00, IEUAdrE};
assign SelSpillE = '0;
assign SelSpillE = 0;
assign DCacheReadDataWordSpillM = DCacheReadDataWordM;
assign ByteMaskSpillM = ByteMaskM;
assign LSUWriteDataSpillM = LSUWriteDataM;
assign MemRWSpillM = MemRWM;
assign {SpillStallM, SelStoreDelay} = '0;
assign {SpillStallM} = 0;
end
if(P.ZICBOZ_SUPPORTED) begin : cboz
mux2 #(P.XLEN) writedatacbozmux(WriteDataM, '0, CMOpM[3], WriteDataZM);
end else begin : cboz
assign WriteDataZM = CMOpM[3] ? 0 : WriteDataM;
end else begin : cboz
assign WriteDataZM = WriteDataM;
end
@ -218,8 +216,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
assign LoadPageFaultM = LSULoadPageFaultM;
assign StoreAmoPageFaultM = LSUStoreAmoPageFaultM;
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = '0;
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = '0;
assign {HPTWStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF, IgnoreRequestTLB} = 0;
assign {HPTWInstrAccessFaultF, HPTWInstrPageFaultF} = 0;
end
// CommittedM indicates the cache, bus, or HPTW are busy with a multiple cycle operation.
@ -255,8 +253,8 @@ module lsu import cvw::*; #(parameter cvw_t P) (
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
end else begin // No MMU, so no PMA/page faults and no address translation
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = '0;
assign {DTLBMissM, LSULoadAccessFaultM, LSUStoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = 0;
assign {LSULoadPageFaultM, LSUStoreAmoPageFaultM} = 0;
assign PAdrM = IHAdrM[P.PA_BITS-1:0];
assign CacheableM = 1'b1;
assign SelDTIM = P.DTIM_SUPPORTED & ~P.BUS_SUPPORTED; // if no PMA then select dtim if there is a DTIM. If there is
@ -281,7 +279,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
mux2 #(P.PA_BITS) DTIMAdrMux(IEUAdrExtE[P.PA_BITS-1:0], IEUAdrExtM[P.PA_BITS-1:0], MemRWM[0], DTIMAdr);
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : 0;
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
// **** create config to support DTIM with floating point.
// Add support for cboz
@ -318,22 +316,22 @@ module lsu import cvw::*; #(parameter cvw_t P) (
if(P.ZICBOZ_SUPPORTED) begin
assign BusCMOZero = CMOpM[3] & ~CacheableM;
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : '0;
assign CacheCMOpM = (CacheableM & ~SelHPTW) ? CMOpM : 0;
assign BusAtomic = AtomicM[1] & ~CacheableM;
end else begin
assign BusCMOZero = '0;
assign CacheCMOpM = '0;
assign BusAtomic = '0;
assign BusCMOZero = 0;
assign CacheCMOpM = 0;
assign BusAtomic = 0;
end
assign BusRW = ~CacheableM & ~SelDTIM ? LSURWM : '0;
assign BusRW = (~CacheableM & ~SelDTIM )? LSURWM : 0;
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
assign CacheRWM = CacheableM & ~SelDTIM ? LSURWM : '0;
assign CacheRWM = (CacheableM & ~SelDTIM) ? LSURWM : 0;
assign FlushDCache = FlushDCacheM & ~(SelHPTW);
cache #(.P(P), .PA_BITS(P.PA_BITS), .XLEN(P.XLEN), .LINELEN(P.DCACHE_LINELENINBITS), .NUMLINES(P.DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(P.DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(CACHEWORDLEN), .MUXINTERVAL(P.LLEN), .READ_ONLY_CACHE(0)) dcache(
.clk, .reset, .Stall(GatedStallW & ~SelSpillE), .SelBusBeat, .FlushStage(FlushW | IgnoreRequestTLB),
.CacheRW(SelStoreDelay ? 2'b00 : CacheRWM),
.CacheRW(CacheRWM),
.FlushCache(FlushDCache), .NextSet(IEUAdrExtE[11:0]), .PAdr(PAdrM),
.ByteMask(ByteMaskSpillM), .BeatCount(BeatCount[AHBWLOGBWPL-1:AHBWLOGBWPL-LLENLOGBWPL]),
.CacheWriteData(LSUWriteDataSpillM), .SelHPTW,
@ -367,7 +365,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
logic [P.XLEN-1:0] FetchBuffer;
assign BusRW = ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
assign BusRW = (~IgnoreRequestTLB & ~SelDTIM) ? LSURWM : 0;
assign LSUHADDR = PAdrM;
assign LSUHSIZE = LSUFunct3M;
@ -381,14 +379,14 @@ module lsu import cvw::*; #(parameter cvw_t P) (
if(P.DTIM_SUPPORTED) mux2 #(P.XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM[P.XLEN-1:0], SelDTIM, ReadDataWordMuxM[P.XLEN-1:0]);
else assign ReadDataWordMuxM[P.XLEN-1:0] = FetchBuffer[P.XLEN-1:0]; // *** bus only does not support double wide floats.
assign LSUHBURST = 3'b0;
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0;
assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = 0;
end
end else begin: nobus // block: bus, only DTIM
assign LSUHWDATA = '0;
assign LSUHWDATA = 0;
assign ReadDataWordMuxM = DTIMReadDataWordM;
assign {BusStall, BusCommittedM} = '0;
assign {DCacheMiss, DCacheAccess} = '0;
assign {DCacheStallM, DCacheCommittedM} = '0;
assign {BusStall, BusCommittedM} = 0;
assign {DCacheMiss, DCacheAccess} = 0;
assign {DCacheStallM, DCacheCommittedM} = 0;
end
assign LSUBusStallM = BusStall & ~IgnoreRequestTLB;

View File

@ -29,39 +29,42 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module subwordread import cvw::*; #(parameter cvw_t P) (
input logic [P.LLEN-1:0] ReadDataWordMuxM,
input logic [3:0] PAdrM,
input logic [2:0] Funct3M,
input logic FpLoadStoreM,
input logic BigEndianM,
output logic [P.LLEN-1:0] ReadDataM
input logic [P.LLEN-1:0] ReadDataWordMuxM,
input logic [3:0] PAdrM,
input logic [2:0] Funct3M,
input logic FpLoadStoreM,
input logic BigEndianM,
output logic [P.LLEN-1:0] ReadDataM
);
localparam ADRBITS = $clog2(P.LLEN)-3;
logic [ADRBITS-1:0] PAdrSwapM;
logic [7:0] ByteM;
logic [15:0] HalfwordM;
logic [31:0] WordM;
logic [63:0] DblWordM;
logic [ADRBITS-1:0] PAdrSwap;
// Funct3M[2] is the unsigned bit. mask upper bits.
// Funct3M[1:0] is the size of the memory access.
if (P.BIGENDIAN_SUPPORTED) assign PAdrSwap = PAdrM[ADRBITS-1:0] ^ {ADRBITS{BigEndianM}};
else assign PAdrSwap = PAdrM[ADRBITS-1:0];
assign ByteM = ReadDataWordMuxM[PAdrSwap*8 +: 8];
assign HalfwordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1:1]*16 +: 16];
if (P.LLEN >= 64) assign WordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1:2] * 32 +: 32];
else assign WordM = ReadDataWordMuxM;
if (P.LLEN >= 64) assign DblWordM = ReadDataWordMuxM[PAdrSwap[ADRBITS-1] * 64 +: 64];
// invert lsbs of address to select appropriate subword for big endian
if (P.BIGENDIAN_SUPPORTED) assign PAdrSwapM = PAdrM[ADRBITS-1:0] ^ {ADRBITS{BigEndianM}};
else assign PAdrSwapM = PAdrM[ADRBITS-1:0];
// Use indexed part select to imply muxes to select each size of subword
if (P.LLEN == 128) mux2 #(64) dblmux(ReadDataWordMuxM[63:0], ReadDataWordMuxM[127:64], PAdrSwapM[3], DblWordM);
else if (P.LLEN == 64) assign DblWordM = ReadDataWordMuxM;
if (P.LLEN >= 64) mux2 #(32) wordmux(DblWordM[31:0], DblWordM[63:32], PAdrSwapM[2], WordM);
else assign WordM = ReadDataWordMuxM;
mux2 #(16) halfwordmux(WordM[15:0], WordM[31:16], PAdrSwapM[1], HalfwordM);
mux2 #(8) bytemux(HalfwordM[7:0], HalfwordM[15:8], PAdrSwapM[0], ByteM);
// sign extension/ NaN boxing
always_comb
case(Funct3M)
3'b000: ReadDataM = {{(P.LLEN-8){ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{P.LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
3'b010: ReadDataM = {{P.LLEN-32{WordM[31]|FpLoadStoreM}}, WordM[31:0]}; // lw/flw
3'b011: if (P.LLEN >= 64) ReadDataM = {{P.LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
else ReadDataM = ReadDataWordMuxM;
3'b000: ReadDataM = {{(P.LLEN-8){ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{P.LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
3'b010: ReadDataM = {{P.LLEN-32{WordM[31]|FpLoadStoreM}}, WordM[31:0]}; // lw/flw
3'b011: if (P.LLEN >= 64) ReadDataM = {{P.LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
else ReadDataM = ReadDataWordMuxM; // shouldn't happen
3'b100: if (P.LLEN == 128) ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{P.LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq
else ReadDataM = {{P.LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {{P.LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu

View File

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

View File

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

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)
assign PRegEn = HPTWRW[1] & ~DCacheBusStallM | UpdatePTE;
flopenr #(P.XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache
assert property(@(posedge clk) ~PRegEn | reset | NextPTE[0] !== 1'bx); // report writing an x PTE from an uninitialized page table
// Assign PTE descriptors common across all XLEN values
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
@ -174,7 +173,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] AccessedPTE;
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
//assign ReadDataNoXM = (ReadDataM[0] === 'x) ? '0 : ReadDataM; // If the PTE.V bit is x because it was read from uninitialized memory set to 0 to avoid x propagation and hanging the simulation.
//assign ReadDataNoXM = (ReadDataM[0] === 'x) ? 0 : ReadDataM; // If the PTE.V bit is x because it was read from uninitialized memory set to 0 to avoid x propagation and hanging the simulation.
assign ReadDataNoXM = ReadDataM; // *** temporary fix for synthesis; === and x in line above are not synthesizable.
mux2 #(P.XLEN) NextPTEMux(ReadDataNoXM, AccessedPTE, UpdatePTE, NextPTE); // NextPTE = ReadDataNoXM when ADUE = 0 because UpdatePTE = 0
flopenr #(P.PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
@ -214,9 +213,9 @@ module hptw import cvw::*; #(parameter cvw_t P) (
end else begin // block: hptwwrites
assign NextPTE = ReadDataNoXM;
assign HPTWAdr = HPTWReadAdr;
assign HPTWUpdateDA = '0;
assign UpdatePTE = '0;
assign HPTWRW[0] = '0;
assign HPTWUpdateDA = 0;
assign UpdatePTE = 0;
assign HPTWRW[0] = 0;
end
// Enable and select signals based on states

View File

@ -98,6 +98,6 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
// Output the hit physical address if translation is currently on.
// Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal
mux2 #(P.PA_BITS) hitmux('0, {PPNMixed2, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system
assign TLBPAdr = TLBHit ? {PPNMixed2, Offset} : 0;
endmodule

View File

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

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

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_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
assign MSTATUSH_REGW = 0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
end else begin: csrsr32 // RV32
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,

View File

@ -80,7 +80,7 @@ module privdec import cvw::*; #(parameter cvw_t P) (
if (P.U_SUPPORTED) begin:wfi
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
assign WFICountPlus1 = wfiM ? '0 : WFICount + 1; // restart counting on WFI
assign WFICountPlus1 = wfiM ? WFICount + 1 : '0; // restart counting on WFI
flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
// coverage off -item e 1 -fecexprrow 1
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.

View File

@ -65,8 +65,8 @@ module trap import cvw::*; #(parameter cvw_t P) (
assign PendingIntsM = MIP_REGW & MIE_REGW;
assign IntPendingM = |PendingIntsM;
assign Committed = CommittedM | CommittedF;
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
assign EnabledIntsM = (MIntGlobalEnM ? PendingIntsM & ~MIDELEG_REGW : 0) | (SIntGlobalEnM ? PendingIntsM & MIDELEG_REGW : 0);
assign ValidIntsM = Committed ? 0 : EnabledIntsM;
assign InterruptM = (|ValidIntsM) & InstrValidM & (~wfiM | wfiW); // suppress interrupt if the memory system has partially processed a request. Delay interrupt until wfi is in the W stage.
// wfiW is to support possible but unlikely back to back wfi instructions. wfiM would be high in the M stage, while also in the W stage.
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &

View File

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

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 PREADY = 1'b1; // PLIC never takes >1 cycle to respond
assign entry = {PADDR[23:2],2'b0};
assign One[P.PLIC_NUM_SRC-1:1] = '0; assign One[0] = 1'b1; // Vivado does not like this as a single assignment.
assign One[P.PLIC_NUM_SRC-1:1] = 0; assign One[0] = 1'b1; // Vivado does not like this as a single assignment.
// account for subword read/write circuitry
// -- Note PLIC registers are 32 bits no matter what; access them with LW SW.
@ -104,13 +104,13 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
// ==================
localparam PLIC_NUM_SRC_MIN_32 = P.PLIC_NUM_SRC < 32 ? P.PLIC_NUM_SRC : 31;
always @(posedge PCLK) begin
always_ff @(posedge PCLK) begin
// resetting
if (~PRESETn) begin
intPriority <= #1 '0;
intEn <= #1 '0;
intThreshold <= #1 '0;
intInProgress <= #1 '0;
intPriority <= #1 0;
intEn <= #1 0;
intThreshold <= #1 0;
intInProgress <= #1 0;
// writing
end else begin
if (memwrite)

View File

@ -520,7 +520,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
intrpending = 0;
end
end
always @(posedge PCLK) INTR <= #1 intrpending; // prevent glitches on interrupt pin
always_ff @(posedge PCLK) INTR <= #1 intrpending; // prevent glitches on interrupt pin
// Side effect of reading LSR is lowering overrun, parity, framing, break intr's
assign setSquashRXerrIP = ~MEMRb & (A==3'b101);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,12 +2,12 @@ hart_ids: [0]
hart0:
# ISA: RV64IMAFDCSUZicsr_Zicboz_Zifencei_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
# ISA: RV64IMAFDCSUZicsr_Zifencei_Zca_Zcb_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
ISA: RV64IMAFDCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
ISA: RV64IMAFDQCSUZicsr_Zicond_Zifencei_Zfa_Zfh_Zba_Zbb_Zbc_Zbs # Zkbs_Zcb
physical_addr_sz: 56
User_Spec_Version: '2.3'
supported_xlen: [64]
misa:
reset-val: 0x800000000014112D
reset-val: 0x800000000015112D
rv32:
accessible: false
rv64:

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