diff --git a/bin/derivgen.pl b/bin/derivgen.pl index 58991faae..8a065bf7e 100755 --- a/bin/derivgen.pl +++ b/bin/derivgen.pl @@ -88,6 +88,18 @@ foreach my $key (@derivnames) { open(my $unmod, $configunmod) or die "Could not open file '$configunmod' $!"; open(my $fh, '>>', $config) or die "Could not open file '$config' $!"; + # Create symlink to imperas.ic for deriv buildroot + if ($key eq "buildroot") { + my $baseimperas_ic = "$ENV{WALLY}/config/$basederiv{$key}/imperas.ic"; + if (! -e $baseimperas_ic) { + my $baseimperas_ic = "$ENV{WALLY}/config/deriv/$basederiv{$key}/config.vh"; + } + if (-e $baseimperas_ic) { # If imperas.ic exists for base derivative, create hardlink to it + my $imperas_ic = "$dir/imperas.ic"; + system("ln -T $baseimperas_ic $imperas_ic"); + } + } + my $datestring = localtime(); my %hit = (); print $fh "// Config $key automatically derived from $basederiv{$key} on $datestring using derivgen.pl\n"; diff --git a/bin/nightly_build.py b/bin/nightly_build.py index cb8583eef..b675fceca 100755 --- a/bin/nightly_build.py +++ b/bin/nightly_build.py @@ -261,9 +261,6 @@ class TestRunner: cvw = folder.joinpath("cvw") self.logger.info(f"cvw is: {cvw}") - # set the WALLY environmental variable to the new repository - os.environ["WALLY"] = str(cvw) - self.cvw = cvw self.sim_dir = cvw.joinpath("bin") self.base_parent_dir = folder @@ -292,11 +289,11 @@ class TestRunner: output_file = self.log_dir.joinpath(f"make-{target}-output.log") else: output_file = self.log_dir.joinpath(f"make-output.log") - # Execute make with target and cores/2 + # Source setup script and execute make with target and cores/2 if target: - command = ["make", target, "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make {target} --jobs=$(($(nproc)/2))"] else: - command = ["make", "--jobs=$(($(nproc)/2))"] + command = [f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && make --jobs=$(($(nproc)/2))"] self.logger.info(f"Command used in directory {makefile_location}: {' '.join(command)}") @@ -305,7 +302,7 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") # Execute the command using a subprocess and not save the output #result = subprocess.run(command, text=True) @@ -334,12 +331,16 @@ class TestRunner: output_file = self.log_dir.joinpath(f"{test_name}-output.log") os.chdir(self.sim_dir) + # Source setup script and delete output from log on whatever test command gets run + command = f"source {os.path.join(self.cvw, 'setup.sh')} > /dev/null && " + if test_extensions: - command = [test_type, test_name] + test_extensions + commandext = [test_type, test_name] + test_extensions self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name} {' '.join(test_extensions)}") else: - command = [test_type, test_name] + commandext = [test_type, test_name] self.logger.info(f"Command used to run tests in directory {self.sim_dir}: {test_type} {test_name}") + command += " ".join(commandext) # Execute the command using subprocess and save the output into a file @@ -348,15 +349,15 @@ class TestRunner: formatted_datetime = self.current_datetime.strftime("%Y-%m-%d %H:%M:%S") f.write(formatted_datetime) f.write("\n\n") - result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True) + result = subprocess.run(command, stdout=f, stderr=subprocess.STDOUT, text=True, shell=True, executable="/bin/bash") except Exception as e: - self.logger.error("There was an error in running the tests in the run_tests function: {e}") + self.logger.error(f"There was an error in running the tests in the run_tests function: {e}") # Check if the command executed successfuly if result.returncode or result.returncode == 0: - self.logger.info(f"Test ran successfuly. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.info(f"Test ran successfuly. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return True, output_file else: - self.logger.error(f"Error making test. Test type: {test_type}, test name: {test_name}, test extension: {' '.join(test_extensions)}") + self.logger.error(f"Error making test. Test name: {test_name}, test extension: {' '.join(test_extensions)}") return False, output_file diff --git a/bin/regression-wally b/bin/regression-wally index 0a7a8fa69..cc0588bf6 100755 --- a/bin/regression-wally +++ b/bin/regression-wally @@ -539,7 +539,7 @@ def main(): num_fail = 0 results = {} for config in configs: - results[config] = pool.apply_async(run_test_case,(config,)) + results[config] = pool.apply_async(run_test_case,(config, args.dryrun)) for (config,result) in results.items(): try: num_fail+=result.get(timeout=TIMEOUT_DUR) diff --git a/bin/wsim b/bin/wsim index ca44e22a6..72ec81a22 100755 --- a/bin/wsim +++ b/bin/wsim @@ -65,7 +65,7 @@ if(args.testsuite.endswith('.elf') and args.elf == ""): # No --elf argument; che print("ELF file not found: " + args.testsuite) exit(1) -if(args.lockstep and not args.testsuite.endswith('.elf')): +if(args.lockstep and not args.testsuite.endswith('.elf') and not args.testsuite == "buildroot"): print(f"Invalid Options. Cannot run a testsuite, {args.testsuite} with lockstep. Must run a single elf.") exit(1) @@ -90,7 +90,10 @@ else: EnableLog = 0 prefix = "" if (args.lockstep or args.lockstepverbose or args.fcov or args.fcovimp): if (args.sim == "questa" or args.sim == "vcs"): - prefix = "IMPERAS_TOOLS=" + WALLY + "/config/"+args.config+"/imperas.ic" + imperasicPath = os.path.join(WALLY, "config", args.config, "imperas.ic") + if not os.path.isfile(imperasicPath): # If config is a derivative, look for imperas.ic in derivative configs + imperasicPath = os.path.join(WALLY, "config", "deriv", args.config, "imperas.ic") + prefix = "IMPERAS_TOOLS=" + imperasicPath # Force Questa to use 64-bit mode, sometimes it defaults to 32-bit even on 64-bit machines if (args.sim == "questa"): prefix = "MTI_VCO_MODE=64 " + prefix diff --git a/config/rv32gc/coverage.svh b/config/rv32gc/coverage.svh index 97496a8b9..eed513f9f 100644 --- a/config/rv32gc/coverage.svh +++ b/config/rv32gc/coverage.svh @@ -10,6 +10,13 @@ `include "RV32M_coverage.svh" `include "RV32F_coverage.svh" `include "RV32D_coverage.svh" +`include "RV32Zba_coverage.svh" +`include "RV32Zbb_coverage.svh" +`include "RV32Zbc_coverage.svh" +`include "RV32Zbs_coverage.svh" +`include "RV32Zbkb_coverage.svh" +`include "RV32Zbkc_coverage.svh" +`include "RV32Zbkx_coverage.svh" `include "RV32ZfaF_coverage.svh" `include "RV32ZfaD_coverage.svh" `include "RV32ZfaZfh_coverage.svh" @@ -22,6 +29,11 @@ `include "RV32ZcbZbb_coverage.svh" `include "RV32Zcf_coverage.svh" `include "RV32Zcd_coverage.svh" +`include "RV32Zaamo_coverage.svh" +`include "RV32Zalrsc_coverage.svh" +`include "RV32Zknd_coverage.svh" +`include "RV32Zkne_coverage.svh" +`include "RV32Zknh_coverage.svh" // Privileged extensions `include "ZicsrM_coverage.svh" diff --git a/config/rv64gc/coverage.svh b/config/rv64gc/coverage.svh index d594a3a44..a293eb5b1 100644 --- a/config/rv64gc/coverage.svh +++ b/config/rv64gc/coverage.svh @@ -10,6 +10,13 @@ `include "RV64M_coverage.svh" `include "RV64F_coverage.svh" `include "RV64D_coverage.svh" +`include "RV64Zba_coverage.svh" +`include "RV64Zbb_coverage.svh" +`include "RV64Zbc_coverage.svh" +`include "RV64Zbs_coverage.svh" +`include "RV64Zbkb_coverage.svh" +`include "RV64Zbkc_coverage.svh" +`include "RV64Zbkx_coverage.svh" `include "RV64ZfaF_coverage.svh" `include "RV32ZfaD_coverage.svh" `include "RV32ZfaZfh_coverage.svh" @@ -22,6 +29,18 @@ `include "RV64ZcbZbb_coverage.svh" `include "RV64ZcbZba_coverage.svh" `include "RV64Zcd_coverage.svh" +`include "RV64Zaamo_coverage.svh" +`include "RV64Zalrsc_coverage.svh" +`include "RV64Zknd_coverage.svh" +`include "RV64Zkne_coverage.svh" +`include "RV64Zknh_coverage.svh" + + + + + + + // Privileged extensions `include "RV64VM_coverage.svh" diff --git a/linux/testvector-generation/EmulateLinux.sh b/linux/testvector-generation/EmulateLinux.sh deleted file mode 100755 index e2b50af4d..000000000 --- a/linux/testvector-generation/EmulateLinux.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -usage() { echo "Usage: $0 [-h] [-b ] [-d ]" 1>&2; exit 1; } - -help() { - echo "Usage: $0 [OPTIONS] " - echo " -b get images from given buildroot" - echo " -d specify device tree to use" - exit 0; -} - -# defaults -imageDir=$RISCV/buildroot/output/images -DEVICE_TREE=${imageDir}/wally-virt.dtb - -# Process options and arguments. The following code grabs the single -# sdcard device argument no matter where it is in the positional -# parameters list. -ARGS=() -while [ $OPTIND -le "$#" ] ; do - if getopts "hb:d:" arg ; then - case "${arg}" in - h) help - ;; - b) BUILDROOT=${OPTARG} - ;; - d) DEVICE_TREE=${OPTARG} - ;; - esac - else - ARGS+=("${!OPTIND}") - ((OPTIND++)) - fi -done - -# File location variables -imageDir=$BUILDROOT/output/images - -tvDir=$RISCV/linux-testvectors -tcpPort=1239 - -# QEMU Simulation -qemu-system-riscv64 \ --M virt -m 256M -dtb $DEVICE_TREE \ --nographic \ --bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" --singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on diff --git a/linux/testvector-generation/checkpointSweep.sh b/linux/testvector-generation/checkpointSweep.sh deleted file mode 100755 index 075ca253c..000000000 --- a/linux/testvector-generation/checkpointSweep.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -for index in {450..500}; -do - instrs=$(($index*1000000)) - echo "y" | nice -n 5 ./genCheckpoint.sh $instrs -done diff --git a/linux/testvector-generation/debug.sh b/linux/testvector-generation/debug.sh deleted file mode 100755 index 7ca3e9b15..000000000 --- a/linux/testvector-generation/debug.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -tcpPort=1239 - -# QEMU Simulation -qemu-system-riscv64 \ --M virt -dtb $imageDir/wally-virt.dtb \ --nographic \ --bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ --singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on -# > ./qemu-serial \ -# -gdb tcp::$tcpPort -S) \ -# & riscv64-unknown-elf-gdb -quiet \ -# -ex "set pagination off" \ -# -ex "set logging overwrite on" \ -# -ex "set logging redirect on" \ -# -ex "set confirm off" \ -# -ex "target extended-remote :$tcpPort" \ -# -ex "maintenance packet Qqemu.PhyMemMode:1" \ -# -ex "file $imageDir/vmlinux" diff --git a/linux/testvector-generation/disassembleBootTrace.py b/linux/testvector-generation/disassembleBootTrace.py deleted file mode 100755 index ac36fd36e..000000000 --- a/linux/testvector-generation/disassembleBootTrace.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -# -# disassembleBootTrace.py -# David_Harris@hmc.edu 22 November 2023 -# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -# -# Reads boottrace.log and disassembles the machine code -# - -import csv -import os -import re - -# read a file from sim/logs/boottrace.log and extract the second comma-separated field containing the instruction -print("Reading boottrace.log") -trace = [] -count = 0 -with open('../../sim/logs/boottrace.log') as f: - reader = csv.reader(f, delimiter=',') - for row in reader: - trace.append(row) - count = count + 1 - if count > 50000000: - break -f.close() - -print("Disassembling boottrace.log instructions") -# Write an assembly language file with the machine code -with (open('boottrace.S', 'w')) as f: - f.write('main:\n') - for row in trace: - instr = row[1] - # scrape off leading white space from instr - instr = instr.lstrip() - # check if last character indicates an compressed or uncompressed instruction - lastNibble = instr[-1] - if (lastNibble == '3' or lastNibble == '7' or lastNibble == 'b' or lastNibble == 'f'): - # uncompressed - f.write('.word 0x' + instr + '\n') - else: - # compressed - instr = instr[-4:] - f.write('.hword 0x' + instr + '\n') -f.close() - -# Then assemble and disassemble the file -os.system('riscv64-unknown-elf-gcc -march=rv64gqc_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64d -c boottrace.S') -os.system('riscv64-unknown-elf-objdump -D boottrace.o > boottrace.objdump') - -# Patch disassembly back into boottrace -print("Inserting disassembly into trace") -dumpedLines = [] -with (open('boottrace.objdump', 'r')) as f: - lines = f.readlines() - f.close() -lines = lines[7:] # skip header -p = r'[^:]*:\s*(\S*)\s*(.*)' -for line in lines: - match = re.search(p, line) - if (match): - dump = [match.group(1), match.group(2)] - dumpedLines.append(dump) - -linenum = 0 -for i in range(len(trace)): - row = trace[i] - row.insert(2, dumpedLines[i][1]) - -# write trace back to csv file -print("Writing trace back to boottrace_disasm.log") -with (open('boottrace_disasm.log', 'w')) as f: - writer = csv.writer(f) - writer.writerows(trace) -f.close() diff --git a/linux/testvector-generation/filterTrapsToInterrupts.py b/linux/testvector-generation/filterTrapsToInterrupts.py deleted file mode 100755 index 7476e110f..000000000 --- a/linux/testvector-generation/filterTrapsToInterrupts.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -import sys, os -from functools import reduce - -################ -# 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 - -def strip0x(num): - return num[2:] - -def stripZeroes(num): - num = num.strip('0') - if num=='': - return '0' - else: - return num - -############# -# Main Code # -############# -print("Begin filtering traps down to just external interrupts.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error filterTrapsToInterrupts.py expects 1 arg: ') -tvDir = sys.argv[1]+'/' -trapsFilePath = tvDir+'traps.txt' -if not os.path.exists(trapsFilePath): - sys.exit('Error input file '+trapsFilePath+'not found') - -with open(tvDir+'interrupts.txt', 'w') as interruptsFile: - with open(trapsFilePath, 'r') as trapsFile: - while True: - trap = trapsFile.readline() - if trap == '': - break - trapType = trap.split(' ')[-1] - if ('interrupt' in trap) and (('external' in trapType) or ('m_timer' in trapType)): # no s_timer because that is not controlled by CLINT - interruptsFile.write(trap) # overall line - interruptsFile.write(trapsFile.readline()) # attempted instr count - interruptsFile.write(trapsFile.readline()) # hart # - interruptsFile.write(trapsFile.readline()) # asynchronous - interruptsFile.write(trapsFile.readline()) # cause - interruptsFile.write(trapsFile.readline()) # epc - interruptsFile.write(trapsFile.readline()) # tval - interruptsFile.write(trapsFile.readline()) # description - else: - for i in range(7): - trapsFile.readline() - -print("Finished filtering traps down to just external interrupts.") diff --git a/linux/testvector-generation/genCheckpoint.sh b/linux/testvector-generation/genCheckpoint.sh deleted file mode 100755 index f12223f54..000000000 --- a/linux/testvector-generation/genCheckpoint.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/bash -tcpPort=1238 -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -traceFile="$tvDir/all.txt" - -# Parse Commandline Arg -if [ "$#" -ne 1 ]; then - echo "genCheckpoint requires 1 argument: " >&2 - exit 1 -fi -instrs=$1 -if ! [ "$instrs" -eq "$instrs" ] 2> /dev/null -then - echo "Error expected integer number of instructions, got $instrs" >&2 - exit 1 -fi - -checkPtDir="$tvDir/checkpoint$instrs" -outTraceFile="$checkPtDir/all.txt" -rawStateFile="$checkPtDir/stateGDB.txt" -rawUartStateFile="$checkPtDir/uartStateGDB.txt" -uartStateFile="$checkPtDir/checkpoint-UART" -rawPlicStateFile="$checkPtDir/plicStateGDB.txt" -plicStateFile="$checkPtDir/checkpoint-PLIC" -rawRamFile="$checkPtDir/ramGDB.bin" -ramFile="$checkPtDir/ram.bin" - -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 - echo "Creating checkpoint at $instrs instructions!" - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - mkdir -p $checkPtDir - - # Identify instruction in trace - instr=$(sed "${instrs}q;d" "$traceFile") - echo "Found ${instrs}th instr: ${instr}" - pc=$(echo $instr | cut -d " " -f1) - asm=$(echo $instr | cut -d " " -f2) - occurences=$(($(head -$instrs "$traceFile" | grep -c "${pc} ${asm}")-1)) - echo "It occurs ${occurences} times before the ${instrs}th instr." - - # Create GDB script because GDB is terrible at handling arguments / variables - cat > genCheckpoint.gdb <<- end_of_script - set pagination off - set logging overwrite on - set logging redirect on - set confirm off - target extended-remote :$tcpPort - maintenance packet Qqemu.PhyMemMode:1 - file $imageDir/vmlinux - # Step over reset vector into actual code - stepi 100 - shell echo \"GDB proceeding to checkpoint at $instrs instrs, pc $pc\" - b *0x$pc - ignore 1 $occurences - c - shell echo \"Reached checkpoint at $instrs instrs\" - shell echo \"GDB storing CPU state to $rawStateFile\" - set logging file $rawStateFile - set logging on - info all-registers - set logging off - shell echo \"GDB storing UART state to $rawUartStateFile\" - # Save value of LCR - set \$LCR=*0x10000003 & 0xff - set logging file $rawUartStateFile - set logging on - # Change LCR to set DLAB=0 to be able to read RBR and IER - set {char}0x10000003 &= ~0x80 - x/1xb 0x10000000 - x/1xb 0x10000001 - x/1xb 0x10000002 - # But log original value of LCR - printf "0x10000003:\t0x%02x\n", \$LCR - x/1xb 0x10000004 - x/1xb 0x10000005 - x/1xb 0x10000006 - x/1xb 0x10000007 - set logging off - shell echo \"GDB storing PLIC state to $rawPlicStateFile\" - shell echo \"Note: this dumping assumes a maximum of 63 PLIC sources\" - set logging file $rawPlicStateFile - set logging on - # Priority Levels for sources 1 thru 63 - x/63xw 0x0C000004 - # Interrupt Enables for sources 1 thru 63 for contexts 0 and 1 - x/2xw 0x0C002000 - x/2xw 0x0C002080 - # Global Priority Threshold for contexts 0 and 1 - x/1xw 0x0C200000 - x/1xw 0x0C201000 - set logging off - shell echo \"GDB storing RAM to $rawRamFile\" - dump binary memory $rawRamFile 0x80000000 0x87ffffff - kill - q -end_of_script - - # GDB+QEMU - echo "Starting QEMU in replay mode with attached GDB script at $(date +%H:%M:%S)" - (qemu-system-riscv64 \ - -M virt -dtb $imageDir/wally-virt.dtb \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \ - -gdb tcp::$tcpPort -S \ - 1>./qemu-serial) \ - & riscv64-unknown-elf-gdb --quiet -x genCheckpoint.gdb - - echo "Completed GDB script at $(date +%H:%M:%S)" - - # Post-Process GDB outputs - ./parseState.py "$checkPtDir" - ./parseUartState.py "$checkPtDir" - ./parsePlicState.py "$checkPtDir" - echo "Changing Endianness at $(date +%H:%M:%S)" - make fixBinMem - ./fixBinMem "$rawRamFile" "$ramFile" - echo "Copying over a truncated trace" - tail -n+$instrs $traceFile > $outTraceFile - - echo "Checkpoint completed at $(date +%H:%M:%S)" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi - diff --git a/linux/testvector-generation/genRecording.sh b/linux/testvector-generation/genRecording.sh deleted file mode 100755 index 2696253c5..000000000 --- a/linux/testvector-generation/genRecording.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -DEVICE_TREE=${imageDir}/wally-virt.dtb - -read -p "Warning: running this script will overwrite $recordFile -Would you like to proceed? (y/n) " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]] -then - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - echo "Launching QEMU in record mode!" - qemu-system-riscv64 \ - -M virt -m 256M -dtb $DEVICE_TREE \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=record,rrfile=$recordFile - - echo "genRecording.sh completed!" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi diff --git a/linux/testvector-generation/genTrace.sh b/linux/testvector-generation/genTrace.sh deleted file mode 100755 index 5d04592ce..000000000 --- a/linux/testvector-generation/genTrace.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -tcpPort=1234 -imageDir=$RISCV/buildroot/output/images -tvDir=$RISCV/linux-testvectors -recordFile="$tvDir/all.qemu" -traceFile="$tvDir/all.txt" -trapsFile="$tvDir/traps.txt" -interruptsFile="$tvDir/interrupts.txt" -DEVICE_TREE=${imageDir}/wally-virt.dtb - -read -p "Warning: running this script will overwrite the contents of: - * $traceFile - * $trapsFile - * $interruptsFile -Would you like to proceed? (y/n) " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]] -then - if [ ! -d "$tvDir" ]; then - echo "Error: linux testvector directory $tvDir not found!">&2 - echo "Please create it. For example:">&2 - echo " sudo mkdir -p $tvDir">&2 - exit 1 - fi - test -w $tvDir - if [ ! $? -eq 0 ]; then - echo "Error: insuffcient write privileges for linux testvector directory $tvDir !">&2 - echo "Please chmod it. For example:">&2 - echo " sudo chmod -R a+rw $tvDir">&2 - exit 1 - fi - - touch $traceFile - touch $trapsFile - touch $interruptsFile - - # QEMU Simulation - echo "Launching QEMU in replay mode!" - (qemu-system-riscv64 \ - -M virt -m 256M -dtb $DEVICE_TREE \ - -nographic \ - -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ - -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=replay,rrfile=$recordFile \ - -d nochain,cpu,in_asm,int \ - 2>&1 >./qemu-serial | ./parseQEMUtoGDB.py | ./parseGDBtoTrace.py $trapsFile > $traceFile) - - ./filterTrapsToInterrupts.py $tvDir - - echo "genTrace.sh completed!" - echo "You may want to restrict write access to $tvDir now and give cad ownership of it." - echo "Run the following:" - echo " sudo chown -R cad:cad $tvDir" - echo " sudo chmod -R go-w $tvDir" -fi diff --git a/linux/testvector-generation/parseGDBtoTrace.py b/linux/testvector-generation/parseGDBtoTrace.py deleted file mode 100755 index 96ad464ed..000000000 --- a/linux/testvector-generation/parseGDBtoTrace.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python3 -import sys, fileinput, re - -# Rose Thompson -# July 27, 2021 -# Rewrite of the linux trace parser. - - -InstrStartDelim = '=>' -InstrEndDelim = '-----' - -#InputFile = 'noparse.txt' -#InputFile = sys.stdin -#InputFile = 'temp.txt' -#OutputFile = 'parsedAll.txt' - -HUMAN_READABLE = False - -def toDict(lst): - 'Converts the list of register values to a dictionary' - dct= {} - for item in lst: - regTup = item.split() - dct[regTup[0]] = int(regTup[2], 10) - del dct['pc'] - return dct - -def whichClass(text, Regs): - 'Which instruction class?' - #print(text, Regs) - if text[0:2] == 'ld' or text[0:2] == 'lw' or text[0:2] == 'lh' or text[0:2] == 'lb': - return ('load', WhatAddr(text, Regs), None, WhatMemDestSource(text)) - elif text[0:2] == 'sd' or text[0:2] == 'sw' or text[0:2] == 'sh' or text[0:2] == 'sb': - return ('store', WhatAddr(text, Regs), WhatMemDestSource(text), None) - elif text[0:3] == 'amo': - return ('amo', WhatAddrAMO(text, Regs), WhatMemDestSource(text), WhatMemDestSource(text)) - elif text[0:2] == 'lr': - return ('lr', WhatAddrLR(text, Regs), None, WhatMemDestSource(text)) - elif text[0:2] == 'sc': - return ('sc', WhatAddrSC(text, Regs), WhatMemDestSource(text), None) - else: - return ('other', None, None, None) - -def whatChanged(dct0, dct1): - 'Compares two dictionaries of instrution registers and indicates which registers changed' - dct = {} - for key in dct0: - if (dct1[key] != dct0[key]): - dct[key] = dct1[key] - return dct - -def WhatMemDestSource(text): - ''''What is the destination register. Used to compute where the read data is - on a load or the write data on a store.''' - return text.split()[1].split(',')[0] - -def WhatAddr(text, Regs): - 'What is the data memory address?' - Imm = text.split(',')[1] - (Imm, Src) = Imm.split('(') - Imm = int(Imm.strip(), 10) - Src = Src.strip(')').strip() - RegVal = Regs[Src] - return Imm + RegVal - -def WhatAddrAMO(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def WhatAddrLR(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def WhatAddrSC(text, Regs): - 'What is the data memory address?' - Src = text.split('(')[1] - Src = Src.strip(')').strip() - return Regs[Src] - -def PrintInstr(instr): - if instr[2] == None: - return - ChangedRegisters = instr[4] - GPR = '' - CSR = [] - for key in ChangedRegisters: - # filter out csr which are not checked. - if(key in RegNumber): - if(RegNumber[key] < 32): - # GPR - if(HUMAN_READABLE): - GPR = '{:-2d} {:016x}'.format(RegNumber[key], ChangedRegisters[key]) - else: - GPR = '{:d} {:x}'.format(RegNumber[key], ChangedRegisters[key]) - else: - if(HUMAN_READABLE): - CSR.extend([key, '{:016x}'.format(ChangedRegisters[key])]) - else: - CSR.extend([key, '{:x}'.format(ChangedRegisters[key])]) - - CSRStr = ' '.join(CSR) - - #print(instr) - - if (HUMAN_READABLE == True): - outString='{:016x} {:08x} {:25s}'.format(instr[0], instr[1], instr[2]) - if(len(GPR) != 0): - outString+=' GPR {}'.format(GPR) - if(instr[3] == 'load' or instr[3] == 'lr'): - outString+=' MemR {:016x} {:016x} {:016x}'.format(instr[5], 0, instr[7]) - if(instr[3] == 'store'): - outString+='\t\t\t MemW {:016x} {:016x} {:016x}'.format(instr[5], instr[6], 0) - if(len(CSR) != 0): - outString+=' CSR {}'.format(CSRStr) - else: - outString='{:x} {:x} {:s}'.format(instr[0], instr[1], instr[2].replace(' ', '_')) - if(len(GPR) != 0): - outString+=' GPR {}'.format(GPR) - if(instr[3] == 'load' or instr[3] == 'lr'): - outString+=' MemR {:x} {:x} {:x}'.format(instr[5], 0, instr[7]) - if(instr[3] == 'store'): - outString+=' MemW {:x} {:x} {:x}'.format(instr[5], instr[6], 0) - if(len(CSR) != 0): - outString+=' CSR {}'.format(CSRStr) - outString+='\n' - return outString - -# ========= -# Main Code -# ========= -# Parse argument for interrupt file -if len(sys.argv) != 2: - sys.exit('Error parseGDBtoTrace.py expects 1 arg:\n >') -interruptFname = sys.argv[1] -# reg number -RegNumber = {'zero': 0, 'ra': 1, 'sp': 2, 'gp': 3, 'tp': 4, 't0': 5, 't1': 6, 't2': 7, 's0': 8, 's1': 9, 'a0': 10, 'a1': 11, 'a2': 12, 'a3': 13, 'a4': 14, 'a5': 15, 'a6': 16, 'a7': 17, 's2': 18, 's3': 19, 's4': 20, 's5': 21, 's6': 22, 's7': 23, 's8': 24, 's9': 25, 's10': 26, 's11': 27, 't3': 28, 't4': 29, 't5': 30, 't6': 31, 'mhartid': 32, 'mstatus': 33, 'mip': 34, 'mie': 35, 'mideleg': 36, 'medeleg': 37, 'mtvec': 38, 'stvec': 39, 'mepc': 40, 'sepc': 41, 'mcause': 42, 'scause': 43, 'mtval': 44, 'stval': 45, 'mscratch': 46, 'sscratch': 47, 'satp': 48} -# initial state -CurrentInstr = ['0', '0', None, 'other', {'zero': 0, 'ra': 0, 'sp': 0, 'gp': 0, 'tp': 0, 't0': 0, 't1': 0, 't2': 0, 's0': 0, 's1': 0, 'a0': 0, 'a1': 0, 'a2': 0, 'a3': 0, 'a4': 0, 'a5': 0, 'a6': 0, 'a7': 0, 's2': 0, 's3': 0, 's4': 0, 's5': 0, 's6': 0, 's7': 0, 's8': 0, 's9': 0, 's10': 0, 's11': 0, 't3': 0, 't4': 0, 't5': 0, 't6': 0, 'mhartid': 0, 'mstatus': 0, 'mip': 0, 'mie': 0, 'mideleg': 0, 'medeleg': 0, 'mtvec': 0, 'stvec': 0, 'mepc': 0, 'sepc': 0, 'mcause': 0, 'scause': 0, 'mtval': 0, 'stval': 0, 'mscratch': 0, 'sscratch': 0, 'satp': 0}, {}, None, None, None] - -#with open (InputFile, 'r') as InputFileFP: -#lines = InputFileFP.readlines() -lineNum = 0 -StartLine = 0 -EndLine = 0 -numInstrs = 0 -#instructions = [] -MemAdr = 0 -lines = [] -interrupts=open(interruptFname,'w') -interrupts.close() - -prevInstrOutString='' -currInstrOutString='' -for line in fileinput.input('-'): - if line.startswith('riscv_cpu_do_interrupt'): - with open(interruptFname,'a') as interrupts: - # Write line - # Example line: hart:0, async:0, cause:0000000000000002, epc:0x0000000080008548, tval:0x0000000000000000, desc=illegal_instruction - interrupts.write(line) - # Write instruction count - interrupts.write(str(numInstrs)+'\n') - # Convert line to rows of info for easier Verilog parsing - vals=line.strip('riscv_cpu_do_interrupt: ').strip('\n').split(',') - vals=[val.split(':')[-1].strip(' ') for val in vals] - vals=[val.split('=')[-1].strip(' ') for val in vals] - for val in vals: - interrupts.write(val+'\n') - continue - lines.insert(lineNum, line) - if InstrStartDelim in line: - lineNum = 0 - StartLine = lineNum - elif InstrEndDelim in line: - EndLine = lineNum - (InstrBits, text) = lines[StartLine].split(':') - InstrBits = int(InstrBits.strip('=> '), 16) - text = text.strip() - PC = int(lines[StartLine+1].split(':')[0][2:], 16) - Regs = toDict(lines[StartLine+2:EndLine]) - (Class, Addr, WriteReg, ReadReg) = whichClass(text, Regs) - #print("CWR", Class, WriteReg, ReadReg) - PreviousInstr = CurrentInstr - - Changed = whatChanged(PreviousInstr[4], Regs) - - if (ReadReg !=None): ReadData = ReadReg - else: ReadData = None - - if (WriteReg !=None): WriteData = WriteReg - else: WriteData = None - - CurrentInstr = [PC, InstrBits, text, Class, Regs, Changed, Addr, WriteData, ReadData] - - #print(CurrentInstr[0:4], PreviousInstr[5], CurrentInstr[6:7], PreviousInstr[8]) - - # pc, instrbits, text and class come from the last line. - MoveInstrToRegWriteLst = PreviousInstr[0:4] - # updated registers come from the current line. - MoveInstrToRegWriteLst.append(CurrentInstr[5]) # destination regs - # memory address if present comes from the last line. - MoveInstrToRegWriteLst.append(PreviousInstr[6]) # MemAdrM - # write data from the previous line - #MoveInstrToRegWriteLst.append(PreviousInstr[7]) # WriteDataM - - if (PreviousInstr[7] != None): - MoveInstrToRegWriteLst.append(Regs[PreviousInstr[7]]) # WriteDataM - else: - MoveInstrToRegWriteLst.append(None) - - # read data from the current line - #MoveInstrToRegWriteLst.append(PreviousInstr[8]) # ReadDataM - if (PreviousInstr[8] != None): - MoveInstrToRegWriteLst.append(Regs[PreviousInstr[8]]) # ReadDataM - else: - MoveInstrToRegWriteLst.append(None) - - lines.clear() - #instructions.append(MoveInstrToRegWriteLst) - - prevInstrOutString = currInstrOutString - currInstrOutString = PrintInstr(MoveInstrToRegWriteLst) - # Remove duplicates - if (PreviousInstr[0] != CurrentInstr[0]) and (currInstrOutString != None): - sys.stdout.write(currInstrOutString) - numInstrs += 1 - if (numInstrs % 1e5 == 0): - sys.stderr.write('GDB trace parser reached '+str(numInstrs/1.0e6)+' million instrs.\n') - sys.stderr.flush() - lineNum += 1 - - -#for instruction in instructions[1::]: - - -#with open(OutputFile, 'w') as OutputFileFP: -# print('opened file') - - - diff --git a/linux/testvector-generation/parsePlicState.py b/linux/testvector-generation/parsePlicState.py deleted file mode 100755 index 5fb2b4eac..000000000 --- a/linux/testvector-generation/parsePlicState.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 -import sys, os -from functools import reduce - -################ -# 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 - -def strip0x(num): - return num[2:] - -def stripZeroes(num): - num = int(num,16) - return hex(num)[2:] - -############# -# Main Code # -############# -print("Begin parsing PLIC state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parsePlicState.py expects 1 arg: ') -outDir = sys.argv[1]+'/' -rawPlicStateFile = outDir+'plicStateGDB.txt' -if not os.path.exists(rawPlicStateFile): - sys.exit('Error input file '+rawPlicStateFile+'not found') - -with open(rawPlicStateFile, 'r') as rawPlicStateFile: - plicIntPriorityArray = [] # iterates over number of different sources - # 0x0C000004 thru 0x0C000010 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000014 thru 0x0C000020 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000024 thru 0x0C000030 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000034 thru 0x0C000040 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000044 thru 0x0C000050 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000054 thru 0x0C000060 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000064 thru 0x0C000070 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000074 thru 0x0C000080 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000084 thru 0x0C000090 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C000094 thru 0x0C0000a0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000a4 thru 0x0C0000b0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000b4 thru 0x0C0000c0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000c4 thru 0x0C0000d0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000d4 thru 0x0C0000e0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000e4 thru 0x0C0000f0 - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C0000f4 thru 0x0C0000fc - plicIntPriorityArray += tokenize(rawPlicStateFile.readline())[1:] - - plicIntEnableArray = [] # iterates over number of different contexts - # 0x0C020000 thru 0x0C020004 - plicIntEnable = tokenize(rawPlicStateFile.readline())[1:] - plicIntEnable = map(strip0x,plicIntEnable) - plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable)) - # 0x0C020080 thru 0x0C020084 - plicIntEnable = tokenize(rawPlicStateFile.readline())[1:] - plicIntEnable = map(strip0x,plicIntEnable) - plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable)) - - plicIntPriorityThresholdArray = [] # iterates over number of different contexts - # 0x0C200000 - plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:] - # 0x0C201000 - plicIntPriorityThresholdArray += tokenize(rawPlicStateFile.readline())[1:] - -with open(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile: - for word in plicIntPriorityArray: - outFile.write(stripZeroes(word[2:])+'\n') -with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile: - for word in plicIntEnableArray: - outFile.write(stripZeroes(word[2:])+'\n') -with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile: - for word in plicIntPriorityThresholdArray: - outFile.write(stripZeroes(word[2:])+'\n') - -print("Finished parsing PLIC state!") diff --git a/linux/testvector-generation/parseQEMUtoGDB.py b/linux/testvector-generation/parseQEMUtoGDB.py deleted file mode 100755 index 457085a1b..000000000 --- a/linux/testvector-generation/parseQEMUtoGDB.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 -import fileinput, sys - -parseState = "idle" -beginPageFault = 0 -inPageFault = 0 -endPageFault = 0 -CSRs = {} -pageFaultCSRs = {} -regs = {} -pageFaultRegs = {} -instrs = {} -instrCount = 0 -returnAdr = 0 -sys.stderr.write("reminder: parse_qemu.py takes input from stdin\n") - -def printPC(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount - if not inPageFault: - inst = l.split() - if len(inst) > 3: - print(f'=> {inst[1]}:\t{inst[2]} {inst[3]}') - else: - print(f'=> {inst[1]}:\t{inst[2]}') - print(f'{inst[0]} 0x{inst[1]}') - instrCount += 1 - if ((instrCount % 100000) == 0): - sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n") - -def printCSRs(): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs - global interrupt_line - if not inPageFault: - for (csr,val) in CSRs.items(): - print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val)) - print('-----') # end of current instruction - if len(interrupt_line)>0: # squish interrupts in between instructions - print(interrupt_line) - interrupt_line="" - -def parseCSRs(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs - if l.strip() and (not l.startswith("Disassembler")) and (not l.startswith("Please")): - # If we've hit the register file - if l.startswith(' x0/zero'): - parseState = "regFile" - if not inPageFault: - instr = instrs[CSRs["pc"]] - printPC(instr) - parseRegs(l) - # If we've hit a CSR - else: - csr = l.split()[0] - val = int(l.split()[1],16) - # Commented out this conditional because the pageFault instrs don't corrupt CSRs - #if inPageFault: - # Not sure if these CSRs should be updated or not during page fault. - #if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"): - # We do update some CSRs - # CSRs[csr] = val - #else: - # Others we preserve until changed later - # pageFaultCSRs[csr] = val - #elif pageFaultCSRs and (csr in pageFaultCSRs): - # if (val != pageFaultCSRs[csr]): - # del pageFaultCSRs[csr] - # CSRs[csr] = val - #else: - # CSRs[csr] = val - # - # However SEPC and STVAL do get corrupted upon exiting - if endPageFault and ((csr == 'sepc') or (csr == 'stval')): - CSRs[csr] = returnAdr - pageFaultCSRs[csr] = val - elif pageFaultCSRs and (csr in pageFaultCSRs): - if (val != pageFaultCSRs[csr]): - del pageFaultCSRs[csr] - CSRs[csr] = val - else: - CSRs[csr] = val - -def parseRegs(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, pageFaultRegs - if "pc" in l: - printCSRs() - # New non-disassembled instruction - parseState = "CSRs" - parseCSRs(l) - elif l.startswith('--------'): - # End of disassembled instruction - printCSRs() - parseState = "idle" - else: - s = l.split() - for i in range(0,len(s),2): - if '/' in s[i]: - reg = s[i].split('/')[1] - val = int(s[i+1], 16) - if inPageFault: - pageFaultRegs[reg] = val - else: - if pageFaultRegs and (reg in pageFaultRegs): - if (val != pageFaultRegs[reg]): - del pageFaultRegs[reg] - regs[reg] = val - else: - regs[reg] = val - val = regs[reg] - print('{}{}{:#x} {}'.format(reg, ' '*(15-len(reg)), val, val)) - else: - sys.stderr.write("Whoops. Expected a list of reg file regs; got:\n"+l) - -############# -# Main Code # -############# -interrupt_line="" -for l in fileinput.input(): - #sys.stderr.write(l) - if l.startswith('riscv_cpu_do_interrupt'): - sys.stderr.write(l) - interrupt_line = l.strip('\n') - elif l.startswith('qemu-system-riscv64: QEMU: Terminated via GDBstub'): - break - elif l.startswith('IN:'): - # New disassembled instr - parseState = "instr" - elif (parseState == "instr") and l.startswith('0x'): - # New instruction - if "out of bounds" in l: - sys.stderr.write("Detected QEMU page fault error\n") - beginPageFault = not inPageFault - if beginPageFault: - returnAdr = int(l.split()[0][2:-1], 16) - sys.stderr.write('Saving SEPC of '+hex(returnAdr)+'\n') - inPageFault = 1 - else: - endPageFault = inPageFault - inPageFault = 0 - adr = int(l.split()[0][2:-1], 16) - instrs[adr] = l - parseState = "CSRs" - elif parseState == "CSRs": - parseCSRs(l) - elif parseState == "regFile": - parseRegs(l) diff --git a/linux/testvector-generation/parseState.py b/linux/testvector-generation/parseState.py deleted file mode 100755 index f54ba0f78..000000000 --- a/linux/testvector-generation/parseState.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -import sys, os - -################ -# 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 CPU state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parseState.py expects 1 arg:\n parseState.py ') -outDir = sys.argv[1]+'/' -stateGDBpath = outDir+'stateGDB.txt' -if not os.path.exists(stateGDBpath): - sys.exit('Error input file '+stateGDBpath+'not found') - -singleCSRs = ['pc','mip','mie','mscratch','mcause','mepc','mtvec','medeleg','mideleg','sscratch','scause','sepc','stvec','sedeleg','sideleg','satp','mstatus','priv','sie','sip','sstatus'] -# priv (current privilege mode) isn't technically a CSR but we can log it with the same machinery -thirtyTwoBitCSRs = ['mcounteren','scounteren'] -listCSRs = ['hpmcounter','pmpaddr'] -pmpcfg = ['pmpcfg'] - -# Initialize List CSR files to empty -# (because later we'll open them in append mode) -for csr in listCSRs+pmpcfg: - outFileName = 'checkpoint-'+csr.upper() - outFile = open(outDir+outFileName, 'w') - outFile.close() - -# Initial State for Main Loop -currState = 'regFile' -regFileIndex = 0 -outFileName = 'checkpoint-RF' -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) - if (name != 'zero'): - # Wally doesn't need to know zero=0 - 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 in thirtyTwoBitCSRs: - outFileName = 'checkpoint-'+name.upper() - outFile = open(outDir+outFileName, 'w') - val = int(val,16) & 0xffffffff - outFile.write(hex(val)[2:]+'\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() - elif name.strip('0123456789') in pmpcfg: - outFileName = 'checkpoint-'+name.upper().strip('0123456789') - outFile = open(outDir+outFileName, 'a') - fourPmp = int(val,16) - for i in range(0,4): - byte = (fourPmp >> 8*i) & 0xff - outFile.write(hex(byte)[2:]+'\n') - outFile.close() - -print("Finished parsing CPU state!") diff --git a/linux/testvector-generation/parseUartState.py b/linux/testvector-generation/parseUartState.py deleted file mode 100755 index 82028d528..000000000 --- a/linux/testvector-generation/parseUartState.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -import sys, os - -################ -# 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 UART state.") - -# Parse Args -if len(sys.argv) != 2: - sys.exit('Error parseUartState.py expects 1 arg: ') -outDir = sys.argv[1]+'/' -rawUartStateFile = outDir+'uartStateGDB.txt' -if not os.path.exists(rawUartStateFile): - sys.exit('Error input file '+rawUartStateFile+'not found') - -with open(rawUartStateFile, 'r') as rawUartStateFile: - uartBytes = [] - for i in range(0,8): - uartBytes += tokenize(rawUartStateFile.readline())[1:] -with open(outDir+'checkpoint-UART_IER', 'w') as outFile: - outFile.write(uartBytes[1][2:]) -with open(outDir+'checkpoint-UART_LCR', 'w') as outFile: - outFile.write(uartBytes[3][2:]) -with open(outDir+'checkpoint-UART_MCR', 'w') as outFile: - outFile.write(uartBytes[4][2:]) -with open(outDir+'checkpoint-UART_SCR', 'w') as outFile: - outFile.write(uartBytes[7][2:]) - -print("Finished parsing UART state!") diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index ab9cad093..d04fc45fa 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -248,9 +248,9 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( // coverage off // Not covered in testing because rv64gc is not RV64Q or RV32D 7'b1011001: if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct3D == 3'b000) - ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0_0; // fmvp.d.x (Zfa) + ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_1_0; // fmvp.d.x (Zfa) 7'b1011011: if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct3D == 3'b000) - ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0_0; // fmvp.q.x (Zfa) + ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_1_0; // fmvp.q.x (Zfa) // coverage on endcase endcase diff --git a/src/ifu/fetchbuffer.sv b/src/ifu/fetchbuffer.sv index d532aa51f..2efd2a6c0 100644 --- a/src/ifu/fetchbuffer.sv +++ b/src/ifu/fetchbuffer.sv @@ -47,19 +47,6 @@ module fetchbuffer import cvw::*; #(parameter cvw_t P) ( flopenl #(32) f1 (.clk, .load(reset | FlushD), .en(WritePtr[1]), .d(WriteData), .val(nop), .q(Readf1)); flopenl #(32) f2 (.clk, .load(reset | FlushD), .en(WritePtr[2]), .d(WriteData), .val(nop), .q(Readf2)); - // always_comb begin : readMuxes - // // Mux read data from the three registers - // case (ReadPtr) - // 3'b001: ReadFetchBuffer = Readf0; - // 3'b010: ReadFetchBuffer = Readf1; - // 3'b100: ReadFetchBuffer = Readf2; - // default: ReadFetchBuffer = nop; // just in case? - // endcase - // // issue nop when appropriate - // ReadData = Empty ? nop : ReadFetchBuffer; - // end - - // Fetch buffer entries anded with read ptr for AO Muxing logic [31:0] DaoArr [2:0]; // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make parameterizable diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index 293c2c2b5..9b15839e7 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -48,7 +48,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( output logic SPICLK ); - // register map + // register map localparam SPI_SCKDIV = 8'h00; localparam SPI_SCKMODE = 8'h04; localparam SPI_CSID = 8'h10; @@ -85,11 +85,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // SPI Controller signals logic SCLKenable; logic EndOfFrame; - logic EndOfFrameDelay; logic Transmitting; logic InactiveState; logic [3:0] FrameLength; + // Starting Transmission and restarting SCLKenable logic ResetSCLKenable; logic TransmitStart; logic TransmitStartD; @@ -98,16 +98,19 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( typedef enum logic [1:0] {READY, START, WAIT} txState; txState CurrState, NextState; - // FIFO FSM signals - // Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] - logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; - logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement; - logic [7:0] TransmitFIFOReadData; + // FIFO Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1] + logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark; + // Transmit FIFO Signals + logic TransmitFIFOFull, TransmitFIFOEmpty; + logic TransmitFIFOWriteInc; + logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic [7:0] TransmitReadData; + + // ReceiveFIFO Signals logic ReceiveFIFOWriteInc; - logic ReceiveFIFOReadIncrement; - logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; + logic ReceiveFIFOReadInc; + logic ReceiveFIFOFull, ReceiveFIFOEmpty; /* verilator lint_off UNDRIVEN */ logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs @@ -115,16 +118,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) // Shift reg signals - logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg - logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg - logic [7:0] TransmitReg; // Transmit shift register + logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg + logic SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg + logic [7:0] TransmitReg; // Transmit shift register logic [7:0] ReceiveShiftReg; // Receive shift register logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB - logic TransmitLoad; // Determines when to load TransmitReg - logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read + logic TransmitLoad; // Determines when to load TransmitReg + logic TransmitRegLoaded; // Shift stuff due to Format register? - logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) + logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST) logic [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian logic [7:0] ASR; // AlignedReceiveShiftReg @@ -135,7 +138,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // APB access assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase - // assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP; assign PREADY = 1'b1; // Account for subword read/write circuitry @@ -162,7 +164,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( InterruptEnable <= 2'b0; InterruptPending <= 2'b0; end else begin // writes - /* verilator lint_off CASEINCOMPLETE */ + /* verilator lint_off CASEINCOMPLETE */ if (Memwrite) case(Entry) // flop to sample inputs SPI_SCKDIV: SckDiv <= Din[11:0]; @@ -180,14 +182,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if (Memwrite) case(Entry) - SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; + SPI_TXDATA: if (~TransmitFIFOFull) TransmitData[7:0] <= Din[7:0]; endcase /* verilator lint_off CASEINCOMPLETE */ // According to FU540 spec: Once interrupt is pending, it will remain set until number // of entries in tx/rx fifo is strictly more/less than tx/rxmark InterruptPending[0] <= TransmitReadMark; - InterruptPending[1] <= RecieveWriteMark; + InterruptPending[1] <= ReceiveWriteMark; case(Entry) // Flop to sample inputs SPI_SCKDIV: Dout <= {20'b0, SckDiv}; @@ -198,8 +200,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( SPI_DELAY0: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; SPI_DELAY1: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; SPI_FMT: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; - SPI_TXDATA: Dout <= {TransmitFIFOWriteFull, 23'b0, 8'b0}; - SPI_RXDATA: Dout <= {ReceiveFIFOReadEmpty, 23'b0, ReceiveData[7:0]}; + SPI_TXDATA: Dout <= {TransmitFIFOFull, 23'b0, 8'b0}; + SPI_RXDATA: Dout <= {ReceiveFIFOEmpty, 23'b0, ReceiveData[7:0]}; SPI_TXMARK: Dout <= {29'b0, TransmitWatermark}; SPI_RXMARK: Dout <= {29'b0, ReceiveWatermark}; SPI_IE: Dout <= {30'b0, InterruptEnable}; @@ -208,11 +210,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end - // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) - // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv - // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase - // When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). - // SPI Controller module ------------------------------------------- // This module controls state and timing signals that drive the rest of this module assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV); @@ -220,59 +217,51 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( spi_controller controller(PCLK, PRESETn, // Transmit Signals - TransmitStart, TransmitStartD, ResetSCLKenable, + TransmitStart, TransmitRegLoaded, ResetSCLKenable, // Register Inputs SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength, // txFIFO stuff - TransmitFIFOReadEmpty, + TransmitFIFOEmpty, // Timing - SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay, + SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, // State stuff Transmitting, InactiveState, // Outputs SPICLK); // Transmit FIFO --------------------------------------------------- - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOWriteIncrement <= 1'b0; - end else begin - TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - TransmitFIFOReadIncrement <= 1'b0; - end else if (SCLKenable) begin - TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ; - end + // txFIFO write increment logic + flopr #(1) txwincreg(PCLK, ~PRESETn, + (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull), + TransmitFIFOWriteInc); + // txFIFO read increment logic + flopenr #(1) txrincreg(PCLK, ~PRESETn, SCLKenable, + TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty), + TransmitFIFOReadInc); + // Check whether TransmitReg has been loaded. // We use this signal to prevent returning to the Ready state for TransmitStart - logic TransmitRegLoaded; always_ff @(posedge PCLK) begin if (~PRESETn) begin TransmitRegLoaded <= 1'b0; end else if (TransmitLoad) begin TransmitRegLoaded <= 1'b1; - end else if (ShiftEdge | EndOfFrameDelay) begin + end else if (ShiftEdge | EndOfFrame) begin TransmitRegLoaded <= 1'b0; end end - + // Setup TransmitStart state machine - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - CurrState <= READY; - end else begin - CurrState <= NextState; - end - end + always_ff @(posedge PCLK) + if (~PRESETn) CurrState <= READY; + else CurrState <= NextState; // State machine for starting transmissions always_comb begin case (CurrState) - READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START; + READY: if (~TransmitFIFOEmpty & ~Transmitting) NextState = START; else NextState = READY; START: NextState = WAIT; WAIT: if (~Transmitting & ~TransmitRegLoaded) NextState = READY; @@ -281,49 +270,48 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase end + // Delayed TransmitStart signal for incrementing tx read point. assign TransmitStart = (CurrState == START); always_ff @(posedge PCLK) if (~PRESETn) TransmitStartD <= 1'b0; else if (TransmitStart) TransmitStartD <= 1'b1; else if (SCLKenable) TransmitStartD <= 1'b0; - + + // Transmit FIFO spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, - TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, + TransmitFIFOWriteInc, TransmitFIFOReadInc, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], - TransmitFIFOReadData[7:0], - TransmitFIFOWriteFull, - TransmitFIFOReadEmpty, + TransmitReadData[7:0], + TransmitFIFOFull, + TransmitFIFOEmpty, TransmitWriteMark, TransmitReadMark); - // Receive FIFO ---------------------------------------------------- - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOReadIncrement <= 1'b0; - end else begin - ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); - end - always_ff @(posedge PCLK) - if (~PRESETn) begin - ReceiveFIFOWriteInc <= 1'b0; - end else if (SCLKenable) begin - ReceiveFIFOWriteInc <= EndOfFrameDelay; - end + // Receive FIFO Read Increment register + flopr #(1) rxfiforincreg(PCLK, ~PRESETn, + ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc), + ReceiveFIFOReadInc); + // Receive FIFO Write Increment register + flopenr #(1) rxfifowincreg(PCLK, ~PRESETn, SCLKenable, + EndOfFrame, ReceiveFIFOWriteInc); + + // Receive FIFO spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, - ReceiveFIFOWriteInc, ReceiveFIFOReadIncrement, + ReceiveFIFOWriteInc, ReceiveFIFOReadInc, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], - ReceiveFIFOWriteFull, - ReceiveFIFOReadEmpty, - RecieveWriteMark, RecieveReadMark); + ReceiveFIFOFull, + ReceiveFIFOEmpty, + ReceiveWriteMark, ReceiveReadMark); + // Shift Registers -------------------------------------------------- // Transmit shift register - assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~TransmitFIFOReadEmpty); - assign TransmitDataEndian = Format[0] ? {<<{TransmitFIFOReadData[7:0]}} : TransmitFIFOReadData[7:0]; + assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty); + assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0]; always_ff @(posedge PCLK) if(~PRESETn) TransmitReg <= 8'b0; else if (TransmitLoad) TransmitReg <= TransmitDataEndian; @@ -342,12 +330,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if(~PRESETn) begin ReceiveShiftReg <= 8'b0; end else if (SampleEdge) begin - if (~Transmitting) ReceiveShiftReg <= 8'b0; - else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; + ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn}; end // Aligns received data and reverses if little-endian - assign LeftShiftAmount = 4'h8 - Format[4:1]; + assign LeftShiftAmount = 4'h8 - FrameLength; assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0]; diff --git a/src/uncore/spi_controller.sv b/src/uncore/spi_controller.sv index 19b32cab3..37c1e3ac9 100644 --- a/src/uncore/spi_controller.sv +++ b/src/uncore/spi_controller.sv @@ -33,7 +33,7 @@ module spi_controller ( // Start Transmission input logic TransmitStart, - input logic TransmitStartD, + input logic TransmitRegLoaded, input logic ResetSCLKenable, // Registers @@ -45,14 +45,13 @@ module spi_controller ( input logic [3:0] FrameLength, // Is the Transmit FIFO Empty? - input logic txFIFOReadEmpty, + input logic TransmitFIFOEmpty, // Control signals output logic SCLKenable, output logic ShiftEdge, output logic SampleEdge, - output logic EndOfFrame, - output logic EndOfFrameDelay, + output logic EndOfFrame, output logic Transmitting, output logic InactiveState, output logic SPICLK @@ -63,43 +62,31 @@ module spi_controller ( localparam AUTOMODE = 2'b00; localparam OFFMODE = 2'b11; + // FSM States typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; statetype CurrState, NextState; // SCLKenable stuff logic [11:0] DivCounter; - // logic SCLKenable; - // logic SCLKenableEarly; - logic ZeroDiv; - logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK! - + logic SCK; // Shift and Sample Edges - logic PreShiftEdge; - logic PreSampleEdge; - // logic ShiftEdge; - // logic SampleEdge; + logic EdgePulse; logic ShiftEdgePulse; logic SampleEdgePulse; logic EndOfFramePulse; + logic PhaseOneOffset; // Frame stuff logic [3:0] BitNum; logic LastBit; - //logic EndOfFrame; - //logic EndOfFrameDelay; - logic PhaseOneOffset; // Transmit Stuff logic ContinueTransmit; - - // SPIOUT Stuff - // logic TransmitLoad; - logic [7:0] TransmitReg; - //logic Transmitting; logic EndTransmission; - - logic HoldMode; + // logic TransmitRegLoaded; // TODO: Could be replaced by TransmitRegLoaded? + logic NextEndDelay; + logic CurrentEndDelay; // Delay Stuff logic [7:0] cssck; @@ -116,13 +103,12 @@ module spi_controller ( logic EndOfSCKCS; logic EndOfINTERCS; logic EndOfINTERXFR; + logic EndOfDelay; - logic [7:0] CSSCKCounter; - logic [7:0] SCKCSCounter; - logic [7:0] INTERCSCounter; - logic [7:0] INTERXFRCounter; + logic [7:0] DelayCounter; logic DelayIsNext; + logic DelayState; // Convenient Delay Reg Names assign cssck = Delay0[7:0]; @@ -137,23 +123,25 @@ module spi_controller ( assign HasINTERXFR = interxfr > 8'b0; // Have we hit full delay for any of the delays? - assign EndOfCSSCK = CSSCKCounter == cssck; - assign EndOfSCKCS = SCKCSCounter == sckcs; - assign EndOfINTERCS = INTERCSCounter == intercs; - assign EndOfINTERXFR = INTERXFRCounter == interxfr; + assign EndOfCSSCK = (DelayCounter == cssck) & (CurrState == CSSCK); + assign EndOfSCKCS = (DelayCounter == sckcs) & (CurrState == SCKCS); + assign EndOfINTERCS = (DelayCounter == intercs) & (CurrState == INTERCS); + assign EndOfINTERXFR = (DelayCounter == interxfr) & (CurrState == INTERXFR); + + assign EndOfDelay = EndOfCSSCK | EndOfSCKCS | EndOfINTERCS | EndOfINTERXFR; // Clock Signal Stuff ----------------------------------------------- // I'm going to handle all clock stuff here, including ShiftEdge and // SampleEdge. This makes sure that SPICLK is an output of a register // and it properly synchronizes signals. - - assign SCLKenable = DivCounter == SckDiv; - // assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv; - assign LastBit = (BitNum == FrameLength - 4'b1); - //assign EndOfFrame = SCLKenable & LastBit & Transmitting; - assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay; - assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay; + // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) + // Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv + // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase + assign SCLKenable = DivCounter == SckDiv; + + assign ContinueTransmit = ~TransmitFIFOEmpty & EndOfFrame; + assign EndTransmission = TransmitFIFOEmpty & EndOfFrame; always_ff @(posedge PCLK) begin if (~PRESETn) begin @@ -161,44 +149,20 @@ module spi_controller ( SPICLK <= SckMode[1]; SCK <= 0; BitNum <= 4'h0; - PreShiftEdge <= 0; - PreSampleEdge <= 0; - EndOfFrame <= 0; - CSSCKCounter <= 0; - SCKCSCounter <= 0; - INTERCSCounter <= 0; - INTERXFRCounter <= 0; + DelayCounter <= 0; end else begin - // TODO: Consolidate into one delay counter since none of the - // delays happen at the same time? + // SCK logic for delay times if (TransmitStart) begin SCK <= 0; end else if (SCLKenable) begin SCK <= ~SCK; end - - if ((CurrState == CSSCK) & SCK & SCLKenable) begin - CSSCKCounter <= CSSCKCounter + 8'd1; - end else if (SCLKenable & EndOfCSSCK) begin - CSSCKCounter <= 8'd0; - end - - if ((CurrState == SCKCS) & SCK & SCLKenable) begin - SCKCSCounter <= SCKCSCounter + 8'd1; - end else if (SCLKenable & EndOfSCKCS) begin - SCKCSCounter <= 8'd0; - end - - if ((CurrState == INTERCS) & SCK & SCLKenable) begin - INTERCSCounter <= INTERCSCounter + 8'd1; - end else if (SCLKenable & EndOfINTERCS) begin - INTERCSCounter <= 8'd0; - end - - if ((CurrState == INTERXFR) & SCK & SCLKenable) begin - INTERXFRCounter <= INTERXFRCounter + 8'd1; - end else if (SCLKenable & EndOfINTERXFR) begin - INTERXFRCounter <= 8'd0; + + // Counter for all four delay types + if (DelayState & SCK & SCLKenable) begin + DelayCounter <= DelayCounter + 8'd1; + end else if (SCLKenable & EndOfDelay) begin + DelayCounter <= 8'd0; end // SPICLK Logic @@ -215,95 +179,69 @@ module spi_controller ( DivCounter <= DivCounter + 12'd1; end - // EndOfFrame controller - // if (SckDiv > 0 ? SCLKenableEarly & LastBit & SPICLK : LastBit & ~SPICLK) begin - // EndOfFrame <= 1'b1; - // end else begin - // EndOfFrame <= 1'b0; - // end - - // TODO: Rename EndOfFrameDelay to EndOfFrame and remove this logic - if (~TransmitStart) begin - EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; - end - // Increment BitNum if (ShiftEdge & Transmitting) begin BitNum <= BitNum + 4'd1; - end else if (EndOfFrameDelay) begin + end else if (EndOfFrame) begin BitNum <= 4'b0; end end end + // The very last bit in a frame of any length. + assign LastBit = (BitNum == FrameLength - 4'b1); + + // Any SCLKenable pulse aligns with leading or trailing edge during + // Transmission. We can use this signal as the basis for ShiftEdge + // and SampleEdge. + assign EdgePulse = SCLKenable & Transmitting; + + // Possible pulses for all edge types. Combined with SPICLK to get + // edges for different phase and polarity modes. + assign ShiftEdgePulse = EdgePulse & ~LastBit; + assign SampleEdgePulse = EdgePulse & ~DelayIsNext; + assign EndOfFramePulse = EdgePulse & LastBit; + // Delay ShiftEdge and SampleEdge by a half PCLK period // Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges. // Sweeeeeeeeeet... - - assign ShiftEdgePulse = SCLKenable & ~LastBit & Transmitting; - assign SampleEdgePulse = SCLKenable & Transmitting & ~DelayIsNext; - assign EndOfFramePulse = SCLKenable & LastBit & Transmitting; - always_ff @(posedge ~PCLK) begin if (~PRESETn | TransmitStart) begin ShiftEdge <= 0; PhaseOneOffset <= 0; SampleEdge <= 0; - EndOfFrameDelay <= 0; + EndOfFrame <= 0; end else begin - PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay; + PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrame; case(SckMode) 2'b00: begin ShiftEdge <= SPICLK & ShiftEdgePulse; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end 2'b01: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b10: begin ShiftEdge <= ~SPICLK & ShiftEdgePulse; SampleEdge <= SPICLK & SampleEdgePulse; - EndOfFrameDelay <= ~SPICLK & EndOfFramePulse; + EndOfFrame <= ~SPICLK & EndOfFramePulse; end 2'b11: begin ShiftEdge <= SPICLK & ShiftEdgePulse & PhaseOneOffset; SampleEdge <= ~SPICLK & SampleEdgePulse; - EndOfFrameDelay <= SPICLK & EndOfFramePulse; + EndOfFrame <= SPICLK & EndOfFramePulse; end - // ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset; - // PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay; - // SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext; - // EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting; endcase end end - // typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype; - // statetype CurrState, NextState; - - assign HoldMode = CSMode == HOLDMODE; - // assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty); - - logic ContinueTransmitD; - logic NextEndDelay; - logic CurrentEndDelay; - + // Logic for continuing to transmit through Delay states after end of frame assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR; assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR; - always_ff @(posedge PCLK) begin - if (~PRESETn) begin - ContinueTransmitD <= 1'b0; - end else if (NextEndDelay & ~CurrentEndDelay) begin - ContinueTransmitD <= ContinueTransmit; - end else if (EndOfSCKCS & SCLKenable) begin - ContinueTransmitD <= 1'b0; - end - end - always_ff @(posedge PCLK) begin if (~PRESETn) begin CurrState <= INACTIVE; @@ -314,7 +252,7 @@ module spi_controller ( always_comb begin case (CurrState) - INACTIVE: if (TransmitStartD) begin + INACTIVE: if (TransmitRegLoaded) begin if (~HasCSSCK) NextState = TRANSMIT; else NextState = CSSCK; end else begin @@ -326,7 +264,7 @@ module spi_controller ( case(CSMode) AUTOMODE: begin if (EndTransmission) NextState = INACTIVE; - else if (EndOfFrameDelay) NextState = SCKCS; + else if (EndOfFrame) NextState = SCKCS; else NextState = TRANSMIT; end HOLDMODE: begin @@ -344,7 +282,7 @@ module spi_controller ( end SCKCS: begin // SCKCS case -------------------------------------- if (EndOfSCKCS) begin - if (~ContinueTransmitD) begin + if (~TransmitRegLoaded) begin // if (CSMode == AUTOMODE) NextState = INACTIVE; if (CSMode == HOLDMODE) NextState = HOLD; else NextState = INACTIVE; @@ -359,7 +297,7 @@ module spi_controller ( HOLD: begin // HOLD mode case ----------------------------------- if (CSMode == AUTOMODE) begin NextState = INACTIVE; - end else if (TransmitStartD) begin // If FIFO is written to, start again. + end else if (TransmitRegLoaded) begin // If FIFO is written to, start again. NextState = TRANSMIT; end else NextState = HOLD; end @@ -386,6 +324,7 @@ module spi_controller ( assign Transmitting = CurrState == TRANSMIT; assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR); + assign DelayState = (CurrState == CSSCK | CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR); assign InactiveState = CurrState == INACTIVE | CurrState == INTERCS; endmodule diff --git a/src/uncore/spi_fifo.sv b/src/uncore/spi_fifo.sv index 40c3ca4ff..1e4910faf 100644 --- a/src/uncore/spi_fifo.sv +++ b/src/uncore/spi_fifo.sv @@ -19,6 +19,10 @@ module spi_fifo #(parameter M=3, N=8)( // 2^M entries of N bits logic [M:0] rptrnext, wptrnext; logic [M-1:0] raddr; logic [M-1:0] waddr; + + logic [M-1:0] numVals; + + assign numVals = waddr - raddr; assign rdata = mem[raddr]; always_ff @(posedge PCLK) diff --git a/tests/coverage/Makefile b/tests/coverage/Makefile index 63b605679..7e68c28c0 100644 --- a/tests/coverage/Makefile +++ b/tests/coverage/Makefile @@ -28,7 +28,7 @@ all: $(OBJDUMPS) $(MEMFILES) # Assemble into object files %.$(OBJEXT): %.$(AEXT) - riscv64-unknown-elf-as -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh -mabi=lp64 $< + riscv64-unknown-elf-as -g -o $@ -march=rv64gqc_zcb_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom_zbkb_zbkx_zknd_zkne_zknh_svinval -mabi=lp64 $< # Preprocess assembly files %.$(AEXT): %.$(SRCEXT) WALLY-init-lib.h diff --git a/tests/coverage/csrwrites.S b/tests/coverage/csrwrites.S index fb5cfd436..ef0c283ec 100644 --- a/tests/coverage/csrwrites.S +++ b/tests/coverage/csrwrites.S @@ -38,6 +38,9 @@ main: csrrw t1, menvcfg, t0 csrrw t2, senvcfg, t0 + # Test writing to TIME CSR + csrw time, zero + # testing FIOM with different privilege modes # setting environment config (to both 1 and 0) in each privilege mode csrsi menvcfg, 1 diff --git a/tests/coverage/fround.S b/tests/coverage/fround.S deleted file mode 100644 index 7d469d773..000000000 --- a/tests/coverage/fround.S +++ /dev/null @@ -1,18 +0,0 @@ -// fround.s - -#include "WALLY-init-lib.h" - -# run-elf.bash find this in project description -main: - - bseti t0, zero, 14 # turn on FPU - csrs mstatus, t0 - - # test fround behavior on NaN - li t0, 0x7FC00001 - fmv.w.x ft0, t0 - fround.s ft1, ft0 - j done - -.align 10 -data_start: diff --git a/tests/coverage/ieu.S b/tests/coverage/ieu.S index 43e7b6604..285a170cb 100644 --- a/tests/coverage/ieu.S +++ b/tests/coverage/ieu.S @@ -81,6 +81,7 @@ main: .word 0xFF00302F // illegal Atomic instruction .word 0xFF00402F // illegal Atomic instruction .word 0x00000873 // illegal CSR instruction + .word 0x31bf1f93 // illegal aes64ksli1 instruction # Illegal CMO instructions because envcfg is 0 and system is in user Mode li a0, 0 diff --git a/tests/coverage/ifu.S b/tests/coverage/ifu.S index 72c515287..eaceb71ce 100644 --- a/tests/coverage/ifu.S +++ b/tests/coverage/ifu.S @@ -43,35 +43,23 @@ main: .hword 0x9C41 // line 134 Illegal compressed instruction # Zcb coverage tests - # could restore assembly language versions when GCC supports Zcb mv s0, sp - #c.lbu s1, 0(s0) // exercise c.lbu - .hword 0x8004 // c.lbu s1, 0(s0) - #c.lh s1, 0(s0) // exercise c.lh - .hword 0x8444 // c.lh s1, 0(s0) - #c.lhu s1, 0(s0) // exercise c.lhu - .hword 0x8404 // c.lhu s1, 0(s0) - #c.sb s1, 0(s0) // exercise c.sb - .hword 0x8804 // c.sb s1, 0(s0) - #c.sh s1, 0(s0) // exercise c.sh - .hword 0x8C04 // c.sh s1, 0(s0) + c.lbu s1, 0(s0) // exercise c.lbu + c.lh s1, 0(s0) // exercise c.lh + c.lhu s1, 0(s0) // exercise c.lhu + c.sb s1, 0(s0) // exercise c.sb + c.sh s1, 0(s0) // exercise c.sh .hword 0x8C44 // Illegal compressed instruction with op = 00, Instr[15:10] = 100011, Instr[6] = 1 and 0's everywhere else. Line 119 illegal instruction .hword 0x9C00 // Illegal compressed instruction with op = 00, Instr[15:10] = 100111, and 0's everywhere else. Line 119 illegal instruction li s0, 0xFF - # c.zext.b s0 // exercise c.zext.b - .hword 0x9C61 // c.zext.b s0 - # c.sext.b s0 // exercise c.sext.b - .hword 0x9C65 // c.sext.b s0 - # c.zext.h s0 // exercise c.zext.h - .hword 0x9C69 // c.zext.h s0 - # c.sext.h s0 // exercise c.sext.h - .hword 0x9C6D // c.sext.h s0 - # c.zext.w s0 // exercise c.zext.w - .hword 0x9C71 // c.zext.w s0 - # c.not s0 // exercise c.not - .hword 0x9C75 // c.not s0 + c.zext.b s0 // exercise c.zext.b + c.sext.b s0 // exercise c.sext.b + c.zext.h s0 // exercise c.zext.h + c.sext.h s0 // exercise c.sext.h + c.zext.w s0 // exercise c.zext.w + c.not s0 // exercise c.not .hword 0x9C7D // Reserved instruction from line 187 with op = 01, Instr[15:10] = 100111, Instr[6:5] = 11, and 0's everywhere else diff --git a/tests/coverage/priv.S b/tests/coverage/priv.S index 1af15add7..d0d3f94f4 100644 --- a/tests/coverage/priv.S +++ b/tests/coverage/priv.S @@ -304,7 +304,7 @@ sretdone: li a0, 3 ecall # exercise sfence.inval.ir instruction - .word 0x18100073 + sfence.inval.ir # exercise sret with rs1 not 0 .word 0x102F8073 diff --git a/tests/coverage/tlbKP.S b/tests/coverage/tlbKP.S deleted file mode 100644 index ca72a16db..000000000 --- a/tests/coverage/tlbKP.S +++ /dev/null @@ -1,144 +0,0 @@ -/////////////////////////////////////////// -// lsu_test.S -// -// Written: mmendozamanriquez@hmc.edu 4 April 2023 -// nlimpert@hmc.edu -// -// Purpose: Test coverage for LSU -// -// A component of the CORE-V-WALLY configurable RISC-V project. -// https://github.com/openhwgroup/cvw -// -// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -// load code to initalize stack, handle interrupts, terminate - -#include "WALLY-init-lib.h" - -# run-elf.bash find this in project description -main: - # Page table root address at 0x80010000 - li t5, 0x9000000000080010 - csrw satp, t5 - - # sfence.vma x0, x0 - - # switch to supervisor mode - li a0, 1 - ecall - - li t0, 0x80015000 - - li t2, 0 # i = 0 - li t3, 33 # Max amount of Loops = 32 - -loop: bge t2, t3, finished # exit loop if i >= loops - lw t1, 0(t0) - li t4, 0x1000 - add t0, t0, t4 - addi t2, t2, 1 - j loop - -finished: - j done - -.data - -.align 16 -# Page table situated at 0x80010000 -pagetable: - .8byte 0x200044C1 // old page table was 200040 which just pointed to itself! wrong - -.align 12 - .8byte 0x0000000000000000 - .8byte 0x00000000200048C1 - .8byte 0x00000000200048C1 - - -.align 12 - .8byte 0x0000000020004CC1 - //.8byte 0x00000200800CF// ADD IN THE MEGAPAGE should 3 nibbles of zeros be removed? - -.align 12 - #80000000 - .8byte 0x200000CF - .8byte 0x200004CF - .8byte 0x200008CF - .8byte 0x20000CCF - - .8byte 0x200010CF - .8byte 0x200014CF - .8byte 0x200018CF - .8byte 0x20001CCF - - .8byte 0x200020CF - .8byte 0x200024CF - .8byte 0x200028CF - .8byte 0x20002CCF - - .8byte 0x200030CF - .8byte 0x200034CF - .8byte 0x200038CF - .8byte 0x20003CCF - - .8byte 0x200040CF - .8byte 0x200044CF - .8byte 0x200048CF - .8byte 0x20004CCF - - .8byte 0x200050CF - .8byte 0x200054CF - .8byte 0x200058CF - .8byte 0x20005CCF - - .8byte 0x200060CF - .8byte 0x200064CF - .8byte 0x200068CF - .8byte 0x20006CCF - - .8byte 0x200070CF - .8byte 0x200074CF - .8byte 0x200078CF - .8byte 0x20007CCF - - .8byte 0x200080CF - .8byte 0x200084CF - .8byte 0x200088CF - .8byte 0x20008CCF - - .8byte 0x200090CF - .8byte 0x200094CF - .8byte 0x200098CF - .8byte 0x20009CCF - - .8byte 0x200100CF - .8byte 0x200104CF - .8byte 0x200108CF - .8byte 0x20010CCF - - .8byte 0x200110CF - .8byte 0x200114CF - .8byte 0x200118CF - .8byte 0x20011CCF - - .8byte 0x200120CF - .8byte 0x200124CF - .8byte 0x200128CF - .8byte 0x20012CCF - - .8byte 0x200130CF - .8byte 0x200134CF diff --git a/tests/coverage/tlbM3.S b/tests/coverage/tlbM3.S deleted file mode 100644 index 986fb378a..000000000 --- a/tests/coverage/tlbM3.S +++ /dev/null @@ -1,156 +0,0 @@ -/////////////////////////////////////////// -// tlbKP.S -// -// Written: mmendozamanriquez@hmc.edu 4 April 2023 -// nlimpert@hmc.edu -// -// Purpose: Test coverage for LSU -// -// A component of the CORE-V-WALLY configurable RISC-V project. -// https://github.com/openhwgroup/cvw -// -// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -// load code to initalize stack, handle interrupts, terminate - -#include "WALLY-init-lib.h" - -# run-elf.bash find this in project description -main: - # Page table root address at 0x80010000 - li t5, 0x9000000000080010 - csrw satp, t5 - - # sfence.vma x0, x0 - - # switch to supervisor mode - li a0, 1 - ecall - - li t0, 0x1000 - - li t2, 0 # i = 0 - li t3, 64 # Max amount of Loops = 32 - li t4, 0x1000 - -loop: bge t2, t3, interim # exit loop if i >= loops - lw t1, 0(t0) - # sfence.vma x0, x0 - add t0, t0, t4 - addi t2, t2, 1 - j loop - -interim: - li t0, 0xFFFFFFFF000 - li t2, 0 # i = 0 - - -loop2:bge t2, t3, finished # exit loop if i >= loops - lw t1, 0(t0) - add t0, t0, t4 - addi t2, t2, 1 - j loop2 - -finished: - j done - -.data - -.align 16 -# Page table situated at 0x80010000 -pagetable: - .8byte 0x200044C1 // old page table was 200040 which just pointed to itself! wrong - -.align 12 - .8byte 0x00000000200048C1 - .8byte 0x00000000200048C1 - .8byte 0x00000000200048C1 - - -.align 12 - .8byte 0x0000000020004CC1 - //.8byte 0x00000200800CF// ADD IN THE MEGAPAGE should 3 nibbles of zeros be removed? - -.align 12 - #80000000 - .8byte 0x200000CF - .8byte 0x200004CF - .8byte 0x200008CF - .8byte 0x20000CCF - - .8byte 0x200010CF - .8byte 0x200014CF - .8byte 0x200018CF - .8byte 0x20001CCF - - .8byte 0x200020CF - .8byte 0x200024CF - .8byte 0x200028CF - .8byte 0x20002CCF - - .8byte 0x200030CF - .8byte 0x200034CF - .8byte 0x200038CF - .8byte 0x20003CCF - - .8byte 0x200040CF - .8byte 0x200044CF - .8byte 0x200048CF - .8byte 0x20004CCF - - .8byte 0x200050CF - .8byte 0x200054CF - .8byte 0x200058CF - .8byte 0x20005CCF - - .8byte 0x200060CF - .8byte 0x200064CF - .8byte 0x200068CF - .8byte 0x20006CCF - - .8byte 0x200070CF - .8byte 0x200074CF - .8byte 0x200078CF - .8byte 0x20007CCF - - .8byte 0x200080CF - .8byte 0x200084CF - .8byte 0x200088CF - .8byte 0x20008CCF - - .8byte 0x200090CF - .8byte 0x200094CF - .8byte 0x200098CF - .8byte 0x20009CCF - - .8byte 0x2000A0CF - .8byte 0x2000A4CF - .8byte 0x2000A8CF - .8byte 0x2000ACCF - - .8byte 0x2000B0CF - .8byte 0x2000B4CF - .8byte 0x2000B8CF - .8byte 0x2000BCCF - - .8byte 0x2000C0CF - .8byte 0x2000C4CF - .8byte 0x2000C8CF - .8byte 0x2000CCCF - - .8byte 0x2000D0CF - .8byte 0x2000D4CF diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output index 027e02f54..e19f75391 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-spi-01.reference_output @@ -146,6 +146,30 @@ 00000015 +00000010 + +00000010 + +00000010 + +00000010 + +00000010 + +00000010 + +00000011 + +00000011 + +00000011 + +00000011 + +00000011 + +00000011 + 00000011 #delay1 00000022 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S index 94defaf87..19b70829c 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-spi-01.S @@ -316,11 +316,87 @@ test_cases: .4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end .4byte rx_data, 0x00000015, read32_test # read rx_data +# SCKCS Delay of 0, SCKMODE 10 +.4byte sck_mode, 0x00000002, write32_test #set sckmode to 10 +.4byte delay0, 0x00000001, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + +# Arbitrary SCKCS delay, SCKMODE 10 +.4byte delay0, 0x00050001, write32_test # set sckcs delay to 5 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + +# Long SCKCS delay, SCKMODE 10 +.4byte delay0, 0x00A50001, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + +# CSSCK Delay 0, SCKMODE 10 +.4byte delay0, 0x00010000, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + +# Arbitrary CSSCK delay, SCKMODE 10 +.4byte delay0, 0x00010005, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + +# Long CSSCK delay, SCKMODE 10 +.4byte delay0, 0x000100A5, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000010, read32_test # reade rx_data + + + +# SCKCS Delay of 0, SCKMODE 11 +.4byte sck_mode, 0x00000003, write32_test +.4byte delay0, 0x00000001, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + +# Arbitrary SCKCS delay, SCKMODE 11 +.4byte delay0, 0x00050001, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + +# Long SCKCS delay, SCKMODE 11 +.4byte delay0, 0x00A50001, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + +# CSSCK Delay 0, SCKMODE 11 +.4byte delay0, 0x00010000, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + +# Arbitrary CSSCK delay, SCKMODE 11 +.4byte delay0, 0x00010005, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + +# Long CSSCK delay, SCKMODE 11 +.4byte delay0, 0x000100A5, write32_test # set sckcs delay to 0 +.4byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.4byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.4byte rx_data, 0x00000011, read32_test # reade rx_data + # =========== Test delay1 register =========== # Test inter cs delay - +.4byte sck_mode, 0x00000000, write32_test #reset sck_mode .4byte delay0, 0x00010001, write32_test # reset delay0 register .4byte delay1, 0x00000005, write32_test # set inter_cs delay to 5 .4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output index 8d9ae8bbc..bc17f4beb 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-spi-01.reference_output @@ -146,6 +146,30 @@ 00000000 00000015 00000000 +00000010 +00000000 +00000010 +00000000 +00000010 +00000000 +00000010 +00000000 +00000010 +00000000 +00000010 +00000000 +00000011 +00000000 +00000011 +00000000 +00000011 +00000000 +00000011 +00000000 +00000011 +00000000 +00000011 +00000000 00000011 #delay1 00000000 00000022 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S index 23cfd169a..a31069470 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-spi-01.S @@ -258,7 +258,7 @@ test_cases: .8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end .8byte rx_data, 0x00000011, read32_test # read rx_data -# =========== Test delay0 register =========== +# =========== Test delay0 register (mode auto)=========== # Test cs-sck delay of 0 with sck phase = 0 (implicit half cycle delay) @@ -320,11 +320,87 @@ test_cases: .8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end .8byte rx_data, 0x00000015, read32_test # read rx_data +# SCKCS Delay of 0, SCKMODE 10 +.8byte sck_mode, 0x00000002, write32_test #set sckmode to 10 +.8byte delay0, 0x00000001, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + +# Arbitrary SCKCS delay, SCKMODE 10 +.8byte delay0, 0x00050001, write32_test # set sckcs delay to 5 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + +# Long SCKCS delay, SCKMODE 10 +.8byte delay0, 0x00A50001, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + +# CSSCK Delay 0, SCKMODE 10 +.8byte delay0, 0x00010000, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + +# Arbitrary CSSCK delay, SCKMODE 10 +.8byte delay0, 0x00010005, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + +# Long CSSCK delay, SCKMODE 10 +.8byte delay0, 0x000100A5, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000010, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000010, read32_test # reade rx_data + + + +# SCKCS Delay of 0, SCKMODE 11 +.8byte sck_mode, 0x00000003, write32_test +.8byte delay0, 0x00000001, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + +# Arbitrary SCKCS delay, SCKMODE 11 +.8byte delay0, 0x00050001, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + +# Long SCKCS delay, SCKMODE 11 +.8byte delay0, 0x00A50001, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + +# CSSCK Delay 0, SCKMODE 11 +.8byte delay0, 0x00010000, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + +# Arbitrary CSSCK delay, SCKMODE 11 +.8byte delay0, 0x00010005, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + +# Long CSSCK delay, SCKMODE 11 +.8byte delay0, 0x000100A5, write32_test # set sckcs delay to 0 +.8byte tx_data, 0x00000011, write32_test # place 10 into tx_data +.8byte 0x0, 0x00000000, spi_data_wait #wait for transmission +.8byte rx_data, 0x00000011, read32_test # reade rx_data + # =========== Test delay1 register =========== # Test inter cs delay - +.8byte sck_mode, 0x00000000, write32_test #reset sck_mode .8byte delay0, 0x00010001, write32_test # reset delay0 register .8byte delay1, 0x00000005, write32_test # set inter_cs delay to 5 .8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock