mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge pull request #819 from ross144/main
wsim now supports directories
This commit is contained in:
commit
b9d177edc4
36
README.md
36
README.md
@ -150,20 +150,22 @@ If you want to add a cronjob you can do the following:
|
|||||||
|
|
||||||
wsim runs one of multiple simulators, Questa, VCS, or Verilator using a specific configuration and either a suite of tests or a specific elf file.
|
wsim runs one of multiple simulators, Questa, VCS, or Verilator using a specific configuration and either a suite of tests or a specific elf file.
|
||||||
The general syntax is
|
The general syntax is
|
||||||
wsim <config> <suite or elf file> [--options]
|
wsim <config> <suite or elf file or directory> [--options]
|
||||||
|
|
||||||
Parameters and options:
|
Parameters and options:
|
||||||
|
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--elf, -e Elf file
|
--sim {questa,verilator,vcs}, -s {questa,verilator,vcs} Simulator
|
||||||
--sim {questa,verilator,vcs}, -s {questa,verilator,vcs} Simulator
|
--tb {testbench,testbench_fp}, -t {testbench,testbench_fp} Testbench
|
||||||
--tb {testbench,testbench_fp}, -t {testbench,testbench_fp} Testbench
|
--gui, -g Simulate with GUI
|
||||||
--gui, -g Simulate with GUI
|
--coverage, -c Code & Functional Coverage
|
||||||
--coverage, -c Code & Functional Coverage
|
--fcov, -f Code & Functional Coverage
|
||||||
--args ARGS, -a ARGS Optional arguments passed to simulator via $value$plusargs
|
--args ARGS, -a ARGS Optional arguments passed to simulator via $value$plusargs
|
||||||
--vcd, -v Generate testbench.vcd
|
--vcd, -v Generate testbench.vcd
|
||||||
--lockstep, -l Run ImperasDV lock, step, and compare.
|
--lockstep, -l Run ImperasDV lock, step, and compare.
|
||||||
--locksteplog LOCKSTEPLOG, -b LOCKSTEPLOG Retired instruction number to be begin logging.
|
--locksteplog LOCKSTEPLOG, -b LOCKSTEPLOG Retired instruction number to be begin logging.
|
||||||
|
--covlog COVLOG, -d COVLOG Log coverage after n instructions.
|
||||||
|
--elfext ELFEXT, -e ELFEXT When searching for elf files only includes ones which end in this extension
|
||||||
|
|
||||||
Run basic test with questa
|
Run basic test with questa
|
||||||
|
|
||||||
@ -175,8 +177,16 @@ Run Questa with gui
|
|||||||
|
|
||||||
Run lockstep against ImperasDV with a single elf file in the --gui. Lockstep requires single elf.
|
Run lockstep against ImperasDV with a single elf file in the --gui. Lockstep requires single elf.
|
||||||
|
|
||||||
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --elf --lockstep --gui
|
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --lockstep --gui
|
||||||
|
|
||||||
Run lockstep against ImperasDV with a single elf file. Compute coverage.
|
Run lockstep against ImperasDV with a single elf file. Compute coverage.
|
||||||
|
|
||||||
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --elf --lockstep --coverage
|
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/add-01.S/ref/ref.elf --lockstep --coverage
|
||||||
|
|
||||||
|
Run lockstep against ImperasDV with directory file.
|
||||||
|
|
||||||
|
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/ --lockstep
|
||||||
|
|
||||||
|
Run lockstep against ImperasDV with directory file and specify specific extension.
|
||||||
|
|
||||||
|
wsim rv64gc ../../tests/riscof/work/riscv-arch-test/rv64i_m/I/src/ --lockstep --elfext ref.elf
|
||||||
|
137
bin/wsim
137
bin/wsim
@ -14,11 +14,72 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
def LaunchSim(ElfFile):
|
||||||
|
# Launch selected simulator
|
||||||
|
cd = "cd $WALLY/sim/" +args.sim
|
||||||
|
# ugh. can't have more than 9 arguments passed to vsim. why? I'll have to remove --lockstep when running
|
||||||
|
# functional coverage and imply it.
|
||||||
|
if (args.sim == "questa"):
|
||||||
|
if (args.lockstep):
|
||||||
|
prefix = "IMPERAS_TOOLS=" + WALLY + "/sim/imperas.ic"
|
||||||
|
if(int(args.locksteplog) >= 1): EnableLog = 1
|
||||||
|
else: EnableLog = 0
|
||||||
|
if(args.locksteplog != 0): ImperasPlusArgs = " +IDV_TRACE2LOG=" + str(EnableLog) + " +IDV_TRACE2LOG_AFTER=" + str(args.locksteplog)
|
||||||
|
else: ImperasPlusArgs = ""
|
||||||
|
if(args.fcov):
|
||||||
|
CovEnableStr = "1" if int(args.covlog) > 0 else "0";
|
||||||
|
if(args.covlog >= 1): EnableLog = 1
|
||||||
|
else: EnableLog = 0
|
||||||
|
ImperasPlusArgs = " +IDV_TRACE2COV=" + str(EnableLog) + " +TRACE2LOG_AFTER=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr;
|
||||||
|
suffix = ""
|
||||||
|
else:
|
||||||
|
CovEnableStr = ""
|
||||||
|
suffix = "--lockstep"
|
||||||
|
else:
|
||||||
|
prefix = ""
|
||||||
|
ImperasPlusArgs = ""
|
||||||
|
suffix = ""
|
||||||
|
if (args.tb == "testbench_fp"):
|
||||||
|
args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args
|
||||||
|
cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + suffix + " " + ImperasPlusArgs
|
||||||
|
if (args.coverage):
|
||||||
|
cmd += " --coverage"
|
||||||
|
if (args.fcov):
|
||||||
|
cmd += " --fcov"
|
||||||
|
if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible
|
||||||
|
if(args.tb == "testbench"):
|
||||||
|
cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\""
|
||||||
|
elif(args.tb == "testbench_fp"):
|
||||||
|
cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\""
|
||||||
|
else: # launch Questa in batch mode
|
||||||
|
cmd = cd + "; " + prefix + " vsim -c -do \"" + cmd + "\""
|
||||||
|
print("Running Questa with command: " + cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
elif (args.sim == "verilator"):
|
||||||
|
# PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i
|
||||||
|
print(f"Running Verilator on {args.config} {args.testsuite}")
|
||||||
|
if (args.coverage):
|
||||||
|
print("Coverage option not available for Verilator")
|
||||||
|
exit(1)
|
||||||
|
if (args.gui):
|
||||||
|
print("GUI option not available for Verilator")
|
||||||
|
exit(1)
|
||||||
|
os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'")
|
||||||
|
elif (args.sim == "vcs"):
|
||||||
|
print(f"Running VCS on " + args.config + " " + args.testsuite)
|
||||||
|
if (args.gui):
|
||||||
|
args.args += "gui"
|
||||||
|
elif (args.coverage):
|
||||||
|
args.args += "coverage"
|
||||||
|
cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + " " + args.args
|
||||||
|
print(cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("config", help="Configuration file")
|
parser.add_argument("config", help="Configuration file")
|
||||||
parser.add_argument("testsuite", help="Test suite or ELF file")
|
parser.add_argument("testsuite", help="Test suite or ELF file")
|
||||||
parser.add_argument("--elf", "-e", help="Elf file", action="store_true")
|
|
||||||
parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilator", "vcs"], default="questa")
|
parser.add_argument("--sim", "-s", help="Simulator", choices=["questa", "verilator", "vcs"], default="questa")
|
||||||
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
|
parser.add_argument("--tb", "-t", help="Testbench", choices=["testbench", "testbench_fp"], default="testbench")
|
||||||
parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
|
parser.add_argument("--gui", "-g", help="Simulate with GUI", action="store_true")
|
||||||
@ -29,13 +90,25 @@ parser.add_argument("--vcd", "-v", help="Generate testbench.vcd", action="store_
|
|||||||
parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true")
|
parser.add_argument("--lockstep", "-l", help="Run ImperasDV lock, step, and compare.", action="store_true")
|
||||||
parser.add_argument("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0)
|
parser.add_argument("--locksteplog", "-b", help="Retired instruction number to be begin logging.", default=0)
|
||||||
parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0)
|
parser.add_argument("--covlog", "-d", help="Log coverage after n instructions.", default=0)
|
||||||
|
parser.add_argument("--elfext", "-e", help="When searching for elf files only includes ones which end in this extension", default=".elf")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'")
|
print("Config=" + args.config + " tests=" + args.testsuite + " sim=" + args.sim + " gui=" + str(args.gui) + " args='" + args.args + "'")
|
||||||
ElfFile=""
|
ElfFile=""
|
||||||
|
DirectorMode = 0
|
||||||
|
ElfList = []
|
||||||
|
|
||||||
if(args.elf):
|
if(os.path.isfile(args.testsuite)):
|
||||||
ElfFile = "+ElfFile=" + args.testsuite
|
ElfFile = "+ElfFile=" + args.testsuite
|
||||||
args.testsuite = "none"
|
args.testsuite = "none"
|
||||||
|
ElfList.append("+ElfFile=" + args.testsuite)
|
||||||
|
elif(os.path.isdir(args.testsuite)):
|
||||||
|
DirectorMode = 1
|
||||||
|
for dirpath, dirnames, filenames in os.walk(args.testsuite):
|
||||||
|
for file in filenames:
|
||||||
|
if file.endswith(args.elfext):
|
||||||
|
ElfList.append("+ElfFile=" + os.path.join(dirpath, file))
|
||||||
|
args.testsuite = "none"
|
||||||
|
print(ElfList)
|
||||||
|
|
||||||
# Validate arguments
|
# Validate arguments
|
||||||
if (args.gui):
|
if (args.gui):
|
||||||
@ -60,59 +133,9 @@ for d in ["logs", "wkdir", "cov"]:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if(DirectorMode):
|
||||||
|
for ElfFile in ElfList:
|
||||||
|
LaunchSim(ElfFile)
|
||||||
|
|
||||||
# Launch selected simulator
|
else:
|
||||||
cd = "cd $WALLY/sim/" +args.sim
|
LaunchSim(ElfFile)
|
||||||
# ugh. can't have more than 9 arguments passed to vsim. why? I'll have to remove --lockstep when running
|
|
||||||
# functional coverage and imply it.
|
|
||||||
if (args.sim == "questa"):
|
|
||||||
if (args.lockstep):
|
|
||||||
prefix = "IMPERAS_TOOLS=" + WALLY + "/sim/imperas.ic" # OTHERFLAGS=\"+IDV_TRACE2LOG=" + str(args.locksteplog) + " +IDV_TRACE2COV=" + str(args.covlog) + "\"";
|
|
||||||
if(args.fcov):
|
|
||||||
CovEnableStr = "1" if int(args.covlog) > 0 else "0";
|
|
||||||
#ImperasPlusArgs = "+IDV_TRACE2LOG=" + str(args.locksteplog) + " +IDV_TRACE2COV=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr;
|
|
||||||
ImperasPlusArgs = " +IDV_TRACE2COV=" + str(args.covlog) + " +TRACE2COV_ENABLE=" + CovEnableStr;
|
|
||||||
suffix = ""
|
|
||||||
else:
|
|
||||||
CovEnableStr = ""
|
|
||||||
ImperasPlusArgs = "";
|
|
||||||
suffix = "--lockstep"
|
|
||||||
else:
|
|
||||||
prefix = ""
|
|
||||||
ImperasPlusArgs = ""
|
|
||||||
suffix = ""
|
|
||||||
if (args.tb == "testbench_fp"):
|
|
||||||
args.args = " -GTEST=\"" + args.testsuite + "\" " + args.args
|
|
||||||
cmd = "do wally.do " + args.config + " " + args.testsuite + " " + args.tb + " " + args.args + " " + ElfFile + " " + suffix + " " + ImperasPlusArgs
|
|
||||||
if (args.coverage):
|
|
||||||
cmd += " --coverage"
|
|
||||||
if (args.fcov):
|
|
||||||
cmd += " --fcov"
|
|
||||||
if (args.gui): # launch Questa with GUI; add +acc to keep variables accessible
|
|
||||||
if(args.tb == "testbench"):
|
|
||||||
cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc -GDEBUG=1\""
|
|
||||||
elif(args.tb == "testbench_fp"):
|
|
||||||
cmd = cd + "; " + prefix + " vsim -do \"" + cmd + " +acc\""
|
|
||||||
else: # launch Questa in batch mode
|
|
||||||
cmd = cd + "; " + prefix + " vsim -c -do \"" + cmd + "\""
|
|
||||||
print("Running Questa with command: " + cmd)
|
|
||||||
os.system(cmd)
|
|
||||||
elif (args.sim == "verilator"):
|
|
||||||
# PWD=${WALLY}/sim CONFIG=rv64gc TESTSUITE=arch64i
|
|
||||||
print(f"Running Verilator on {args.config} {args.testsuite}")
|
|
||||||
if (args.coverage):
|
|
||||||
print("Coverage option not available for Verilator")
|
|
||||||
exit(1)
|
|
||||||
if (args.gui):
|
|
||||||
print("GUI option not available for Verilator")
|
|
||||||
exit(1)
|
|
||||||
os.system(f"/usr/bin/make -C {regressionDir}/verilator WALLYCONF={args.config} TEST={args.testsuite} TESTBENCH={args.tb} EXTRA_ARGS='{args.args}'")
|
|
||||||
elif (args.sim == "vcs"):
|
|
||||||
print(f"Running VCS on " + args.config + " " + args.testsuite)
|
|
||||||
if (args.gui):
|
|
||||||
args.args += "gui"
|
|
||||||
elif (args.coverage):
|
|
||||||
args.args += "coverage"
|
|
||||||
cmd = cd + "; ./run_vcs " + args.config + " " + args.testsuite + " " + args.args
|
|
||||||
print(cmd)
|
|
||||||
os.system(cmd)
|
|
||||||
|
14
src/cache/cache.sv
vendored
14
src/cache/cache.sv
vendored
@ -29,7 +29,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module cache import cvw::*; #(parameter cvw_t P,
|
module cache import cvw::*; #(parameter cvw_t P,
|
||||||
parameter PA_BITS, XLEN, LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTERVAL, READ_ONLY_CACHE) (
|
parameter PA_BITS, XLEN, LINELEN, NUMSETS, NUMWAYS, LOGBWPL, WORDLEN, MUXINTERVAL, READ_ONLY_CACHE) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic Stall, // Stall the cache, preventing new accesses. In-flight access finished but does not return to READY
|
input logic Stall, // Stall the cache, preventing new accesses. In-flight access finished but does not return to READY
|
||||||
@ -42,7 +42,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
input logic [11:0] NextSet, // Virtual address, but we only use the lower 12 bits.
|
input logic [11:0] NextSet, // Virtual address, but we only use the lower 12 bits.
|
||||||
input logic [PA_BITS-1:0] PAdr, // Physical address
|
input logic [PA_BITS-1:0] PAdr, // Physical address
|
||||||
input logic [(WORDLEN-1)/8:0] ByteMask, // Which bytes to write (D$ only)
|
input logic [(WORDLEN-1)/8:0] ByteMask, // Which bytes to write (D$ only)
|
||||||
input logic [WORDLEN-1:0] CacheWriteData, // Data to write to cache (D$ only)
|
input logic [WORDLEN-1:0] WriteData, // Data to write to cache (D$ only)
|
||||||
output logic CacheCommitted, // Cache has started bus operation that shouldn't be interrupted
|
output logic CacheCommitted, // Cache has started bus operation that shouldn't be interrupted
|
||||||
output logic CacheStall, // Cache stalls pipeline during multicycle operation
|
output logic CacheStall, // Cache stalls pipeline during multicycle operation
|
||||||
output logic [WORDLEN-1:0] ReadDataWord, // Word read from cache (goes to CPU and bus)
|
output logic [WORDLEN-1:0] ReadDataWord, // Word read from cache (goes to CPU and bus)
|
||||||
@ -63,12 +63,12 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
// Cache parameters
|
// Cache parameters
|
||||||
localparam LINEBYTELEN = LINELEN/8; // Line length in bytes
|
localparam LINEBYTELEN = LINELEN/8; // Line length in bytes
|
||||||
localparam OFFSETLEN = $clog2(LINEBYTELEN); // Number of bits in offset field
|
localparam OFFSETLEN = $clog2(LINEBYTELEN); // Number of bits in offset field
|
||||||
localparam SETLEN = $clog2(NUMLINES); // Number of set bits
|
localparam SETLEN = $clog2(NUMSETS); // Number of set bits
|
||||||
localparam SETTOP = SETLEN+OFFSETLEN; // Number of set plus offset bits
|
localparam SETTOP = SETLEN+OFFSETLEN; // Number of set plus offset bits
|
||||||
localparam TAGLEN = PA_BITS - SETTOP; // Number of tag bits
|
localparam TAGLEN = PA_BITS - SETTOP; // Number of tag bits
|
||||||
localparam CACHEWORDSPERLINE = LINELEN/WORDLEN;// Number of words in cache line
|
localparam CACHEWORDSPERLINE = LINELEN/WORDLEN;// Number of words in cache line
|
||||||
localparam LOGCWPL = $clog2(CACHEWORDSPERLINE);// Log2 of ^
|
localparam LOGCWPL = $clog2(CACHEWORDSPERLINE);// Log2 of ^
|
||||||
localparam FLUSHADRTHRESHOLD = NUMLINES - 1; // Used to determine when flush is complete
|
localparam FLUSHADRTHRESHOLD = NUMSETS - 1; // Used to determine when flush is complete
|
||||||
localparam LOGLLENBYTES = $clog2(WORDLEN/8); // Number of bits to address a word
|
localparam LOGLLENBYTES = $clog2(WORDLEN/8); // Number of bits to address a word
|
||||||
|
|
||||||
|
|
||||||
@ -119,14 +119,14 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
AdrSelMuxSelTag, CacheSetTag);
|
AdrSelMuxSelTag, CacheSetTag);
|
||||||
|
|
||||||
// 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, NUMSETS, LINELEN, TAGLEN, OFFSETLEN, SETLEN, READ_ONLY_CACHE) CacheWays[NUMWAYS-1:0](
|
||||||
.clk, .reset, .CacheEn, .CacheSetData, .CacheSetTag, .PAdr, .LineWriteData, .LineByteMask, .SelVictim,
|
.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);
|
||||||
|
|
||||||
// Select victim way for associative caches
|
// Select victim way for associative caches
|
||||||
if(NUMWAYS > 1) begin:vict
|
if(NUMWAYS > 1) begin:vict
|
||||||
cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMLINES) cacheLRU(
|
cacheLRU #(NUMWAYS, SETLEN, OFFSETLEN, NUMSETS) cacheLRU(
|
||||||
.clk, .reset, .FlushStage, .CacheEn, .HitWay, .ValidWay, .VictimWay, .CacheSetData, .CacheSetTag, .LRUWriteEn,
|
.clk, .reset, .FlushStage, .CacheEn, .HitWay, .ValidWay, .VictimWay, .CacheSetData, .CacheSetTag, .LRUWriteEn,
|
||||||
.SetValid, .ClearValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache);
|
.SetValid, .ClearValid, .PAdr(PAdr[SETTOP-1:OFFSETLEN]), .InvalidateCache);
|
||||||
end else
|
end else
|
||||||
@ -184,7 +184,7 @@ module cache import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
// 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(WriteData[(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 = SetDirty ? DemuxedByteMask : '1;
|
assign LineByteMask = SetDirty ? DemuxedByteMask : '1;
|
||||||
|
6
src/cache/cacheLRU.sv
vendored
6
src/cache/cacheLRU.sv
vendored
@ -29,7 +29,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module cacheLRU
|
module cacheLRU
|
||||||
#(parameter NUMWAYS = 4, SETLEN = 9, OFFSETLEN = 5, NUMLINES = 128) (
|
#(parameter NUMWAYS = 4, SETLEN = 9, OFFSETLEN = 5, NUMSETS = 128) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic FlushStage,
|
input logic FlushStage,
|
||||||
@ -48,7 +48,7 @@ module cacheLRU
|
|||||||
|
|
||||||
localparam LOGNUMWAYS = $clog2(NUMWAYS);
|
localparam LOGNUMWAYS = $clog2(NUMWAYS);
|
||||||
|
|
||||||
logic [NUMWAYS-2:0] LRUMemory [NUMLINES-1:0];
|
logic [NUMWAYS-2:0] LRUMemory [NUMSETS-1:0];
|
||||||
logic [NUMWAYS-2:0] CurrLRU;
|
logic [NUMWAYS-2:0] CurrLRU;
|
||||||
logic [NUMWAYS-2:0] NextLRU;
|
logic [NUMWAYS-2:0] NextLRU;
|
||||||
logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
|
logic [LOGNUMWAYS-1:0] HitWayEncoded, Way;
|
||||||
@ -146,7 +146,7 @@ module cacheLRU
|
|||||||
// Move to = to keep Verilator happy and simulator running fast
|
// Move to = to keep Verilator happy and simulator running fast
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset | (InvalidateCache & ~FlushStage))
|
if (reset | (InvalidateCache & ~FlushStage))
|
||||||
for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = '0; // exclusion-tag: initialize
|
for (int set = 0; set < NUMSETS; set++) LRUMemory[set] = '0; // exclusion-tag: initialize
|
||||||
else if(CacheEn) begin
|
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
|
// 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 = NextLRU;
|
if(LRUWriteEn & (PAdr == CacheSetTag)) CurrLRU = NextLRU;
|
||||||
|
18
src/cache/cacheway.sv
vendored
18
src/cache/cacheway.sv
vendored
@ -29,14 +29,14 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module cacheway import cvw::*; #(parameter cvw_t P,
|
module cacheway import cvw::*; #(parameter cvw_t P,
|
||||||
parameter PA_BITS, XLEN, NUMLINES=512, LINELEN = 256, TAGLEN = 26,
|
parameter PA_BITS, XLEN, NUMSETS=512, LINELEN = 256, TAGLEN = 26,
|
||||||
OFFSETLEN = 5, INDEXLEN = 9, READ_ONLY_CACHE = 0) (
|
OFFSETLEN = 5, INDEXLEN = 9, READ_ONLY_CACHE = 0) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations)
|
input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations)
|
||||||
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 [$clog2(NUMLINES)-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
input logic [$clog2(NUMSETS)-1:0] CacheSetData, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||||
input logic [$clog2(NUMLINES)-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
input logic [$clog2(NUMSETS)-1:0] CacheSetTag, // Cache address, the output of the address select mux, NextAdr, PAdr, or FlushAdr
|
||||||
input logic [PA_BITS-1:0] PAdr, // Physical address
|
input logic [PA_BITS-1:0] PAdr, // Physical address
|
||||||
input logic [LINELEN-1:0] LineWriteData, // Final data written to cache (D$ only)
|
input logic [LINELEN-1:0] LineWriteData, // Final data written to cache (D$ only)
|
||||||
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
|
||||||
@ -63,8 +63,8 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
localparam LOGXLENBYTES = $clog2(XLEN/8);
|
localparam LOGXLENBYTES = $clog2(XLEN/8);
|
||||||
localparam BYTESPERWORD = XLEN/8;
|
localparam BYTESPERWORD = XLEN/8;
|
||||||
|
|
||||||
logic [NUMLINES-1:0] ValidBits;
|
logic [NUMSETS-1:0] ValidBits;
|
||||||
logic [NUMLINES-1:0] DirtyBits;
|
logic [NUMSETS-1:0] DirtyBits;
|
||||||
logic [LINELEN-1:0] ReadDataLine;
|
logic [LINELEN-1:0] ReadDataLine;
|
||||||
logic [TAGLEN-1:0] ReadTag;
|
logic [TAGLEN-1:0] ReadTag;
|
||||||
logic Dirty;
|
logic Dirty;
|
||||||
@ -112,7 +112,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
// Tag Array
|
// Tag Array
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
|
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMSETS), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
|
||||||
.addr(CacheSetTag), .dout(ReadTag),
|
.addr(CacheSetTag), .dout(ReadTag),
|
||||||
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
||||||
|
|
||||||
@ -136,12 +136,12 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
|
|
||||||
for(words = 0; words < NUMSRAM; words++) begin: word
|
for(words = 0; words < NUMSRAM; words++) begin: word
|
||||||
if (READ_ONLY_CACHE) begin:wordram // no byte-enable needed for i$.
|
if (READ_ONLY_CACHE) begin:wordram // no byte-enable needed for i$.
|
||||||
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(P.CACHE_SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSetData),
|
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMSETS), .WIDTH(P.CACHE_SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSetData),
|
||||||
.dout(ReadDataLine[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
.dout(ReadDataLine[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
||||||
.din(LineWriteData[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
.din(LineWriteData[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
||||||
.we(SelectedWriteWordEn));
|
.we(SelectedWriteWordEn));
|
||||||
end else begin:wordram // D$ needs byte enables
|
end else begin:wordram // D$ needs byte enables
|
||||||
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(P.CACHE_SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSetData),
|
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMSETS), .WIDTH(P.CACHE_SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSetData),
|
||||||
.dout(ReadDataLine[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
.dout(ReadDataLine[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
||||||
.din(LineWriteData[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
.din(LineWriteData[P.CACHE_SRAMLEN*(words+1)-1:P.CACHE_SRAMLEN*words]),
|
||||||
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
||||||
@ -173,7 +173,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||||||
if (!READ_ONLY_CACHE) begin:dirty
|
if (!READ_ONLY_CACHE) begin:dirty
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
// reset is optional. Consider merging with TAG array in the future.
|
// reset is optional. Consider merging with TAG array in the future.
|
||||||
//if (reset) DirtyBits <= {NUMLINES{1'b0}};
|
//if (reset) DirtyBits <= {NUMSETS{1'b0}};
|
||||||
if(CacheEn) begin
|
if(CacheEn) begin
|
||||||
Dirty <= DirtyBits[CacheSetTag];
|
Dirty <= DirtyBits[CacheSetTag];
|
||||||
if((SetDirtyWay | ClearDirtyWay) & ~FlushStage) DirtyBits[CacheSetData] <= SetDirtyWay; // exclusion-tag: cache UpdateDirty
|
if((SetDirtyWay | ClearDirtyWay) & ~FlushStage) DirtyBits[CacheSetData] <= SetDirtyWay; // exclusion-tag: cache UpdateDirty
|
||||||
|
@ -239,7 +239,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
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),
|
.NUMSETS(P.ICACHE_WAYSIZEINBYTES*8/P.ICACHE_LINELENINBITS),
|
||||||
.NUMWAYS(P.ICACHE_NUMWAYS), .LOGBWPL(LOGBWPL), .WORDLEN(32), .MUXINTERVAL(16), .READ_ONLY_CACHE(1))
|
.NUMWAYS(P.ICACHE_NUMWAYS), .LOGBWPL(LOGBWPL), .WORDLEN(32), .MUXINTERVAL(16), .READ_ONLY_CACHE(1))
|
||||||
icache(.clk, .reset, .FlushStage(FlushD), .Stall(GatedStallD),
|
icache(.clk, .reset, .FlushStage(FlushD), .Stall(GatedStallD),
|
||||||
.FetchBuffer, .CacheBusAck(ICacheBusAck),
|
.FetchBuffer, .CacheBusAck(ICacheBusAck),
|
||||||
@ -249,7 +249,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
.SelHPTW('0),
|
.SelHPTW('0),
|
||||||
.CacheMiss(ICacheMiss), .CacheAccess(ICacheAccess),
|
.CacheMiss(ICacheMiss), .CacheAccess(ICacheAccess),
|
||||||
.ByteMask('0), .BeatCount('0), .SelBusBeat('0),
|
.ByteMask('0), .BeatCount('0), .SelBusBeat('0),
|
||||||
.CacheWriteData('0),
|
.WriteData('0),
|
||||||
.CacheRW(CacheRWF),
|
.CacheRW(CacheRWF),
|
||||||
.FlushCache('0),
|
.FlushCache('0),
|
||||||
.NextSet(PCSpillNextF[11:0]),
|
.NextSet(PCSpillNextF[11:0]),
|
||||||
|
@ -329,13 +329,13 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||||||
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), .NUMSETS(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(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,
|
.WriteData(LSUWriteDataSpillM), .SelHPTW,
|
||||||
.CacheStall, .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
|
.CacheStall, .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
|
||||||
.CacheCommitted(DCacheCommittedM),
|
.CacheCommitted(DCacheCommittedM),
|
||||||
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
|
.CacheBusAdr(DCacheBusAdr), .ReadDataWord(DCacheReadDataWordM),
|
||||||
|
Loading…
Reference in New Issue
Block a user