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" 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/all.txt all.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/bootmem.txt bootmem.txt ln -s /courses/e190ax/buildroot_boot/bootmem.txt bootmem.txt
ln -s /courses/e190ax/buildroot_boot/ram.txt ram.txt ln -s /courses/e190ax/buildroot_boot/ram.txt ram.txt
echo "Done!" echo "Done!"

View File

@ -1,10 +1,6 @@
# This could be nice to use if you want to mess with the testvectors # This could be nice to use if you want to mess with the testvectors
# without corrupting the stable copies on Tera. # without corrupting the stable copies on Tera.
unlink parsedCSRs.txt unlink all.txt
unlink parsedMemRead.txt
unlink parsedMemWrite.txt
unlink parsedPC.txt
unlink parsedRegs.txt
unlink bootmem.txt unlink bootmem.txt
unlink ram.txt unlink ram.txt
echo "Done!" 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] inputFile = sys.argv[1]
outputFile = sys.argv[2] outputFile = sys.argv[2]
if not os.path.exists(inputFile): if not os.path.exists(inputFile):
sys.exit('Error input file '+inputFile+'not found') sys.exit('Error input file '+inputFile+' not found')
print('Translating '+os.path.basename(inputFile)+' to '+os.path.basename(outputFile)) print('Begin translating '+os.path.basename(inputFile)+' to '+os.path.basename(outputFile))
with open(inputFile, 'r') as f: with open(inputFile, 'r') as f:
with open(outputFile, 'w') as w: with open(outputFile, 'w') as w:
for l in f: for l in f:
w.write(f'{"".join([x[2:] for x in l.split()[:0:-1]])}\n') 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 lineNum = 0
StartLine = 0 StartLine = 0
EndLine = 0 EndLine = 0
numInstrs = 0
#instructions = [] #instructions = []
MemAdr = 0 MemAdr = 0
lines = [] lines = []
@ -195,6 +196,10 @@ for line in fileinput.input('-'):
lines.clear() lines.clear()
#instructions.append(MoveInstrToRegWriteLst) #instructions.append(MoveInstrToRegWriteLst)
PrintInstr(MoveInstrToRegWriteLst, sys.stdout) 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 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" `include "wally-config.vh"
/* verilator lint_off DECLFILENAME */ /* 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 // ordinary flip-flop
module flop #(parameter WIDTH = 8) ( module flop #(parameter WIDTH = 8) (
@ -40,10 +42,11 @@ endmodule
module flopr #(parameter WIDTH = 8) ( module flopr #(parameter WIDTH = 8) (
input logic clk, reset, input logic clk, reset,
input logic [WIDTH-1:0] d, 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) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0; if (reset) q <= #1 RESET_VAL;
else q <= #1 d; else q <= #1 d;
endmodule endmodule
@ -61,10 +64,11 @@ endmodule
module flopenrc #(parameter WIDTH = 8) ( module flopenrc #(parameter WIDTH = 8) (
input logic clk, reset, clear, en, input logic clk, reset, clear, en,
input logic [WIDTH-1:0] d, 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) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0; if (reset) q <= #1 RESET_VAL;
else if (en) else if (en)
if (clear) q <= #1 0; if (clear) q <= #1 0;
else q <= #1 d; else q <= #1 d;
@ -74,10 +78,11 @@ endmodule
module flopenr #(parameter WIDTH = 8) ( module flopenr #(parameter WIDTH = 8) (
input logic clk, reset, en, input logic clk, reset, en,
input logic [WIDTH-1:0] d, 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) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0; if (reset) q <= #1 RESET_VAL;
else if (en) q <= #1 d; else if (en) q <= #1 d;
endmodule endmodule
@ -99,10 +104,11 @@ module floprc #(parameter WIDTH = 8) (
input logic reset, input logic reset,
input logic clear, input logic clear,
input logic [WIDTH-1:0] d, 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) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0; if (reset) q <= #1 RESET_VAL;
else else
if (clear) q <= #1 0; if (clear) q <= #1 0;
else q <= #1 d; else q <= #1 d;

View File

@ -44,7 +44,13 @@ module regfile (
// reset is intended for simulation only, not synthesis // reset is intended for simulation only, not synthesis
always_ff @(negedge clk or posedge reset) 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; else if (we3) rf[a3] <= wd3;
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0; assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;

View File

@ -104,8 +104,16 @@ module csrc #(parameter
logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M; logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M;
logic [4:0] CounterNumM; logic [4:0] CounterNumM;
logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW; logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW;
var [`COUNTERS-1:3][`XLEN-1:0] initHPMCOUNTER;
logic InstrValidNotFlushedM; logic InstrValidNotFlushedM;
initial
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-HPMCOUNTER.txt"}, initHPMCOUNTER);
`else
initHPMCOUNTER = {(`COUNTERS-3){`XLEN'b0}};
`endif
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
//logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTERH_REGW; //logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTERH_REGW;
@ -137,16 +145,12 @@ module csrc #(parameter
logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3]; logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3]; logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3];
genvar i; genvar i;
// could replace special counters 0-2 with this loop for all counters // could replace special counters 0-2 with this loop for all counters
assign CounterEvent[0] = 1'b1; assign CounterEvent[0] = 1'b1;
assign CounterEvent[1] = 1'b0; assign CounterEvent[1] = 1'b0;
if(`QEMU) begin if(`QEMU) assign CounterEvent[`COUNTERS-1:2] = 0;
assign CounterEvent[`COUNTERS-1:2] = 0; else begin
end else begin
logic LoadStallE, LoadStallM; logic LoadStallE, LoadStallM;
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(FlushE), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); 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)); flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
@ -168,7 +172,7 @@ module csrc #(parameter
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i); assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0]; 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 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; if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 initHPMCOUNTER[i];
else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i]; else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
//flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]); //flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
@ -221,8 +225,8 @@ module csrc #(parameter
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]); // flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_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) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]);
//flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_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) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock*** // 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]); // flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]); flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]);
@ -243,8 +247,7 @@ module csrc #(parameter
assign CounterNumM = CSRAdrM[4:0]; // which counter to read? assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
if (`XLEN==64) // 64-bit counter reads if (`XLEN==64) // 64-bit counter reads
always_comb always_comb
if (PrivilegeModeW == `M_MODE || if (PrivilegeModeW == `M_MODE || MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0; IllegalCSRCAccessM = 0;
if (CSRAdrM >= MHPMCOUNTERBASE+3 && CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-MHPMCOUNTERBASE]; 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]; 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 IllegalCSRCAccessM = 1; // no privileges for this csr
CSRCReadValM = 0; CSRCReadValM = 0;
end end
end else begin end else begin // not `ZICOUNTERS_SUPPORTED
assign CSRCReadValM = 0; assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; assign IllegalCSRCAccessM = 1;
end end

View File

@ -79,14 +79,24 @@ module csri #(parameter
assign SIP_WRITE_MASK = 12'h000; assign SIP_WRITE_MASK = 12'h000;
end end
always @(posedge clk, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21 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 (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 (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 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 else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
end end
always @(posedge clk, posedge reset) begin 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 (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 (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 // else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field

View File

@ -85,6 +85,11 @@ module csrm #(parameter
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW; logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW;
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 WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
@ -94,6 +99,31 @@ module csrm #(parameter
localparam MISA_26 = (`MISA) & 32'h03ffffff; 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 // 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]}; 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); assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID);
// CSRs // 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 generate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist 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) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, initMEDELEG, MEDELEG_REGW);
flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, `XLEN'b0, MIDELEG_REGW); flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, initMIDELEG, MIDELEG_REGW);
end else begin end else begin
assign MEDELEG_REGW = 0; assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0; assign MIDELEG_REGW = 0;
end end
endgenerate endgenerate
// flopenl #(`XLEN) MIPreg(clk, reset, WriteMIPM, CSRWriteValM, zero, MIP_REGW); flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW, initMSCRATCH);
// flopenl #(`XLEN) MIEreg(clk, reset, WriteMIEM, CSRWriteValM, zero, MIE_REGW); flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW, initMEPC);
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW, initMCAUSE);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
if(`QEMU) assign MTVAL_REGW = `XLEN'b0; if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
generate generate
if (`BUSYBEAR == 1) if (`BUSYBEAR == 1)
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW); flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW);
else if (`BUILDROOT == 1) 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 else
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW); flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW);
endgenerate 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 // 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 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]; 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 if (`XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i]; 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 end else begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
// assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW; // 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]); // flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]);
end end
end end

View File

@ -74,6 +74,30 @@ module csrs #(parameter
logic WriteSSCRATCHM, WriteSEPCM; logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW; 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 WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW;
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW; assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW;
@ -85,28 +109,28 @@ module csrs #(parameter
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW; assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW;
// CSRs // CSRs
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `XLEN'b0, STVEC_REGW); //busybear: change reset to 0 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); flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW, initSSCRATCH);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW, initSEPC);
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, `XLEN'b0, SCAUSE_REGW); flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, initSCAUSE, SCAUSE_REGW);
if(`QEMU) assign STVAL_REGW = `XLEN'b0; if(`QEMU) assign STVAL_REGW = `XLEN'b0;
else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`MEM_VIRTMEM) if (`MEM_VIRTMEM)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW, initSATP);
else else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
if (`BUSYBEAR == 1) if (`BUSYBEAR == 1)
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
else if (`BUILDROOT == 1) 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 else
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW);
if (`N_SUPPORTED) begin if (`N_SUPPORTED) begin
logic WriteSEDELEGM, WriteSIDELEGM; logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG); assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG); assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, `XLEN'b0, SEDELEG_REGW); flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, initSEDELEG, SEDELEG_REGW);
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, `XLEN'b0, SIDELEG_REGW); flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, initSIDELEG, SIDELEG_REGW);
end else begin end else begin
assign SEDELEG_REGW = 0; assign SEDELEG_REGW = 0;
assign SIDELEG_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 [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; 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 // STATUS REGISTER FIELD
// See Privileged Spec Section 3.1.6 // See Privileged Spec Section 3.1.6
// Lower privilege status registers are a subset of the full status register // Lower privilege status registers are a subset of the full status register
@ -108,23 +117,33 @@ module csrsr (
// registers for STATUS bits // registers for STATUS bits
// complex register with reset, write enable, and the ability to update other bits in certain cases // 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) always_ff @(posedge clk, posedge reset)
if (reset) begin if (reset) begin
STATUS_TSR_INT <= #1 0; //STATUS_TSR_INT <= #1 0;
STATUS_TW_INT <= #1 0; //STATUS_TW_INT <= #1 0;
STATUS_TVM_INT <= #1 0; //STATUS_TVM_INT <= #1 0;
STATUS_MXR_INT <= #1 0; //STATUS_MXR_INT <= #1 0;
STATUS_SUM_INT <= #1 0; //STATUS_SUM_INT <= #1 0;
STATUS_MPRV_INT <= #1 0; // Per Priv 3.3 //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_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0
STATUS_MPP <= #1 0; //`M_MODE; //STATUS_MPP <= #1 0; //`M_MODE;
STATUS_SPP <= #1 0; //1'b1; //STATUS_SPP <= #1 0; //1'b1;
STATUS_MPIE <= #1 0; //1; //STATUS_MPIE <= #1 0; //1;
STATUS_SPIE <= #1 0; //`S_SUPPORTED; //STATUS_SPIE <= #1 0; //`S_SUPPORTED;
STATUS_UPIE <= #1 0; // `U_SUPPORTED; //STATUS_UPIE <= #1 0; // `U_SUPPORTED;
STATUS_MIE <= #1 0; // Per Priv 3.3 //STATUS_MIE <= #1 0; // Per Priv 3.3
STATUS_SIE <= #1 0; //`S_SUPPORTED; //STATUS_SIE <= #1 0; //`S_SUPPORTED;
STATUS_UIE <= #1 0; //`U_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 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; 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 // 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 // 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. // 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" `include "wally-config.vh"
//`define CHECKPOINT
`define LINUX_CHECKPOINT "../linux-testgen/linux-testvectors/checkpoint1K"
`define DEBUG_TRACE 0 `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(); 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; string ProgramAddrMapFile, ProgramLabelMapFile;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// DUT ///////////////////////////////////// ///////////////////////////////////// DUT /////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
logic clk, reset; logic clk, reset;
logic [`AHBW-1:0] readDataExpected; logic [`AHBW-1:0] readDataExpected;
logic [31:0] HADDR; logic [31:0] HADDR;
logic [`AHBW-1:0] HWDATA; logic [`AHBW-1:0] HWDATA;
@ -51,7 +60,6 @@ module testbench();
logic HCLK, HRESETn; logic HCLK, HRESETn;
logic [`AHBW-1:0] HRDATAEXT; logic [`AHBW-1:0] HRDATAEXT;
logic HREADYEXT, HRESPEXT; logic HREADYEXT, HRESPEXT;
logic [31:0] GPIOPinsIn; logic [31:0] GPIOPinsIn;
logic [31:0] GPIOPinsOut, GPIOPinsEn; logic [31:0] GPIOPinsOut, GPIOPinsEn;
logic UARTSin, UARTSout; logic UARTSin, UARTSout;
@ -73,9 +81,11 @@ module testbench();
// Testbench Core // Testbench Core
integer warningCount = 0; integer warningCount = 0;
integer errorCount = 0; integer errorCount = 0;
integer MIPexpected;
// P, Instr Checking // P, Instr Checking
logic [`XLEN-1:0] PCW; logic [`XLEN-1:0] PCW;
integer data_file_all; integer data_file_all;
string name;
// Write Back stage signals needed for trace compare, but don't actually // Write Back stage signals needed for trace compare, but don't actually
// exist in CPU. // exist in CPU.
@ -85,7 +95,6 @@ module testbench();
logic checkInstrW; logic checkInstrW;
//integer RegAdr; //integer RegAdr;
integer fault; integer fault;
logic TrapW; logic TrapW;
@ -130,16 +139,26 @@ module testbench();
integer NumCSRMIndex; integer NumCSRMIndex;
integer NumCSRWIndex; integer NumCSRWIndex;
integer NumCSRPostWIndex; integer NumCSRPostWIndex;
// logic CurrentInterruptForce;
logic [`XLEN-1:0] InstrCountW; logic [`XLEN-1:0] InstrCountW;
// ----------- // ------
// Error Macro // Macros
// ----------- // ------
`define ERROR \
errorCount +=1; \ `define CSRwarn(CSR) \
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount); \ begin \
$stop; $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 initial begin
data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r"); data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
@ -149,16 +168,11 @@ module testbench();
force dut.hart.priv.ExtIntM = 0; force dut.hart.priv.ExtIntM = 0;
end 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; 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; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW;
// Additonal W stage registers
flopenrc #(`XLEN) MemAdrWReg(clk, reset, dut.hart.FlushW, ~dut.hart.StallW, dut.hart.ieu.dp.MemAdrM, MemAdrW); 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) 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); flopenrc #(`XLEN) PCWReg(clk, reset, dut.hart.FlushW, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.PCM, PCW);
@ -177,7 +191,8 @@ module testbench();
if (checkInstrM) begin if (checkInstrM) begin
// read 1 line of the trace file // read 1 line of the trace file
matchCount = $fgets(line, data_file_all); matchCount = $fgets(line, data_file_all);
if(`DEBUG_TRACE > 1) $display("Time %t, line %x", $time, line); if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line);
// extract PC, Instr
matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM); matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM);
//$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM); //$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM);
@ -213,18 +228,14 @@ module testbench();
RegWriteM = ExpectedTokens[MarkerIndex]; RegWriteM = ExpectedTokens[MarkerIndex];
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM); matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM);
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM); matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM);
MarkerIndex += 3; 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 end else if(ExpectedTokens[MarkerIndex].substr(0, 2) == "Mem") begin
MemOpM = ExpectedTokens[MarkerIndex]; MemOpM = ExpectedTokens[MarkerIndex];
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedMemAdrM); matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedMemAdrM);
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedMemWriteDataM); matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedMemWriteDataM);
matchCount = $sscanf(ExpectedTokens[MarkerIndex+3], "%x", ExpectedMemReadDataM); matchCount = $sscanf(ExpectedTokens[MarkerIndex+3], "%x", ExpectedMemReadDataM);
MarkerIndex += 4; MarkerIndex += 4;
// parse CSRs, because there are 1 or more CSRs after the CSR token // 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. // 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. // if so then we want to parse for a CSR.
@ -235,29 +246,12 @@ module testbench();
end end
matchCount = $sscanf(ExpectedTokens[MarkerIndex], "%s", ExpectedCSRArrayM[NumCSRM]); matchCount = $sscanf(ExpectedTokens[MarkerIndex], "%s", ExpectedCSRArrayM[NumCSRM]);
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedCSRArrayValueM[NumCSRM]); matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedCSRArrayValueM[NumCSRM]);
MarkerIndex += 2; MarkerIndex += 2;
// match MIP to QEMU's because interrupts are imprecise
// if we get an xcause with the interrupt bit set we must generate an interrupt as interrupts if(ExpectedCSRArrayM[NumCSRM].substr(0, 2) == "mip") begin
// are imprecise. Forcing the trap at this time will allow wally to track what qemu does. $display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
// the msb of xcause will be set. MIPexpected = ExpectedCSRArrayValueM[NumCSRM];
// bits 1:0 select mode; 0 = user, 1 = superviser, 3 = machine force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
// 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 end
NumCSRM++; NumCSRM++;
end end
@ -268,12 +262,10 @@ module testbench();
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM; force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM;
end end
if(textM.substr(0,5) == "rdtime") begin 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; force dut.uncore.clint.clint.MTIME = ExpectedRegValueM;
//dut.hart.ieu.dp.regf.wd3
end end
end
end // if (checkInstrM)
end end
// step 1: register expected state into the write back stage. // step 1: register expected state into the write back stage.
@ -320,38 +312,17 @@ module testbench();
ExpectedCSRArrayValueW[NumCSRWIndex] = ExpectedCSRArrayValueM[NumCSRWIndex]; ExpectedCSRArrayValueW[NumCSRWIndex] = ExpectedCSRArrayValueM[NumCSRWIndex];
end end
end end
// override on special conditions
#1; #1;
// override on special conditions
if(~dut.hart.StallW) begin if(~dut.hart.StallW) begin
if(textW.substr(0,5) == "rdtime") 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.uncore.clint.clint.MTIME;
//release dut.hart.ieu.dp.regf.wd3;
end end
if (ExpectedMemAdrM == 'h10000005) begin if (ExpectedMemAdrM == 'h10000005) begin
//$display("%tns, %d instrs: releasing force of ReadDataM.", $time, InstrCountW); //$display("%tns, %d instrs: releasing force of ReadDataM.", $time, InstrCountW);
release dut.hart.ieu.dp.ReadDataM; release dut.hart.ieu.dp.ReadDataM;
end 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
end
end end
end end
end end
@ -365,203 +336,56 @@ module testbench();
if (InstrCountW == waveOnICount) $stop; if (InstrCountW == waveOnICount) $stop;
// print progress message // print progress message
if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW); if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW);
// check PCW
fault = 0; fault = 0;
if(PCW != ExpectedPCW) begin if (`DEBUG_TRACE >= 1) begin
$display("PCW: %016x does not equal ExpectedPCW: %016x", PCW, ExpectedPCW); `checkEQ("PCW",PCW,ExpectedPCW)
fault = 1; `checkEQ("InstrW",dut.hart.ifu.InstrW,ExpectedInstrW)
end `checkEQ("Instr Count",dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW,InstrCountW)
// 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. #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);
if(`DEBUG_TRACE > 2) begin $display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
$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 end
if (RegWriteW == "GPR") begin if (RegWriteW == "GPR") begin
if (dut.hart.ieu.dp.regf.a3 != ExpectedRegAdrW) begin `checkEQ("Reg Write Address",dut.hart.ieu.dp.regf.a3,ExpectedRegAdrW)
$display("Reg Write Address: %02d does not equal expected value: %02d", dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW); $sprintf(name,"RF[%02d]",ExpectedRegAdrW);
fault = 1; `checkEQ(name, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW)
end 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 (MemOpW.substr(0,2) == "Mem") begin
if(`DEBUG_TRACE > 3) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW); if(`DEBUG_TRACE >= 4) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
`checkEQ("MemAdrW",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(MemOpW == "MemR" || MemOpW == "MemRW") begin
if(`DEBUG_TRACE > 3) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW); if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
if (dut.hart.ieu.dp.ReadDataW != ExpectedMemReadDataW) begin `checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
$display("ReadDataW: %016x does not equal expected value: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW); end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
fault = 1; if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
end end
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 // check csr
//$display("%t, about to check csr, NumCSRW = %d", $time, NumCSRW);
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin 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]) case(ExpectedCSRArrayW[NumCSRPostWIndex])
"mhartid": begin "mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW)
if(`DEBUG_TRACE > 0) begin "mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW)
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW, ExpectedCSRArrayValueW[NumCSRPostWIndex]); "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 end
if (dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin if (fault == 1) 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]); errorCount +=1;
if(!`DontHaltOnCSRMisMatch) fault = 1; $display("processed %0d instructions with %0d warnings", InstrCountW, warningCount);
$stop;
end end
end end // if (`DEBUG_TRACE >= 1)
"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 // if (checkInstrW) end // if (checkInstrW)
end // always @ (negedge clk) end // always @ (negedge clk)
@ -587,7 +411,11 @@ module testbench();
// initial loading of memories // initial loading of memories
initial begin initial begin
$readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3); $readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3);
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"ram.txt"}, dut.uncore.dtim.RAM);
`else
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM); $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(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory); $readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"}; ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"};