This commit is contained in:
David Harris 2021-09-30 20:07:43 -04:00
commit a39e14663d
15 changed files with 555 additions and 468 deletions

View File

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

View File

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

View 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

View 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

View File

@ -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)+'!')

View File

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

View 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!")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"};