mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
a39e14663d
@ -1,9 +1,5 @@
|
||||
echo "Warning: this script will only work if your repo is on Tera"
|
||||
ln -s /courses/e190ax/buildroot_boot/parsedCSRs.txt parsedCSRs.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/parsedMemRead.txt parsedMemRead.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/parsedMemWrite.txt parsedMemWrite.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/parsedPC.txt parsedPC.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/parsedRegs.txt parsedRegs.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/all.txt all.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/bootmem.txt bootmem.txt
|
||||
ln -s /courses/e190ax/buildroot_boot/ram.txt ram.txt
|
||||
echo "Done!"
|
||||
|
@ -1,10 +1,6 @@
|
||||
# This could be nice to use if you want to mess with the testvectors
|
||||
# without corrupting the stable copies on Tera.
|
||||
unlink parsedCSRs.txt
|
||||
unlink parsedMemRead.txt
|
||||
unlink parsedMemWrite.txt
|
||||
unlink parsedPC.txt
|
||||
unlink parsedRegs.txt
|
||||
unlink all.txt
|
||||
unlink bootmem.txt
|
||||
unlink ram.txt
|
||||
echo "Done!"
|
||||
|
33
wally-pipelined/linux-testgen/testvector-generation/GenerateCheckpoint.sh
Executable file
33
wally-pipelined/linux-testgen/testvector-generation/GenerateCheckpoint.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
# Oftentimes this script runs so long you'll go to sleep.
|
||||
# But you don't want the script to die when your computer goes to sleep.
|
||||
# So consider invoking this with nohup (i.e. "nohup ./logAllBuildroot.sh")
|
||||
# You can run "tail -f nohup.out" to see what would've
|
||||
# outputted to the terminal if you didn't use nohup
|
||||
|
||||
# use on tera.
|
||||
customQemu="/courses/e190ax/qemu_sim/rv64_initrd/qemu_experimental/qemu/build/qemu-system-riscv64"
|
||||
# use on other systems
|
||||
#customQemu="qemu-system-riscv64"
|
||||
|
||||
instrs=8500000
|
||||
|
||||
imageDir="../buildroot-image-output"
|
||||
outDir="../linux-testvectors/checkpoint$instrs"
|
||||
intermedDir="$outDir/intermediate-outputs"
|
||||
|
||||
|
||||
read -p "This scripts is going to create a checkpoint at $instrs instrs.
|
||||
Is that what you wanted? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
mkdir -p $outDir
|
||||
mkdir -p $intermedDir
|
||||
($customQemu -M virt -nographic -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio -rtc clock=vm -icount shift=1 -d nochain,cpu,in_asm -serial /dev/null -singlestep -gdb tcp::1240 -S 2>&1 1>&2 | ./parse_qemu.py | ./parseNew.py | ./remove_dup.awk > $intermedDir/rawTrace.txt) & riscv64-unknown-elf-gdb -x ./checkpoint.gdb -ex "createCheckpoint $instrs \"$intermedDir\""
|
||||
./fix_mem.py "$intermedDir/ramGDB.txt" "$outDir/ram.txt"
|
||||
./parseState.py "$outDir"
|
||||
else
|
||||
echo "You can change the number of instructions by editing the \"instrs\" variable in this script."
|
||||
echo "Have a nice day!"
|
||||
fi
|
53
wally-pipelined/linux-testgen/testvector-generation/checkpoint.gdb
Executable file
53
wally-pipelined/linux-testgen/testvector-generation/checkpoint.gdb
Executable file
@ -0,0 +1,53 @@
|
||||
define createCheckpoint
|
||||
# GDB config
|
||||
set pagination off
|
||||
set logging overwrite on
|
||||
set logging redirect on
|
||||
set confirm off
|
||||
|
||||
# QEMU must also use TCP port 1240
|
||||
target extended-remote :1240
|
||||
|
||||
# Argument Parsing
|
||||
set $statePath=$arg1
|
||||
set $ramPath=$arg1
|
||||
eval "set $statePath = \"%s/stateGDB.txt\"", $statePath
|
||||
eval "set $ramPath = \"%s/ramGDB.txt\"", $ramPath
|
||||
|
||||
# Symbol file
|
||||
file ../buildroot-image-output/vmlinux
|
||||
|
||||
# Step over reset vector into actual code
|
||||
stepi 1000
|
||||
# Set breakpoint for where to stop
|
||||
b do_idle
|
||||
# Proceed to checkpoint
|
||||
printf "GDB proceeding to checkpoint at %d instrs\n", $arg0
|
||||
stepi $arg0-1000
|
||||
|
||||
printf "Reached checkpoint at %d instrs\n", $arg0
|
||||
|
||||
# Log all registers to a file
|
||||
printf "GDB storing state to %s\n", $statePath
|
||||
set logging file $statePath
|
||||
set logging on
|
||||
info all-registers
|
||||
set logging off
|
||||
|
||||
# Log main memory to a file
|
||||
printf "GDB storing RAM to %s\n", $ramPath
|
||||
set logging file ../linux-testvectors/intermediate-outputs/ramGDB.txt
|
||||
set logging on
|
||||
x/134217728xb 0x80000000
|
||||
set logging off
|
||||
|
||||
# Continue to checkpoint; stop on the 3rd time
|
||||
# Should reach login prompt by then
|
||||
printf "GDB continuing execution to login prompt\n"
|
||||
ignore 1 2
|
||||
c
|
||||
|
||||
printf "GDB reached login prompt!\n"
|
||||
kill
|
||||
q
|
||||
end
|
@ -6,9 +6,10 @@ if len(sys.argv) != 3:
|
||||
inputFile = sys.argv[1]
|
||||
outputFile = sys.argv[2]
|
||||
if not os.path.exists(inputFile):
|
||||
sys.exit('Error input file '+inputFile+'not found')
|
||||
print('Translating '+os.path.basename(inputFile)+' to '+os.path.basename(outputFile))
|
||||
sys.exit('Error input file '+inputFile+' not found')
|
||||
print('Begin translating '+os.path.basename(inputFile)+' to '+os.path.basename(outputFile))
|
||||
with open(inputFile, 'r') as f:
|
||||
with open(outputFile, 'w') as w:
|
||||
for l in f:
|
||||
w.write(f'{"".join([x[2:] for x in l.split()[:0:-1]])}\n')
|
||||
print('Finished translating '+os.path.basename(inputFile)+' to '+os.path.basename(outputFile)+'!')
|
||||
|
@ -140,6 +140,7 @@ CurrentInstr = ['0', '0', None, 'other', {'zero': 0, 'ra': 0, 'sp': 0, 'gp': 0,
|
||||
lineNum = 0
|
||||
StartLine = 0
|
||||
EndLine = 0
|
||||
numInstrs = 0
|
||||
#instructions = []
|
||||
MemAdr = 0
|
||||
lines = []
|
||||
@ -195,6 +196,10 @@ for line in fileinput.input('-'):
|
||||
lines.clear()
|
||||
#instructions.append(MoveInstrToRegWriteLst)
|
||||
PrintInstr(MoveInstrToRegWriteLst, sys.stdout)
|
||||
numInstrs +=1
|
||||
if (numInstrs % 1e4 == 0):
|
||||
sys.stderr.write('Trace parser reached '+str(numInstrs/1.0e6)+' million instrs.\n')
|
||||
sys.stderr.flush()
|
||||
lineNum += 1
|
||||
|
||||
|
||||
|
79
wally-pipelined/linux-testgen/testvector-generation/parseState.py
Executable file
79
wally-pipelined/linux-testgen/testvector-generation/parseState.py
Executable file
@ -0,0 +1,79 @@
|
||||
#! /usr/bin/python3
|
||||
import sys
|
||||
|
||||
################
|
||||
# Helper Funcs #
|
||||
################
|
||||
|
||||
def tokenize(string):
|
||||
tokens = []
|
||||
token = ''
|
||||
whitespace = 0
|
||||
prevWhitespace = 0
|
||||
for char in string:
|
||||
prevWhitespace = whitespace
|
||||
whitespace = char in ' \t\n'
|
||||
if (whitespace):
|
||||
if ((not prevWhitespace) and (token != '')):
|
||||
tokens.append(token)
|
||||
token = ''
|
||||
else:
|
||||
token = token + char
|
||||
return tokens
|
||||
|
||||
#############
|
||||
# Main Code #
|
||||
#############
|
||||
print("Begin parsing state.")
|
||||
|
||||
# Parse Args
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit('Error parseState.py expects 1 arg:\n parseState.py <path_to_checkpoint_dir>')
|
||||
outDir = sys.argv[1]
|
||||
stateGDBpath = outDir+'/intermediate-outputs/stateGDB1K.txt'
|
||||
if not os.path.exists(stateGDBpath):
|
||||
sys.exit('Error input file '+stateGDBpath+'not found')
|
||||
|
||||
listCSRs = ['hpmcounter','pmpcfg','pmpaddr']
|
||||
singleCSRs = ['mip','mie','mscratch','mcause','mepc','mtvec','medeleg','mideleg','mcounteren','sscratch','scause','sepc','stvec','sedeleg','sideleg','scounteren','satp','mstatus']
|
||||
|
||||
# Initialize List CSR files to empty
|
||||
# (because later we'll open them in append mode)
|
||||
for csr in listCSRs:
|
||||
outFileName = 'checkpoint-'+csr.upper()
|
||||
outFile = open(outDir+outFileName, 'w')
|
||||
outFile.close()
|
||||
|
||||
# Initial State for Main Loop
|
||||
currState = 'regFile'
|
||||
regFileIndex = 0
|
||||
outFileName = 'checkpoint-regfile.txt'
|
||||
outFile = open(outDir+outFileName, 'w')
|
||||
|
||||
# Main Loop
|
||||
with open(stateGDBpath, 'r') as stateGDB:
|
||||
for line in stateGDB:
|
||||
line = tokenize(line)
|
||||
name = line[0]
|
||||
val = line[1][2:]
|
||||
if (currState == 'regFile'):
|
||||
if (regFileIndex == 0 and name != 'zero'):
|
||||
print('Whoops! Expected regFile registers to come first, starting with zero')
|
||||
exit(1)
|
||||
outFile.write(val+'\n')
|
||||
regFileIndex += 1
|
||||
if (regFileIndex == 32):
|
||||
outFile.close()
|
||||
currState = 'CSRs'
|
||||
elif (currState == 'CSRs'):
|
||||
if name in singleCSRs:
|
||||
outFileName = 'checkpoint-'+name.upper()
|
||||
outFile = open(outDir+outFileName, 'w')
|
||||
outFile.write(val+'\n')
|
||||
outFile.close()
|
||||
elif name.strip('0123456789') in listCSRs:
|
||||
outFileName = 'checkpoint-'+name.upper().strip('0123456789')
|
||||
outFile = open(outDir+outFileName, 'a')
|
||||
outFile.write(val+'\n')
|
||||
outFile.close()
|
||||
print("Finished parsing state!")
|
@ -25,6 +25,8 @@
|
||||
|
||||
`include "wally-config.vh"
|
||||
/* verilator lint_off DECLFILENAME */
|
||||
// Note that non-zero RESET_VAL's are only ever intended for simulation purposes (to start mid-execution from a checkpoint)
|
||||
|
||||
|
||||
// ordinary flip-flop
|
||||
module flop #(parameter WIDTH = 8) (
|
||||
@ -40,10 +42,11 @@ endmodule
|
||||
module flopr #(parameter WIDTH = 8) (
|
||||
input logic clk, reset,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q);
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 0;
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
else q <= #1 d;
|
||||
endmodule
|
||||
|
||||
@ -61,10 +64,11 @@ endmodule
|
||||
module flopenrc #(parameter WIDTH = 8) (
|
||||
input logic clk, reset, clear, en,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q);
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 0;
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
else if (en)
|
||||
if (clear) q <= #1 0;
|
||||
else q <= #1 d;
|
||||
@ -74,10 +78,11 @@ endmodule
|
||||
module flopenr #(parameter WIDTH = 8) (
|
||||
input logic clk, reset, en,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q);
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 0;
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
else if (en) q <= #1 d;
|
||||
endmodule
|
||||
|
||||
@ -99,10 +104,11 @@ module floprc #(parameter WIDTH = 8) (
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q);
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var RESET_VAL=0);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 0;
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
else
|
||||
if (clear) q <= #1 0;
|
||||
else q <= #1 d;
|
||||
|
@ -44,7 +44,13 @@ module regfile (
|
||||
// reset is intended for simulation only, not synthesis
|
||||
|
||||
always_ff @(negedge clk or posedge reset)
|
||||
if (reset) for(i=1; i<32; i++) rf[i] <= 0;
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-regfile.txt"}, rf);
|
||||
`else
|
||||
for(i=1; i<32; i++) rf[i] <= 0;
|
||||
`endif
|
||||
|
||||
else if (we3) rf[a3] <= wd3;
|
||||
|
||||
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
||||
|
@ -70,24 +70,24 @@ module csrc #(parameter
|
||||
// ... more counters
|
||||
//HPMCOUNTER31H = 12'hC9F
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
output logic IllegalCSRCAccessM
|
||||
);
|
||||
|
||||
generate
|
||||
@ -97,14 +97,22 @@ module csrc #(parameter
|
||||
logic [63:0] HPMCOUNTER3_REGW, HPMCOUNTER4_REGW; // add more performance counters here if desired
|
||||
logic [63:0] CYCLEPlusM, INSTRETPlusM;
|
||||
logic [63:0] HPMCOUNTER3PlusM, HPMCOUNTER4PlusM;
|
||||
// logic [`XLEN-1:0] NextTIMEM;
|
||||
// logic [`XLEN-1:0] NextTIMEM;
|
||||
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
|
||||
logic [`XLEN-1:0] NextHPMCOUNTER3M, NextHPMCOUNTER4M;
|
||||
logic WriteCYCLEM, WriteINSTRETM;
|
||||
logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M;
|
||||
logic [4:0] CounterNumM;
|
||||
logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW;
|
||||
logic InstrValidNotFlushedM;
|
||||
var [`COUNTERS-1:3][`XLEN-1:0] initHPMCOUNTER;
|
||||
logic InstrValidNotFlushedM;
|
||||
|
||||
initial
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-HPMCOUNTER.txt"}, initHPMCOUNTER);
|
||||
`else
|
||||
initHPMCOUNTER = {(`COUNTERS-3){`XLEN'b0}};
|
||||
`endif
|
||||
|
||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||
|
||||
@ -130,121 +138,116 @@ module csrc #(parameter
|
||||
//assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0];
|
||||
//assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0];
|
||||
|
||||
// parameterized number of additional counters
|
||||
if (`COUNTERS > 3) begin
|
||||
// parameterized number of additional counters
|
||||
if (`COUNTERS > 3) begin
|
||||
logic [`COUNTERS-1:3] WriteHPMCOUNTERM;
|
||||
logic [`COUNTERS-1:0] CounterEvent;
|
||||
logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3];
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3];
|
||||
genvar i;
|
||||
|
||||
// could replace special counters 0-2 with this loop for all counters
|
||||
assign CounterEvent[0] = 1'b1;
|
||||
assign CounterEvent[1] = 1'b0;
|
||||
if(`QEMU) begin
|
||||
assign CounterEvent[`COUNTERS-1:2] = 0;
|
||||
end else begin
|
||||
|
||||
logic LoadStallE, LoadStallM;
|
||||
|
||||
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(FlushE), .en(~StallE), .d(LoadStallD), .q(LoadStallE));
|
||||
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
|
||||
|
||||
assign CounterEvent[2] = InstrValidNotFlushedM;
|
||||
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
||||
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[11] = DCacheAccess & InstrValidNotFlushedM;
|
||||
assign CounterEvent[12] = DCacheMiss & InstrValidNotFlushedM;
|
||||
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
||||
end
|
||||
|
||||
for (i = 3; i < `COUNTERS; i = i+1) begin
|
||||
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
|
||||
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
|
||||
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
|
||||
else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
|
||||
//flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
|
||||
|
||||
if (`XLEN==32) begin
|
||||
logic [`COUNTERS-1:3] WriteHPMCOUNTERHM;
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:3];
|
||||
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||
assign WriteHPMCOUNTERHM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERHBASE + i);
|
||||
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
|
||||
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
|
||||
else if (~StallW) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
|
||||
//flopr #(`XLEN) HPMCOUNTERHreg[i](clk, reset, NextHPMCOUNTERHM[i], HPMCOUNTER_REGW[i][63:32]);
|
||||
end else begin
|
||||
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||
end
|
||||
if(`QEMU) assign CounterEvent[`COUNTERS-1:2] = 0;
|
||||
else begin
|
||||
logic LoadStallE, LoadStallM;
|
||||
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(FlushE), .en(~StallE), .d(LoadStallD), .q(LoadStallE));
|
||||
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
|
||||
|
||||
assign CounterEvent[2] = InstrValidNotFlushedM;
|
||||
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
||||
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[11] = DCacheAccess & InstrValidNotFlushedM;
|
||||
assign CounterEvent[12] = DCacheMiss & InstrValidNotFlushedM;
|
||||
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
|
||||
end
|
||||
end
|
||||
|
||||
for (i = 3; i < `COUNTERS; i = i+1) begin
|
||||
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
|
||||
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
|
||||
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 initHPMCOUNTER[i];
|
||||
else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
|
||||
//flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
|
||||
|
||||
if (`XLEN==32) begin
|
||||
logic [`COUNTERS-1:3] WriteHPMCOUNTERHM;
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:3];
|
||||
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||
assign WriteHPMCOUNTERHM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERHBASE + i);
|
||||
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
|
||||
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
|
||||
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
|
||||
else if (~StallW) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
|
||||
//flopr #(`XLEN) HPMCOUNTERHreg[i](clk, reset, NextHPMCOUNTERHM[i], HPMCOUNTER_REGW[i][63:32]);
|
||||
end else begin
|
||||
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Write / update counters
|
||||
// Only the Machine mode versions of the counter CSRs are writable
|
||||
if (`XLEN==64) begin// 64-bit counters
|
||||
// flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
|
||||
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
|
||||
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
|
||||
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
|
||||
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
|
||||
end else begin // 32-bit low and high counters
|
||||
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
|
||||
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
|
||||
logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
|
||||
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
|
||||
if (`XLEN==64) begin// 64-bit counters
|
||||
// flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
|
||||
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
|
||||
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
|
||||
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
|
||||
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
|
||||
end else begin // 32-bit low and high counters
|
||||
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
|
||||
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
|
||||
logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
|
||||
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
|
||||
|
||||
// Write Enables
|
||||
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
|
||||
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
|
||||
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
|
||||
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
|
||||
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
|
||||
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
|
||||
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
|
||||
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
|
||||
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
|
||||
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
|
||||
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
|
||||
// Write Enables
|
||||
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
|
||||
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
|
||||
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
|
||||
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
|
||||
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
|
||||
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
|
||||
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
|
||||
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
|
||||
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
|
||||
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
|
||||
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
|
||||
|
||||
// Counter CSRs
|
||||
// flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
|
||||
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW[31:0]);
|
||||
flopr #(32) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]);
|
||||
//flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]);
|
||||
//flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
|
||||
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
|
||||
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]);
|
||||
flopr #(32) INSTRETHreg(clk, reset, NextINSTRETHM, INSTRET_REGW[63:32]);
|
||||
//flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]);
|
||||
//flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
|
||||
end
|
||||
// Counter CSRs
|
||||
// flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
|
||||
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW[31:0]);
|
||||
flopr #(32) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]);
|
||||
// flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]);
|
||||
// flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
|
||||
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock***
|
||||
// flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
|
||||
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]);
|
||||
flopr #(32) INSTRETHreg(clk, reset, NextINSTRETHM, INSTRET_REGW[63:32]);
|
||||
//flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]);
|
||||
//flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
|
||||
end
|
||||
|
||||
// eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot!
|
||||
// run TIME off asynchronous reference clock
|
||||
// synchronize write enable to TIME
|
||||
// four phase handshake to synchronize reads from TIME
|
||||
// eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot!
|
||||
// run TIME off asynchronous reference clock
|
||||
// synchronize write enable to TIME
|
||||
// four phase handshake to synchronize reads from TIME
|
||||
|
||||
// interrupt on timer compare
|
||||
// ability to disable optional CSRs
|
||||
// interrupt on timer compare
|
||||
// ability to disable optional CSRs
|
||||
|
||||
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
|
||||
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
|
||||
if (`XLEN==64) // 64-bit counter reads
|
||||
always_comb
|
||||
if (PrivilegeModeW == `M_MODE ||
|
||||
MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
|
||||
if (PrivilegeModeW == `M_MODE || MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
|
||||
IllegalCSRCAccessM = 0;
|
||||
if (CSRAdrM >= MHPMCOUNTERBASE+3 && CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-MHPMCOUNTERBASE];
|
||||
else if (CSRAdrM >= HPMCOUNTERBASE+3 && CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-HPMCOUNTERBASE];
|
||||
@ -309,7 +312,7 @@ module csrc #(parameter
|
||||
IllegalCSRCAccessM = 1; // no privileges for this csr
|
||||
CSRCReadValM = 0;
|
||||
end
|
||||
end else begin
|
||||
end else begin // not `ZICOUNTERS_SUPPORTED
|
||||
assign CSRCReadValM = 0;
|
||||
assign IllegalCSRCAccessM = 1;
|
||||
end
|
||||
@ -356,20 +359,20 @@ module csrc #(parameter
|
||||
MPHMEVENTBASE = 12'h320,
|
||||
HPMCOUNTERBASE = 12'hC00,
|
||||
HPMCOUNTERHBASE = 12'hC80,
|
||||
)(input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
)(input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM);
|
||||
output logic IllegalCSRCAccessM);
|
||||
|
||||
// counters
|
||||
|
||||
|
@ -79,14 +79,24 @@ module csri #(parameter
|
||||
assign SIP_WRITE_MASK = 12'h000;
|
||||
end
|
||||
always @(posedge clk, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
|
||||
if (reset) IP_REGW_writeable <= 10'b0;
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIP.txt"}, IP_REGW_writeable);
|
||||
`else
|
||||
IP_REGW_writeable <= 10'b0;
|
||||
`endif
|
||||
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
||||
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
|
||||
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
|
||||
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
|
||||
end
|
||||
always @(posedge clk, posedge reset) begin
|
||||
if (reset) IE_REGW <= 12'b0;
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIE.txt"}, IE_REGW);
|
||||
`else
|
||||
IE_REGW <= 12'b0;
|
||||
`endif
|
||||
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
|
||||
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
|
||||
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
|
||||
|
@ -85,15 +85,45 @@ module csrm #(parameter
|
||||
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||
logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW;
|
||||
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
var [`XLEN-1:0] initMSCRATCH, initMCAUSE, initMEPC, initMTVEC, initMEDELEG, initMIDELEG;
|
||||
var [31:0] initMCOUNTEREN, initMCOUNTINHIBIT;
|
||||
var [`PMP_ENTRIES-1:0][7:0] initPMPCFG_ARRAY;
|
||||
var [`PMP_ENTRIES-1:0][`XLEN-1:0] initPMPADDR_ARRAY;
|
||||
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
|
||||
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
|
||||
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
|
||||
|
||||
localparam MISA_26 = (`MISA) & 32'h03ffffff;
|
||||
|
||||
initial begin
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MSCRATCH.txt"}, initMSCRATCH);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MCAUSE.txt"}, initMCAUSE);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MEPC.txt"}, initMEPC);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MTVEC.txt"}, initMTVEC);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MEDELEG.txt"}, initMEDELEG);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIDELEG.txt"}, initMIDELEG);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MCOUNTEREN.txt"}, initMCOUNTEREN);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-PMPCFG.txt"}, initPMPCFG_ARRAY);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-PMPADDR.txt"}, initPMPADDR_ARRAY);
|
||||
`else
|
||||
initMSCRATCH = `XLEN'b0;
|
||||
initMCAUSE = `XLEN'b0;
|
||||
initMEPC = `XLEN'b0;
|
||||
initMTVEC = `XLEN'b0;
|
||||
initMEDELEG = `XLEN'b0;
|
||||
initMIDELEG = `XLEN'b0;
|
||||
initMCOUNTEREN = 32'b0;
|
||||
initMCOUNTINHIBIT = 32'b0;
|
||||
initPMPCFG_ARRAY = {`PMP_ENTRIES{8'b0}};
|
||||
initPMPADDR_ARRAY = {`PMP_ENTRIES{`XLEN'b0}};
|
||||
`endif
|
||||
end
|
||||
|
||||
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
|
||||
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]};
|
||||
|
||||
@ -115,33 +145,31 @@ module csrm #(parameter
|
||||
assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID);
|
||||
|
||||
// CSRs
|
||||
flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0
|
||||
flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, initMTVEC, MTVEC_REGW); //busybear: changed reset value to 0
|
||||
generate
|
||||
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist
|
||||
flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, `XLEN'b0, MEDELEG_REGW);
|
||||
flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, `XLEN'b0, MIDELEG_REGW);
|
||||
flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, initMEDELEG, MEDELEG_REGW);
|
||||
flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, initMIDELEG, MIDELEG_REGW);
|
||||
end else begin
|
||||
assign MEDELEG_REGW = 0;
|
||||
assign MIDELEG_REGW = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// flopenl #(`XLEN) MIPreg(clk, reset, WriteMIPM, CSRWriteValM, zero, MIP_REGW);
|
||||
// flopenl #(`XLEN) MIEreg(clk, reset, WriteMIEM, CSRWriteValM, zero, MIE_REGW);
|
||||
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
|
||||
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
|
||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
|
||||
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW, initMSCRATCH);
|
||||
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW, initMEPC);
|
||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW, initMCAUSE);
|
||||
if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
|
||||
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
|
||||
generate
|
||||
if (`BUSYBEAR == 1)
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW);
|
||||
else if (`BUILDROOT == 1)
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'h0, MCOUNTEREN_REGW);
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], initMCOUNTEREN, MCOUNTEREN_REGW);
|
||||
else
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW);
|
||||
endgenerate
|
||||
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], 32'h0, MCOUNTINHIBIT_REGW);
|
||||
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], initMCOUNTINHIBIT, MCOUNTINHIBIT_REGW);
|
||||
|
||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||
|
||||
@ -158,14 +186,14 @@ module csrm #(parameter
|
||||
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
|
||||
|
||||
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
|
||||
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
|
||||
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i], initPMPADDR_ARRAY[i]);
|
||||
if (`XLEN==64) begin
|
||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
|
||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
|
||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i], initPMPCFG_ARRAY[i]);
|
||||
end else begin
|
||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
|
||||
// assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW;
|
||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
|
||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i], initPMPCFG_ARRAY[i]);
|
||||
// flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]);
|
||||
end
|
||||
end
|
||||
|
@ -74,6 +74,30 @@ module csrs #(parameter
|
||||
logic WriteSSCRATCHM, WriteSEPCM;
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW;
|
||||
var [`XLEN-1:0] initSSCRATCH, initSCAUSE, initSEPC, initSTVEC, initSEDELEG, initSIDELEG, initSATP;
|
||||
var [31:0] initSCOUNTEREN;
|
||||
|
||||
initial begin
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SSCRATCH.txt"}, initSSCRATCH);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SCAUSE.txt"}, initSCAUSE);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SEPC.txt"}, initSEPC);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-STVEC.txt"}, initSTVEC);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SEDELEG.txt"}, initSEDELEG);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SIDELEG.txt"}, initSIDELEG);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SCOUNTEREN.txt"}, initSCOUNTEREN);
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SATP.txt"}, initSATP);
|
||||
`else
|
||||
initSSCRATCH = `XLEN'b0;
|
||||
initSCAUSE = `XLEN'b0;
|
||||
initSEPC = `XLEN'b0;
|
||||
initSTVEC = `XLEN'b0;
|
||||
initSEDELEG = `XLEN'b0;
|
||||
initSIDELEG = `XLEN'b0;
|
||||
initSCOUNTEREN = 32'b0;
|
||||
initSATP = `XLEN'b0;
|
||||
`endif
|
||||
end
|
||||
|
||||
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW;
|
||||
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW;
|
||||
@ -85,28 +109,28 @@ module csrs #(parameter
|
||||
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW;
|
||||
|
||||
// CSRs
|
||||
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `XLEN'b0, STVEC_REGW); //busybear: change reset to 0
|
||||
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
|
||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
|
||||
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, `XLEN'b0, SCAUSE_REGW);
|
||||
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, initSTVEC, STVEC_REGW); //busybear: change reset to 0
|
||||
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW, initSSCRATCH);
|
||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW, initSEPC);
|
||||
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, initSCAUSE, SCAUSE_REGW);
|
||||
if(`QEMU) assign STVAL_REGW = `XLEN'b0;
|
||||
else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
|
||||
if (`MEM_VIRTMEM)
|
||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW, initSATP);
|
||||
else
|
||||
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
|
||||
if (`BUSYBEAR == 1)
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
|
||||
else if (`BUILDROOT == 1)
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'h0, SCOUNTEREN_REGW);
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], initSCOUNTEREN, SCOUNTEREN_REGW);
|
||||
else
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW);
|
||||
if (`N_SUPPORTED) begin
|
||||
logic WriteSEDELEGM, WriteSIDELEGM;
|
||||
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
|
||||
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
|
||||
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, `XLEN'b0, SEDELEG_REGW);
|
||||
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, `XLEN'b0, SIDELEG_REGW);
|
||||
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, initSEDELEG, SEDELEG_REGW);
|
||||
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, initSIDELEG, SIDELEG_REGW);
|
||||
end else begin
|
||||
assign SEDELEG_REGW = 0;
|
||||
assign SIDELEG_REGW = 0;
|
||||
|
@ -46,6 +46,15 @@ module csrsr (
|
||||
logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS, STATUS_FS_INT, STATUS_MPP_NEXT;
|
||||
logic STATUS_MPIE, STATUS_SPIE, STATUS_UPIE, STATUS_UIE;
|
||||
|
||||
var [`XLEN-1:0] initMSTATUS;
|
||||
initial begin
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MSTATUS.txt"}, initMSTATUS);
|
||||
`else
|
||||
initMSTATUS = `XLEN'b0;
|
||||
`endif
|
||||
end
|
||||
|
||||
// STATUS REGISTER FIELD
|
||||
// See Privileged Spec Section 3.1.6
|
||||
// Lower privilege status registers are a subset of the full status register
|
||||
@ -108,23 +117,33 @@ module csrsr (
|
||||
|
||||
// registers for STATUS bits
|
||||
// complex register with reset, write enable, and the ability to update other bits in certain cases
|
||||
// these null things are needed to make the following LHS assignment legal; this is probably a crappy way of doing things
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) begin
|
||||
STATUS_TSR_INT <= #1 0;
|
||||
STATUS_TW_INT <= #1 0;
|
||||
STATUS_TVM_INT <= #1 0;
|
||||
STATUS_MXR_INT <= #1 0;
|
||||
STATUS_SUM_INT <= #1 0;
|
||||
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
||||
STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0
|
||||
STATUS_MPP <= #1 0; //`M_MODE;
|
||||
STATUS_SPP <= #1 0; //1'b1;
|
||||
STATUS_MPIE <= #1 0; //1;
|
||||
STATUS_SPIE <= #1 0; //`S_SUPPORTED;
|
||||
STATUS_UPIE <= #1 0; // `U_SUPPORTED;
|
||||
STATUS_MIE <= #1 0; // Per Priv 3.3
|
||||
STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
||||
STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
||||
//STATUS_TSR_INT <= #1 0;
|
||||
//STATUS_TW_INT <= #1 0;
|
||||
//STATUS_TVM_INT <= #1 0;
|
||||
//STATUS_MXR_INT <= #1 0;
|
||||
//STATUS_SUM_INT <= #1 0;
|
||||
//STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
|
||||
//STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0
|
||||
//STATUS_MPP <= #1 0; //`M_MODE;
|
||||
//STATUS_SPP <= #1 0; //1'b1;
|
||||
//STATUS_MPIE <= #1 0; //1;
|
||||
//STATUS_SPIE <= #1 0; //`S_SUPPORTED;
|
||||
//STATUS_UPIE <= #1 0; // `U_SUPPORTED;
|
||||
//STATUS_MIE <= #1 0; // Per Priv 3.3
|
||||
//STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
||||
//STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
||||
//
|
||||
// *** this assumes XLEN == 64.
|
||||
// I don't like using generates to respond to XLEN.
|
||||
// I'd rather have an XLEN64 so that we could use `ifdefs -- Ben 9/21
|
||||
{STATUS_TSR_INT,STATUS_TW_INT,STATUS_TVM_INT,STATUS_MXR_INT,STATUS_SUM_INT,STATUS_MPRV_INT} <= #1 initMSTATUS[22:17];
|
||||
{STATUS_FS_INT,STATUS_MPP} <= #1 initMSTATUS[14:11];
|
||||
{STATUS_SPP,STATUS_MPIE} <= #1 initMSTATUS[8:7];
|
||||
{STATUS_SPIE,STATUS_UPIE,STATUS_MIE} <= #1 initMSTATUS[5:3];
|
||||
{STATUS_SIE,STATUS_UIE} <= #1 initMSTATUS[1:0];
|
||||
end else if (~StallW) begin
|
||||
if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else;
|
||||
|
||||
|
@ -21,24 +21,33 @@
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// When letting Wally go for it, let wally generate own interrupts
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
//`define CHECKPOINT
|
||||
`define LINUX_CHECKPOINT "../linux-testgen/linux-testvectors/checkpoint1K"
|
||||
|
||||
`define DEBUG_TRACE 0
|
||||
`define DontHaltOnCSRMisMatch 1
|
||||
// Debug Levels
|
||||
// 0: don't check against QEMU
|
||||
// 1: print disagreements with QEMU, but only halt on PCW disagreements
|
||||
// 2: halt on any disagreement with QEMU except CSRs
|
||||
// 3: halt on all disagreements with QEMU
|
||||
// 4: print memory accesses whenever they happen
|
||||
// 5: print everything
|
||||
|
||||
module testbench();
|
||||
|
||||
parameter waveOnICount = `BUSYBEAR*140000 + `BUILDROOT*6779000; // # of instructions at which to turn on waves in graphical sim
|
||||
|
||||
parameter waveOnICount = `BUSYBEAR*140000 + `BUILDROOT*8700000; // # of instructions at which to turn on waves in graphical sim
|
||||
string ProgramAddrMapFile, ProgramLabelMapFile;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// DUT /////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
logic clk, reset;
|
||||
|
||||
logic [`AHBW-1:0] readDataExpected;
|
||||
logic [31:0] HADDR;
|
||||
logic [`AHBW-1:0] HWDATA;
|
||||
@ -51,7 +60,6 @@ module testbench();
|
||||
logic HCLK, HRESETn;
|
||||
logic [`AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
|
||||
logic [31:0] GPIOPinsIn;
|
||||
logic [31:0] GPIOPinsOut, GPIOPinsEn;
|
||||
logic UARTSin, UARTSout;
|
||||
@ -73,9 +81,11 @@ module testbench();
|
||||
// Testbench Core
|
||||
integer warningCount = 0;
|
||||
integer errorCount = 0;
|
||||
integer MIPexpected;
|
||||
// P, Instr Checking
|
||||
logic [`XLEN-1:0] PCW;
|
||||
integer data_file_all;
|
||||
string name;
|
||||
|
||||
// Write Back stage signals needed for trace compare, but don't actually
|
||||
// exist in CPU.
|
||||
@ -85,7 +95,6 @@ module testbench();
|
||||
logic checkInstrW;
|
||||
|
||||
//integer RegAdr;
|
||||
|
||||
integer fault;
|
||||
logic TrapW;
|
||||
|
||||
@ -129,17 +138,27 @@ module testbench();
|
||||
logic forcedInterrupt;
|
||||
integer NumCSRMIndex;
|
||||
integer NumCSRWIndex;
|
||||
integer NumCSRPostWIndex;
|
||||
// logic CurrentInterruptForce;
|
||||
integer NumCSRPostWIndex;
|
||||
logic [`XLEN-1:0] InstrCountW;
|
||||
|
||||
// -----------
|
||||
// Error Macro
|
||||
// -----------
|
||||
`define ERROR \
|
||||
errorCount +=1; \
|
||||
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount); \
|
||||
$stop;
|
||||
// ------
|
||||
// Macros
|
||||
// ------
|
||||
|
||||
`define CSRwarn(CSR) \
|
||||
begin \
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
|
||||
if (CSR != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin \
|
||||
$display("%tns, %d instrs: CSR %s = %016x, does not equal expected value %016x", $time, InstrCountW, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
|
||||
if(`DEBUG_TRACE >= 3) fault = 1; \
|
||||
end \
|
||||
end
|
||||
|
||||
`define checkEQ(NAME, VAL, EXPECTED) \
|
||||
if(VAL != EXPECTED) begin \
|
||||
$display("%tns, %d instrs: %s %x differs from expected %x", $time, InstrCountW, NAME, VAL, EXPECTED); \
|
||||
if ((NAME == "PCW") || (`DEBUG_TRACE >= 2)) fault = 1; \
|
||||
end
|
||||
|
||||
initial begin
|
||||
data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
||||
@ -149,16 +168,11 @@ module testbench();
|
||||
force dut.hart.priv.ExtIntM = 0;
|
||||
end
|
||||
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
initial begin
|
||||
CurrentInterruptForce = 1'b0;
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
assign checkInstrM = dut.hart.ieu.InstrValidM & ~dut.hart.priv.trap.InstrPageFaultM & ~dut.hart.priv.trap.InterruptM & ~dut.hart.StallM;
|
||||
// trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
||||
assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW;
|
||||
assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
||||
|
||||
// Additonal W stage registers
|
||||
flopenrc #(`XLEN) MemAdrWReg(clk, reset, dut.hart.FlushW, ~dut.hart.StallW, dut.hart.ieu.dp.MemAdrM, MemAdrW);
|
||||
flopenrc #(`XLEN) WriteDataWReg(clk, reset, dut.hart.FlushW, ~dut.hart.StallW, dut.hart.WriteDataM, WriteDataW);
|
||||
flopenrc #(`XLEN) PCWReg(clk, reset, dut.hart.FlushW, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.PCM, PCW);
|
||||
@ -176,8 +190,9 @@ module testbench();
|
||||
// always check PC, instruction bits
|
||||
if (checkInstrM) begin
|
||||
// read 1 line of the trace file
|
||||
matchCount = $fgets(line, data_file_all);
|
||||
if(`DEBUG_TRACE > 1) $display("Time %t, line %x", $time, line);
|
||||
matchCount = $fgets(line, data_file_all);
|
||||
if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line);
|
||||
// extract PC, Instr
|
||||
matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM);
|
||||
//$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM);
|
||||
|
||||
@ -213,21 +228,17 @@ module testbench();
|
||||
RegWriteM = ExpectedTokens[MarkerIndex];
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM);
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM);
|
||||
|
||||
MarkerIndex += 3;
|
||||
|
||||
// parse memory address, read data, and/or write data
|
||||
// parse memory address, read data, and/or write data
|
||||
end else if(ExpectedTokens[MarkerIndex].substr(0, 2) == "Mem") begin
|
||||
MemOpM = ExpectedTokens[MarkerIndex];
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedMemAdrM);
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedMemWriteDataM);
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+3], "%x", ExpectedMemReadDataM);
|
||||
|
||||
MarkerIndex += 4;
|
||||
|
||||
// parse CSRs, because there are 1 or more CSRs after the CSR token
|
||||
// we check if the CSR token or the number of CSRs is greater than 0.
|
||||
// if so then we want to parse for a CSR.
|
||||
// parse CSRs, because there are 1 or more CSRs after the CSR token
|
||||
// we check if the CSR token or the number of CSRs is greater than 0.
|
||||
// if so then we want to parse for a CSR.
|
||||
end else if(ExpectedTokens[MarkerIndex] == "CSR" || NumCSRM > 0) begin
|
||||
if(ExpectedTokens[MarkerIndex] == "CSR") begin
|
||||
// all additional CSR's won't have this token.
|
||||
@ -235,30 +246,13 @@ module testbench();
|
||||
end
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex], "%s", ExpectedCSRArrayM[NumCSRM]);
|
||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedCSRArrayValueM[NumCSRM]);
|
||||
|
||||
MarkerIndex += 2;
|
||||
|
||||
// if we get an xcause with the interrupt bit set we must generate an interrupt as interrupts
|
||||
// are imprecise. Forcing the trap at this time will allow wally to track what qemu does.
|
||||
// the msb of xcause will be set.
|
||||
// bits 1:0 select mode; 0 = user, 1 = superviser, 3 = machine
|
||||
// bits 3:2 select the type of interrupt, 0 = software, 1 = timer, 2 = external
|
||||
if(ExpectedCSRArrayM[NumCSRM].substr(1, 5) == "cause" && (ExpectedCSRArrayValueM[NumCSRM][`XLEN-1] == 1'b1)) begin
|
||||
//what type?
|
||||
ExpectedIntType = ExpectedCSRArrayValueM[NumCSRM] & 64'h0000_000C;
|
||||
$display("%tns, %d instrs: CSR = %s. Forcing interrupt of cause = %x", $time, InstrCountW, ExpectedCSRArrayM[NumCSRM], ExpectedCSRArrayValueM[NumCSRM]);
|
||||
forcedInterrupt = 1;
|
||||
if(ExpectedIntType == 0) begin
|
||||
force dut.hart.priv.SwIntM = 1'b1;
|
||||
$display("Activate spoofed SwIntM");
|
||||
end else if(ExpectedIntType == 4) begin
|
||||
force dut.hart.priv.TimerIntM = 1'b1;
|
||||
$display("Activate spoofed TimeIntM");
|
||||
end else if(ExpectedIntType == 8) begin
|
||||
force dut.hart.priv.ExtIntM = 1'b1;
|
||||
$display("Activate spoofed ExtIntM");
|
||||
end else forcedInterrupt = 0;
|
||||
end
|
||||
// match MIP to QEMU's because interrupts are imprecise
|
||||
if(ExpectedCSRArrayM[NumCSRM].substr(0, 2) == "mip") begin
|
||||
$display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
|
||||
MIPexpected = ExpectedCSRArrayValueM[NumCSRM];
|
||||
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||
end
|
||||
NumCSRM++;
|
||||
end
|
||||
end
|
||||
@ -268,12 +262,10 @@ module testbench();
|
||||
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM;
|
||||
end
|
||||
if(textM.substr(0,5) == "rdtime") begin
|
||||
$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW);
|
||||
//$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW);
|
||||
force dut.uncore.clint.clint.MTIME = ExpectedRegValueM;
|
||||
//dut.hart.ieu.dp.regf.wd3
|
||||
end
|
||||
|
||||
end // if (checkInstrM)
|
||||
end
|
||||
end
|
||||
|
||||
// step 1: register expected state into the write back stage.
|
||||
@ -320,37 +312,16 @@ module testbench();
|
||||
ExpectedCSRArrayValueW[NumCSRWIndex] = ExpectedCSRArrayValueM[NumCSRWIndex];
|
||||
end
|
||||
end
|
||||
// override on special conditions
|
||||
#1;
|
||||
|
||||
|
||||
// override on special conditions
|
||||
if(~dut.hart.StallW) begin
|
||||
if(textW.substr(0,5) == "rdtime") begin
|
||||
$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, InstrCountW);
|
||||
//$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, InstrCountW);
|
||||
release dut.uncore.clint.clint.MTIME;
|
||||
//release dut.hart.ieu.dp.regf.wd3;
|
||||
end
|
||||
|
||||
end
|
||||
if (ExpectedMemAdrM == 'h10000005) begin
|
||||
//$display("%tns, %d instrs: releasing force of ReadDataM.", $time, InstrCountW);
|
||||
release dut.hart.ieu.dp.ReadDataM;
|
||||
end
|
||||
|
||||
// force interrupts to 0
|
||||
if (forcedInterrupt) begin
|
||||
forcedInterrupt = 0;
|
||||
if(ExpectedIntType == 0) begin
|
||||
force dut.hart.priv.SwIntM = 1'b0;
|
||||
$display("Deactivate spoofed SwIntM");
|
||||
end
|
||||
else if(ExpectedIntType == 4) begin
|
||||
force dut.hart.priv.TimerIntM = 1'b0;
|
||||
$display("Deactivate spoofed TimeIntM");
|
||||
end
|
||||
else if(ExpectedIntType == 8) begin
|
||||
force dut.hart.priv.ExtIntM = 1'b0;
|
||||
$display("Deactivate spoofed ExtIntM");
|
||||
end
|
||||
release dut.hart.ieu.dp.ReadDataM;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -365,212 +336,65 @@ module testbench();
|
||||
if (InstrCountW == waveOnICount) $stop;
|
||||
// print progress message
|
||||
if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW);
|
||||
// check PCW
|
||||
fault = 0;
|
||||
if(PCW != ExpectedPCW) begin
|
||||
$display("PCW: %016x does not equal ExpectedPCW: %016x", PCW, ExpectedPCW);
|
||||
fault = 1;
|
||||
end
|
||||
|
||||
// check instruction value
|
||||
if(dut.hart.ifu.InstrW != ExpectedInstrW) begin
|
||||
$display("InstrW: %x does not equal ExpectedInstrW: %x", dut.hart.ifu.InstrW, ExpectedInstrW);
|
||||
fault = 1;
|
||||
end
|
||||
|
||||
// check the number of instructions
|
||||
if(dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW != InstrCountW) begin
|
||||
$display("%t, Number of instruction Retired = %d does not equal number of instructions in trace = %d", $time, dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW, InstrCountW);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
|
||||
#2; // delay 2 ns.
|
||||
|
||||
|
||||
if(`DEBUG_TRACE > 2) begin
|
||||
$display("Reg Write Address: %02d ? expected value: %02d", dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW);
|
||||
$display("RF[%02d]: %016x ? expected value: %016x", ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
|
||||
end
|
||||
|
||||
if (RegWriteW == "GPR") begin
|
||||
if (dut.hart.ieu.dp.regf.a3 != ExpectedRegAdrW) begin
|
||||
$display("Reg Write Address: %02d does not equal expected value: %02d", dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW);
|
||||
fault = 1;
|
||||
if (`DEBUG_TRACE >= 1) begin
|
||||
`checkEQ("PCW",PCW,ExpectedPCW)
|
||||
`checkEQ("InstrW",dut.hart.ifu.InstrW,ExpectedInstrW)
|
||||
`checkEQ("Instr Count",dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW,InstrCountW)
|
||||
#2; // delay 2 ns.
|
||||
if(`DEBUG_TRACE >= 5) begin
|
||||
$display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW);
|
||||
$display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
|
||||
end
|
||||
|
||||
if (dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW] != ExpectedRegValueW) begin
|
||||
$display("RF[%02d]: %016x does not equal expected value: %016x", ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
|
||||
fault = 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (MemOpW.substr(0,2) == "Mem") begin
|
||||
if(`DEBUG_TRACE > 3) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
|
||||
|
||||
// always check address
|
||||
if (MemAdrW != ExpectedMemAdrW) begin
|
||||
$display("MemAdrW: %016x does not equal expected value: %016x", MemAdrW, ExpectedMemAdrW);
|
||||
fault = 1;
|
||||
end
|
||||
|
||||
// check read data
|
||||
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||
if(`DEBUG_TRACE > 3) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||
if (dut.hart.ieu.dp.ReadDataW != ExpectedMemReadDataW) begin
|
||||
$display("ReadDataW: %016x does not equal expected value: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||
fault = 1;
|
||||
end
|
||||
end
|
||||
|
||||
// check write data
|
||||
else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
|
||||
if(`DEBUG_TRACE > 3) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||
if (WriteDataW != ExpectedMemWriteDataW) begin
|
||||
$display("WriteDataW: %016x does not equal expected value: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||
fault = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// check csr
|
||||
//$display("%t, about to check csr, NumCSRW = %d", $time, NumCSRW);
|
||||
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("%t, NumCSRPostWIndex = %d, Expected CSR: %s = %016x", $time, NumCSRPostWIndex, ExpectedCSRArrayW[NumCSRPostWIndex], ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
case(ExpectedCSRArrayW[NumCSRPostWIndex])
|
||||
"mhartid": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
if (RegWriteW == "GPR") begin
|
||||
`checkEQ("Reg Write Address",dut.hart.ieu.dp.regf.a3,ExpectedRegAdrW)
|
||||
$sprintf(name,"RF[%02d]",ExpectedRegAdrW);
|
||||
`checkEQ(name, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW)
|
||||
end
|
||||
if (MemOpW.substr(0,2) == "Mem") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
|
||||
`checkEQ("MemAdrW",MemAdrW,ExpectedMemAdrW)
|
||||
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
||||
end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
||||
end
|
||||
"mstatus": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if ((dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW) != (ExpectedCSRArrayValueW[NumCSRPostWIndex])) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mtvec": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mip": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIP_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MIP_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIP_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mie": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIE_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MIE_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIE_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mideleg": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"medeleg": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mepc": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MEPC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MEPC_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MEPC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"mtval": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"sepc": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.SEPC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrs.SEPC_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.SEPC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"scause": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"stvec": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.STVEC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrs.STVEC_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.STVEC_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
"stval": begin
|
||||
if(`DEBUG_TRACE > 0) begin
|
||||
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin
|
||||
$display("%t, CSR: %s = %016x, does not equal expected value %016x", $time, ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]);
|
||||
if(!`DontHaltOnCSRMisMatch) fault = 1;
|
||||
end
|
||||
end
|
||||
endcase // case (ExpectedCSRArrayW[NumCSRPostWIndex])
|
||||
end // for (NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++)
|
||||
if (fault == 1) begin `ERROR end
|
||||
end
|
||||
// check csr
|
||||
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin
|
||||
case(ExpectedCSRArrayW[NumCSRPostWIndex])
|
||||
"mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW)
|
||||
"mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW)
|
||||
"mtvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW)
|
||||
"mip": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIP_REGW)
|
||||
"mie": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIE_REGW)
|
||||
"mideleg":`CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW)
|
||||
"medeleg": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW)
|
||||
"mepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEPC_REGW)
|
||||
"mtval": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW)
|
||||
"sepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.SEPC_REGW)
|
||||
"scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW)
|
||||
"stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW)
|
||||
"stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW)
|
||||
endcase
|
||||
end
|
||||
if (fault == 1) begin
|
||||
errorCount +=1;
|
||||
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount);
|
||||
$stop;
|
||||
end
|
||||
end // if (`DEBUG_TRACE >= 1)
|
||||
end // if (checkInstrW)
|
||||
end // always @ (negedge clk)
|
||||
|
||||
|
||||
// track the current function
|
||||
FunctionName FunctionName(.reset(reset),
|
||||
.clk(clk),
|
||||
.ProgramAddrMapFile(ProgramAddrMapFile),
|
||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||
.clk(clk),
|
||||
.ProgramAddrMapFile(ProgramAddrMapFile),
|
||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -587,7 +411,11 @@ module testbench();
|
||||
// initial loading of memories
|
||||
initial begin
|
||||
$readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3);
|
||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
`else
|
||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
`endif
|
||||
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
|
||||
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
|
||||
ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"};
|
||||
|
Loading…
Reference in New Issue
Block a user