From a23c1cf18baece33b3dbf986baca671ddd4bc0dd Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Tue, 1 Oct 2024 12:00:12 -0700 Subject: [PATCH 1/7] Remove buildrootBugFinder.py --- sim/buildrootBugFinder.py | 42 --------------------------------------- 1 file changed, 42 deletions(-) delete mode 100755 sim/buildrootBugFinder.py diff --git a/sim/buildrootBugFinder.py b/sim/buildrootBugFinder.py deleted file mode 100755 index ee9fe0603..000000000 --- a/sim/buildrootBugFinder.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 -import sys, os, subprocess - -def main(): - RISCV = os.environ.get("RISCV") - maxGoodCount = 400e6 # num instrs that execute sucessfully starting from 0 - currInstrCount = maxGoodCount - linuxTestvectors = RISCV+"/linux-testvectors" - if not os.path.exists(linuxTestvectors): - sys.stderr.write("Error: Linux testvectors not found at "+linuxTestvectors+"\n") - exit(1) - checkpointList = [int(fileName.strip('checkpoint')) for fileName in os.listdir(linuxTestvectors) if 'checkpoint' in fileName] - checkpointList.sort() - - logDir = "./logs/buildrootBugFinderLogs/" - os.system("mkdir -p "+logDir) - summaryLogFilePath = logDir+"summary.log" - summaryLogFile = open(summaryLogFilePath,'w') - summaryLogFile.close() - while True: - checkpointList = [checkpoint for checkpoint in checkpointList if checkpoint > currInstrCount] - if len(checkpointList)==0: - break - checkpoint = checkpointList[0] - logFile = logDir+"checkpoint"+str(checkpoint)+".log" - runCommand="{\nvsim -c < Date: Tue, 1 Oct 2024 12:08:39 -0700 Subject: [PATCH 2/7] Remove bpred-sim.py --- sim/bpred-sim.py | 194 ----------------------------------------------- 1 file changed, 194 deletions(-) delete mode 100755 sim/bpred-sim.py diff --git a/sim/bpred-sim.py b/sim/bpred-sim.py deleted file mode 100755 index 45c0965a1..000000000 --- a/sim/bpred-sim.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python3 -################################## -# -# regression-wally -# David_Harris@Hmc.edu 25 January 2021 -# Modified by Jarred Allen -# -# Run a regression with multiple configurations in parallel and exit with -# non-zero status code if an error happened, as well as printing human-readable -# output. -# -################################## -import sys,os,shutil -import argparse - -class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKCYAN = '\033[96m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - -from collections import namedtuple -regressionDir = os.path.dirname(os.path.abspath(__file__)) -os.chdir(regressionDir) - -TestCase = namedtuple("TestCase", ['name', 'variant', 'cmd', 'grepstr']) -# name: the name of this test configuration (used in printing human-readable -# output and picking logfile names) -# cmd: the command to run to test (should include the logfile as '{}', and -# the command needs to write to that file) -# grepstr: the string to grep through the log file for. The test succeeds iff -# grep finds that string in the logfile (is used by grep, so it may -# be any pattern grep accepts, see `man 1 grep` for more info). - -# edit this list to add more test cases -configs = [ - TestCase( - name="lints", - variant="all", - cmd="./lint-wally | tee {}", - grepstr="All lints run with no errors or warnings" - ) -] - - -import os -from multiprocessing import Pool, TimeoutError - -def search_log_for_text(text, logfile): - """Search through the given log file for text, returning True if it is found or False if it is not""" - grepcmd = "grep -e '%s' '%s' > /dev/null" % (text, logfile) - return os.system(grepcmd) == 0 - -def run_test_case(config): - """Run the given test case, and return 0 if the test suceeds and 1 if it fails""" - logname = "logs/"+config.variant+"_"+config.name+".log" - cmd = config.cmd.format(logname) - print(cmd) - os.chdir(regressionDir) - os.system(cmd) - if search_log_for_text(config.grepstr, logname): - print(f"{bcolors.OKGREEN}%s_%s: Success{bcolors.ENDC}" % (config.variant, config.name)) - return 0 - else: - print(f"{bcolors.FAIL}%s_%s: Failures detected in output{bcolors.ENDC}" % (config.variant, config.name)) - print(" Check %s" % logname) - return 1 - -def main(): - """Run the tests and count the failures""" - TIMEOUT_DUR = 10800 # 3 hours - - global configs - try: - os.chdir(regressionDir) - os.mkdir("logs") - #print(os.getcwd()) - #print(regressionDir) - except: - pass - try: - shutil.rmtree("wkdir") - except: - pass - finally: - os.mkdir("wkdir") - - parser = argparse.ArgumentParser(description='Runs embench with sweeps of branch predictor sizes and types.') - mode = parser.add_mutually_exclusive_group() - mode.add_argument('-r', '--ras', action='store_const', help='Sweep size of return address stack (RAS).', default=False, const=True) - mode.add_argument('-d', '--direction', action='store_const', help='Sweep size of direction prediction (2-bit, Gshare, local, etc).', default=False, const=True) - mode.add_argument('-t', '--target', action='store_const', help='Sweep size of branch target buffer (BTB).', default=False, const=True) - mode.add_argument('-c', '--iclass', action='store_const', help='Sweep size of classification (BTB) Same as -t.', default=False, const=True) - - args = parser.parse_args() - - if(args.direction): - # for direction predictor size sweep - bpdSize = [6, 8, 10, 12, 14, 16] - #bpdType = ['twobit', 'gshare', 'global', 'gshare_basic', 'global_basic', 'local_basic'] - bpdType = ['twobit', 'gshare'] - for CurrBPType in bpdType: - for CurrBPSize in bpdSize: - name = CurrBPType+str(CurrBPSize) - configOptions = "+define+INSTR_CLASS_PRED=0 +define+BPRED_OVERRIDE +define+BPRED_TYPE=" + str(bpdType.index(CurrBPType)) + "+define+BPRED_SIZE=" + str(CurrBPSize) - tc = TestCase( - name=name, - variant="rv32gc", - cmd="vsim > {} -c < {} -c < {} -c < {} -c < {} -c < Date: Tue, 1 Oct 2024 12:18:07 -0700 Subject: [PATCH 3/7] Remove studies/testgen as it is no longer compatible --- .../testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py | 158 -- .../testgen-ADDI-XORI-ORI-ANDI-SLTI.py | 161 -- .../testgen-ADDIW-SLLIW-SRLIW-SRAIW.py | 182 -- .../testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py | 174 -- studies/testgen/testgen-BRANCH.py | 155 -- studies/testgen/testgen-CSR.py | 218 -- studies/testgen/testgen-JAL-JALR.py | 286 --- studies/testgen/testgen-LOAD.py | 227 -- studies/testgen/testgen-PIPELINE.py | 1917 ----------------- studies/testgen/testgen-SLL-SRL-SRA.py | 154 -- studies/testgen/testgen-SLLI-SRLI-SRAI.py | 189 -- studies/testgen/testgen-SLTIU.py | 173 -- studies/testgen/testgen-STORE.py | 282 --- studies/testgen/testgen-VIRTUALMEMORY.py | 285 --- 14 files changed, 4561 deletions(-) delete mode 100755 studies/testgen/testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py delete mode 100644 studies/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py delete mode 100755 studies/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py delete mode 100755 studies/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py delete mode 100755 studies/testgen/testgen-BRANCH.py delete mode 100644 studies/testgen/testgen-CSR.py delete mode 100755 studies/testgen/testgen-JAL-JALR.py delete mode 100755 studies/testgen/testgen-LOAD.py delete mode 100755 studies/testgen/testgen-PIPELINE.py delete mode 100755 studies/testgen/testgen-SLL-SRL-SRA.py delete mode 100644 studies/testgen/testgen-SLLI-SRLI-SRAI.py delete mode 100644 studies/testgen/testgen-SLTIU.py delete mode 100755 studies/testgen/testgen-STORE.py delete mode 100644 studies/testgen/testgen-VIRTUALMEMORY.py diff --git a/studies/testgen/testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py b/studies/testgen/testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py deleted file mode 100755 index 7a5b824b5..000000000 --- a/studies/testgen/testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADD-SUB-SLT-SLTU-XOR-OR-AND.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["ADD", "SUB", "SLT", "SLTU", "XOR", "OR", "AND"] -author = "David_Harris@hmc.edu & Katherine Parry" -xlens = [32, 64] -numrand = 100; - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for test in tests: - corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners: - for b in corners: - writeVector(a, b, storecmd, xlen) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(xlen) - writeVector(a, b, storecmd, xlen) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py b/studies/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py deleted file mode 100644 index a25958552..000000000 --- a/studies/testgen/testgen-ADDI-XORI-ORI-ANDI-SLTI.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADD-SUB.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def computeExpected(a, b, test): - if (test == "ADDI"): - return a + b - elif (test == "XORI"): - return a ^ b - elif (test == "ORI"): - return a | b - elif (test == "ANDI"): - return a & b - elif (test == "SLTI"): - return a < b - else: - die("bad test name ", test) - # exit(1) - - -def evaluateTwoComplement(b, bits): - if (b & (1 << (bits -1))!= 0): - b = b - (1 << bits) - return b - - -def randRegs(): - reg1 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg3 == 6): - return randRegs() - else: - return reg1, reg3 - -def writeVector(a, b, storecmd): - global testnum - - - - expected = computeExpected(evaluateTwoComplement(a,xlen), evaluateTwoComplement(b, 12), test) - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - - - - reg1, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), imm12:" + "(" +formatstrimm12.format(b) - lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n" - # lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["ADDI", "XORI", "ORI", "ANDI", "SLTI"] -author = "Shriya Nadgauda & Ethan Falicov" -xlens = [32, 64] -numrand = 100 - - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - - formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for test in tests: - corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - - immBitSize = 12 - corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1, - 2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1] - - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners1: - for b in corners2: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(12) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - diff --git a/studies/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py b/studies/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py deleted file mode 100755 index 55cffb3db..000000000 --- a/studies/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADDIW-SLLIW-SRLIW-SRAIW.py -# -# ehedenberg@hmc.edu 4 February 2021 -# heavily influenced by Prof Harris Code -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits -import sys - -################################## -# functions -################################## -def logical_rshift(signed_integer, places): - unsigned_integer=signed_integer%(1<<32) - return unsigned_integer >> places - -def toSigned12bit(n): - n=n & 0xfff - if (n&(1<<11)): - n=n|0xfffffffffffff000 - return n - -def toSigned32bit(n): - n=n & 0xffffffff - if (n&(1<<31)): - n=n|0xffffffff00000000 - return n - - -def computeExpected(a, b, test): - if (test == "ADDIW"): - b=toSigned12bit(b) - return a + b - elif (test == "SLLIW"): - return (a << b) - elif (test == "SRLIW"): - return logical_rshift(a, b) - elif(test == "SRAIW"): - a= toSigned32bit(a) - return a >> b - else: - die("bad test name ", test) - # exit(1) - -def randRegs(): - reg1 = randint(1,31) - reg2 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVector(a, b, storecmd): - global testnum - expected = computeExpected(a, b, test) - expected = expected % 2**64 # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**64 + expected - #expected=expected+2^32<<32 - if (expected >= (2**32)): - expected=expected%(2**32) - expected=toSigned32bit(expected) - reg1, reg2, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), imm:"+formatstr.format(b) - lines = lines + ", result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - #lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstr.format(b) + ")\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg3) +", "+formatstr.format(expected)+")\n" - #lines = lines + str(b)+"\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["ADDIW", "SLLIW", "SRLIW", "SRAIW"] -author = "Eizabeth Hedenberg" -xlens = [64] -shiftlen=5 -addlen=12 -numrand = 100 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - #formatstrlen6=str(int()) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - #formatstr6 = "0x{:0" + "2" + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for test in tests: - cornersa = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - #test both confined to top 32 and not - cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110] - #6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46 - cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111] - #12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - if test=="ADDIW": - for a in cornersa: - for b in cornersadd: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(12) - writeVector(a, b, storecmd) - else: - for a in cornersa: - for b in cornersshift: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(5) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py b/studies/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py deleted file mode 100755 index f57b95315..000000000 --- a/studies/testgen/testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADDW-SUBW-SLLW-SRLW-SRAW.py -# -# trao@g.hmc.edu 11 February 2021 -# Based on testgen-ADD-SUB.py by Prof. David Harris -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits -import sys - -################################## -# functions -################################## -def logical_rshift(signed_integer, places): - unsigned_integer=signed_integer%(1<<32) - return unsigned_integer >> places - -def toSigned12bit(n): - n=n & 0xfff - if (n&(1<<11)): - n=n|0xfffffffffffff000 - return n - -def toSigned32bit(n): - n=n & 0xffffffff - if (n&(1<<31)): - n=n|0xffffffff00000000 - return n - - -def computeExpected(a, b, test): - if (test == "ADDW"): - return toSigned32bit(a + b) - elif (test == "SUBW"): - return toSigned32bit(a - b) - elif (test == "SLLW"): - b = b & 0x1F - return toSigned32bit(a << b) - elif (test == "SRLW"): - b = b & 0x1F - return toSigned32bit(logical_rshift(a, b)) - elif(test == "SRAW"): - a= toSigned32bit(a) - b = b & 0x1F - return toSigned32bit(a >> b) - else: - die("bad test name ", test) - # exit(1) - -def randRegs(): - reg1 = randint(1,31) - reg2 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVector(a, b, storecmd): - global testnum - expected = computeExpected(a, b, test) - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - reg1, reg2, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b) - lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n" - f.write(lines) - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW"] -author = "Tejus Rao" -xlens = [64] -shiftlen=5 -addlen=32 -numrand = 100 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - #formatstrlen6=str(int()) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - #formatstr6 = "0x{:0" + "2" + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - storecmd = "sd" - wordsize = 8 - for test in tests: - cornersa = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - #test both confined to top 32 and not - cornersshift=[0, 1, 2, 2**(shiftlen)-1, 2**(shiftlen)-2, 0b00101, 0b01110] - #6 bits: 0, 1, 2, largest, largest -1, largest -2, 21, 46 - cornersadd=[0, 1, 2, 2**(addlen-1), 2**(addlen-1)-1, 2**(addlen-1)-2, 2**(addlen-1)+1, 2**(addlen)-2, 2**(addlen)-1, 0b001010010101, 0b101011101111] - #12 bit, 0, 1, 2 argest positive, largest -1, largest -2, largest negative number, -2, -1, random - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - if test=="ADDW" or test == "SUBW": - for a in cornersa: - for b in cornersadd: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(xlen) - writeVector(a, b, storecmd) - else: - for a in cornersa: - for b in cornersshift: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(5) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-BRANCH.py b/studies/testgen/testgen-BRANCH.py deleted file mode 100755 index cf5236ad9..000000000 --- a/studies/testgen/testgen-BRANCH.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-branch.py -# -# ssanghai@hmc.edu 13th Feb 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## -def computeExpected(a, b, test): - if (test == "BEQ"): - return 0xcccc if a==b else 0xeeee - elif (test == "BNE"): - return 0xeeee if a==b else 0xcccc - elif (test == "BGEU"): - return 0xcccc if a>=b else 0xeeee - elif (test == "BLT"): - if (1<<(xlen-1)) & a: - a = a -(2**xlen) - if (1<<(xlen-1)) & b: - b = b - (2**xlen) - return 0xcccc if a=b else 0xeeee - else: - die("bad test name ", test) - # exit(1) - -def randRegs(): - reg1 = randint(2,31) - reg2 = randint(2,31) - if (reg1 == 6 or reg2 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2 - -label = 0 - -def writeVector(a, b, storecmd): - global testnum - global label - expected = computeExpected(a, b, test) - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - reg1, reg2 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b) + "\n" - lines = lines + "li x1, MASK_XLEN(0xcccc)\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + test + " x" + str(reg1) + ", x" + str(reg2) + ", " + str(label) + "f\n" - lines = lines + "li x1, MASK_XLEN(0xeeee)\n" - lines = lines + str(label) + ":\n" - lines = lines + storecmd + " x1, " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, x1, "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - label += 1 - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["BEQ", "BNE", "BLT", "BGE", "BGEU", "BLTU"] -author = "Shreya Sanghai" -xlens = [32, 64] -numrand = 100 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for test in tests: - corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners: - for b in corners: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(xlen) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-CSR.py b/studies/testgen/testgen-CSR.py deleted file mode 100644 index 7f74b1658..000000000 --- a/studies/testgen/testgen-CSR.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADD-SUB.py -# -# ushakya@hmc.edu & dottolia@hmc.edu 14 Feb 2021 -# Modified: ushakya@hmc.edu 21 April 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def randRegs(): - reg1 = randint(1,31) - reg2 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVector(a, b, storecmd): - global testnum - csr = "mscratch" - - reg1, reg2, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": " + csr + "\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + "li x" + str(reg2) + ", MASK_XLEN(0)\n" - - # Page 6 of unpriviledged spec - # For both CSRRS and CSRRC, if rs1=x0, then the instruction will not write to the CSR at all, and so shall not cause any of the side effects - - expected = a - - if test == "csrrw": - if testnum == 0: - # this is a corner case (reading and writing same register) - expected = 4 - lines += "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(0x8) + ")\n" - lines += "la x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(0x4) + ")\n" - lines += "csrrw x" + str(reg3) + ", mtvec, x" + str(reg1) + "\n" - lines += test + " x" + str(reg2) + ", mtvec, x" + str(reg2) + "\n" - lines += "csrrw x0, mtvec, x" + str(reg3) + "\n" - else: - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - - elif test == "csrrs": # at some point, try writing a non-zero value first - lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0 - - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - elif test == "csrrc": # at some point, try writing a non-one value first - allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF" - - lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n" - lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones - - lines += "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - - expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF - elif test == "csrrwi": - a = a & 0x1F # imm is only 5 bits - - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - - expected = a - elif test == "csrrsi": # at some point, try writing a non-zero value first - a = a & 0x1F - - lines += "csrrw x0, " + csr + ", x0\n" # set csr to 0 - - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - - expected = a - elif test == "csrrci": # at some point, try writing a non-one value first - a = a & 0x1F - allOnes = "0xFFFFFFFF" if xlen == 32 else "0xFFFFFFFFFFFFFFFF" - - lines += "li x" + str(reg1) + ", MASK_XLEN(" + allOnes + ")\n" - lines += "csrrw x0, " + csr + ", x" + str(reg1) + "\n" # set csr to all ones - - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", " + str(a) + "\n" - - expected = a ^ 0xFFFFFFFF if xlen == 32 else a ^ 0xFFFFFFFFFFFFFFFF - - - lines += storecmd + " x" + str(reg2) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -def writeSpec(a, storecmd): - global testnum - csr = "mscratch" - reg1 = 3 - reg2 = 3 - - lines = "\n# Testcase " + str(testnum) + ": " + csr + "\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - expected = a - - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - lines += test + " x" + str(reg2) + ", " + csr + ", x" + str(reg1) + "\n" - - lines += storecmd + " x" + str(reg2) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci -tests = ["csrrw", "csrrs", "csrrc", "csrrwi", "csrrsi", "csrrci"] -author = "ushakya@hmc.edu & dottolia@hmc.edu" -xlens = [32, 64] -numrand = 60; - -# setup -seed(0xC365DDEB9173AB42) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for test in tests: - corners = [ - 0, 1, 2, 0x1E, 0x1F, 0xFF, - 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 - ] - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test.upper() - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - # test that reading and writing from same register work - if test == "csrrw": - a = getrandbits(xlen) - #writeSpec(a, storecmd) - for a in corners: - for b in corners: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(xlen) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -4\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-JAL-JALR.py b/studies/testgen/testgen-JAL-JALR.py deleted file mode 100755 index 7ce482bd5..000000000 --- a/studies/testgen/testgen-JAL-JALR.py +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-JAL.py -# -# Ben Bracker (bbracker@hmc.edu) 19 January 2021 -# Based on testgen-ADD-SUB.py by David Harris -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import choice -from random import seed -from random import getrandbits -from copy import deepcopy - -################################## -# helper functions -################################## -def InitTestGroup(): - global TestGroup,TestGroupSizes,AllRegs,UnusedRegs,StoreAdrReg - TestGroup += 1 - TestGroupSizes.append(0) - UnusedRegs = deepcopy(AllRegs) - oldStoreAdrReg = StoreAdrReg - while ((StoreAdrReg == oldStoreAdrReg) or (StoreAdrReg == 0) or (StoreAdrReg == 31)): - StoreAdrReg = choice(UnusedRegs) - UnusedRegs.remove(StoreAdrReg) - f.write("\n # ---------------------------------------------------------------------------------------------\n") - f.write(" # new register for address of test results\n") - addInst(" la x"+str(StoreAdrReg)+", test_1_res\n") - f.write(" # ---------------------------------------------------------------------------------------------\n") - -def registerSelect(): - # ensures that rd experiences all possible registers - # *** does not yet ensure that rs experiences all possible registers - # ensures that at least once rd = rs - global UnusedRegs - if len(UnusedRegs)==0: - InitTestGroup() - rd = choice(UnusedRegs) - UnusedRegs.remove(rd) - OtherRegs = deepcopy(UnusedRegs) - if 0 in OtherRegs: - OtherRegs.remove(0) - if len(OtherRegs) == 0: - OtherRegs = deepcopy(AllRegs) - OtherRegs.remove(0) - rs = choice(OtherRegs) - OtherRegs = deepcopy(AllRegs) - OtherRegs.remove(StoreAdrReg) - OtherRegs.remove(rd) - if 0 in OtherRegs: - OtherRegs.remove(0) - if rs in OtherRegs: - OtherRegs.remove(rs) - DataReg = choice(OtherRegs) - OtherRegs.remove(DataReg) - OtherRd = choice(OtherRegs) - return (rd,rs,DataReg,OtherRd) - -def addInst(line): - global CurrAdr - f.write(line) - if ("li x" in line) and ("slli x" not in line): - CurrAdr += 8 if (xlen == 32) else 20 - elif ("la x" in line): - CurrAdr += 8 - else: - CurrAdr += 4 - -def expectValue(expectReg, expectVal, sigOffset): - global TestGroupSizes - TestGroupSizes[TestGroup-1] += 1 - addInst(" "+storecmd+" x"+str(expectReg)+", "+str(wordsize*sigOffset)+"(x"+str(StoreAdrReg)+")\n") - f.write(" RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(expectReg)+", "+formatstr.format(expectVal)+")\n") - if (xlen == 32): - r.write(formatrefstr.format(expectVal)+"\n") - else: - r.write(formatrefstr.format(expectVal % 2**32)+"\n" + formatrefstr.format(expectVal >> 32)+"\n") - -def addJalr(rs,rd,dist): - target = CurrAdr + 20 + dist - target31_12 = CurrAdr >> 12 # 20 bits for lui - target11_0 = target - (target31_12 << 12) # 12 remaining bits - target31_16 = target31_12 >> 4 # lui sign extends, so shift in a leading 0 - target15_12 = target31_12 - (target31_16 << 4) # the nibble we just lost - if target11_0 > 0: - offset = randint(-(1<<11)-1,(1<<11)-2-target11_0) - else: - offset = randint(-(1<<11)-1-target11_0,(1<<11)-2) - addInst(" lui x"+str(rs)+", 0x"+imm20formatstr.format(target31_16)+"\n") - addInst(" addi x"+str(rs)+", x"+str(rs)+", SEXT_IMM(0x0"+imm12formatstr.format(target15_12 << 8)+")\n") - addInst(" slli x"+str(rs)+", x"+str(rs)+", SEXT_IMM(4)\n") - addInst(" addi x"+str(rs)+", x"+str(rs)+", SEXT_IMM(0x"+imm12formatstr.format(0xfff&(offset+target11_0+randint(0,1)))+")\n") - addInst(" JALR x"+str(rd)+", x"+str(rs)+", SEXT_IMM(0x"+imm12formatstr.format(0xfff&(-offset))+")\n") - -################################## -# test functions -################################## -def writeForwardsJumpVector(spacers,instr): - global TestNum - TestNum += 1 - rd, rs, DataReg, OtherRd = registerSelect() - # Header - f.write("\n") - f.write(" # Testcase "+str(TestNum)+"\n") - # Test Code - addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n") - if (instr=="JAL"): - addInst(" JAL x"+str(rd)+", 1f\n") - elif (instr=="JALR"): - dist = spacers*(8 if (xlen == 32) else 20) # Compute distance from linked adr to target adr - addJalr(rs,rd,dist); - else: - exit("invalid instruction") - LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value - for i in range(spacers): - addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n") - f.write("1:\n") - # Store values to be verified - expectValue(rd, LinkAdr, 2*TestNum+0) - expectValue(DataReg, expected, 2*TestNum+1) - -def writeBackwardsJumpVector(spacers,instr): - global TestNum - TestNum += 1 - rd, rs, DataReg, OtherRd = registerSelect() - # Header - f.write("\n") - f.write(" # Testcase "+str(TestNum)+"\n") - # Test Code - addInst(" JAL x"+str(OtherRd)+", 2f\n") - f.write("1:\n") - addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n") - addInst(" JAL x"+str(OtherRd)+", 3f\n") - f.write("2:\n") - for i in range(spacers): - addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n") - if (instr=="JAL"): - addInst(" JAL x"+str(rd)+", 1b\n") - elif (instr=="JALR"): - dist = -20 - 4 - (1+spacers)*(8 if (xlen == 32) else 20) # Compute distance from linked adr to target adr - addJalr(rs,rd,dist); - else: - exit("invalid instruction") - LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value - f.write("3:\n") - # Store values to be verified - expectValue(rd, LinkAdr, 2*TestNum+0) - expectValue(DataReg, expected, 2*TestNum+1) - -def writeChainVector(repetitions,spacers): - global TestNum - TestNum += 1 - rd, rs, DataReg,OtherRd = registerSelect() - # Header - f.write("\n") - f.write(" # Testcase "+str(TestNum)+"\n") - # Test Code - addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n") - for i in range(repetitions): - addInst(" JAL x"+str(OtherRd)+", "+str(3*i+2)+"f\n") - if spacers: - for j in range(i): - addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n") - f.write(str(3*i+1)+":\n") - addInst(" JAL x"+str(OtherRd)+", "+str(3*i+3)+"f\n") - if spacers: - for j in range(i): - addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n") - f.write(str(3*i+2)+":\n") - addInst(" JAL x"+str(rd)+", "+str(3*i+1)+"b\n") - LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value - if spacers: - for j in range(i): - addInst(" li x"+str(DataReg)+", "+formatstr.format(unexpected)+"\n") - f.write(str(3*i+3)+":\n") - # Store values to be verified - expectValue(rd, LinkAdr, 2*TestNum+0) - expectValue(DataReg, expected, 2*TestNum+1) - -################################## -# main body -################################## - -# change these to suite your tests -test = 0 -tests = ["JAL","JALR"] -author = "Ben Bracker (bbracker@hmc.edu)" -xlens = [32,64] -numtests = 100 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for test in tests: - for xlen in xlens: - print(test+" "+str(xlen)) - CurrAdr = int("80000108",16) - TestNum = -1 - TestGroup = 1 - TestGroupSizes = [0] - AllRegs = list(range(0,32)) - UnusedRegs = deepcopy(AllRegs) - StoreAdrReg = 6 # matches what's in header script - UnusedRegs.remove(6) - if (xlen==64): - expected = int("fedbca9876540000",16) - unexpected = int("ffff0000ffff0000",16) - else: - expected = int("fedbca98",16) - unexpected = int("ff00ff00",16) - - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - imm20formatstr = "{:05x}" - imm12formatstr = "{:03x}" - - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - f.write("///////////////////////////////////////////\n") - f.write("// "+fname+ "\n") - f.write("//\n") - f.write("// This file can be used to test the RISC-V JAL(R) instruction.\n") - f.write("// But be warned that altering the test environment may break this test!\n") - f.write("// In order to work, this test expects that the first instruction (la)\n") - f.write("// be allocated at 0x80000100.\n") - f.write("//\n") - f.write("// " + author + "\n") - f.write("// Created "+str(datetime.now())+"\n") - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed test vectors - if test == "JAL": - for i in range(0,31): - writeForwardsJumpVector(randint(0,4),"JAL") - for i in range(0,31): - writeBackwardsJumpVector(randint(0,4),"JAL") - writeForwardsJumpVector(100,"JAL") - writeBackwardsJumpVector(100,"JAL") - writeChainVector(6,True) - writeChainVector(16,False) - elif test == "JALR": - for i in range(0,31): - writeForwardsJumpVector(randint(0,4),"JALR") - for i in range(0,31): - writeBackwardsJumpVector(randint(0,4),"JALR") - # can't make these latter two too long else 12 bit immediate overflows - # (would need to lui or slli rs to achieve longer ranges) - writeForwardsJumpVector(15,"JALR") - writeBackwardsJumpVector(15,"JALR") - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - f.write(".fill "+str(sum(TestGroupSizes))+", "+str(wordsize)+", -1\n") - f.write("\nRV_COMPLIANCE_DATA_END\n") - f.close() - r.close() diff --git a/studies/testgen/testgen-LOAD.py b/studies/testgen/testgen-LOAD.py deleted file mode 100755 index 736b8e05b..000000000 --- a/studies/testgen/testgen-LOAD.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-LOAD.py -# -# Jarred Allen 02 February 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint, seed, getrandbits - -################################## -# functions -################################## - -def rand_reg(): - """Produce a random register (skipping 6 and 31, since they're used for other things)""" - r = randint(1,29) - if r >= 6: - r += 1 - return r - -def rand_value(width): - """Generate a random value which fits in the given width""" - return randint(0, (1 << width) - 1) - -def rand_offset(): - """Generate a random offset""" - ret = rand_value(12) - # print("Random offset: %d" % ret) - return ret - -def rand_source(): - """Generate a random value for the source register, such that the load address is in the test data""" - ret = randint(1 << 12, (1 << 12) + (1 << 10)) - # print("Random source: %d" % ret) - return ret - -def add_offset_to_source(source, offset): - """Find the address from the given source value and offset""" - if offset & 0x800: - offset -= 0x1000 - return source + offset - -def insert_into_data(test_data, source, offset, value, width, xlen): - """Insert the given value into the given location of the test data""" - address = add_offset_to_source(source, offset) - # print("Test #%d" % testcase_num) - # print(f"Source: {source}, Offset: {offset}, Value: {value}, Width: {width}, xlen: {xlen}, Addr: {address}") - if address < 0: - return False - word_offset = address % (xlen // 8) - word_address = address - word_offset - if word_address in test_data: - return False - test_data[word_address] = value * (1 << (word_offset*8)) + ((~(((1 << width)-1) << (word_offset*8))) & rand_value(xlen)) - # print(f"Word: {hex(test_data[word_address])}") - return True - -def align(address, width): - """Align the address to the given width, in bits""" - return address - (address % (width // 8)) - -testcase_num = 0 -def generate_case(xlen, instruction, load_register, source_register, source_register_value, offset, expected): - """Produce the specified test case and return it as a pair of strings, where the first is the test case and the second is the output""" - global testcase_num - if xlen == 64: - store = "sd" - elif xlen == 32: - if instruction in ["lwu", "ld"]: - raise Exception("Instruction %s not supported in RV32I" % instruction) - store = "sw" - else: - raise Exception("Unknown xlen value: %s" % xlen) - if offset >= 0x800: - offset -= 0x1000 - if widths[instruction] != xlen: - expected = expected % (1 << widths[instruction]) - if 'u' not in instruction: - if expected & (1 << (widths[instruction] - 1)): - expected = (expected + ~((1 << widths[instruction]) - 1)) & ((1 << xlen) - 1) - data = f"""# Testcase {testcase_num}: source {offset}(x{source_register} == {source_register_value}), result: x{load_register} == {expected} - la x31, test_data - lui x{source_register}, {source_register_value // (1 << 12)} - addi x{source_register}, x{source_register}, {source_register_value % (1 << 12)} - add x{source_register}, x{source_register}, x31 - {instruction} x{load_register}, {offset}(x{source_register}) - {store} x{load_register}, {(testcase_num*xlen//8) % 0x800}(x6) - RVTEST_IO_ASSERT_GPR_EQ(x8, x{load_register}, {expected}) - - """ - testcase_num += 1 - if testcase_num*xlen//8 % 0x800 == 0: - data += "# Adjust x6 because we're storing too many things\naddi x6, x6, 1024\naddi x6, x6, 1024\n\n" - if xlen == 32: - reference_output = "{:08x}\n".format(expected) - elif xlen == 64: - reference_output = "{:08x}\n{:08x}\n".format(expected % (1 << 32), expected >> 32) - return (data, reference_output) - -def write_header(outfile): - outfile.write(f"""/////////////////////////////////////////// -// -// WALLY-LOAD -// -// Author: {author} -// -// Created {str(datetime.now())} -// -""") - outfile.write(open("testgen_header.S", "r").read()) - -def write_test_data(outfile, test_data, xlen): - # print("Begin writing test data:") - # print("{} entries, from address {} to {}".format(len(test_data), min(test_data.keys()), max(test_data.keys()))) - # print(test_data) - outfile.write(""" - .align 16 -test_data: - - """) - if xlen == 32: - data_word = ".word" - elif xlen == 64: - data_word = ".dword" - else: - raise Exception("Unknown xlen: %d" % xlen) - byte_width = xlen // 8 - for addr in [0] + sorted(test_data.keys()): - if addr in test_data: - word = f" {data_word} {hex(test_data[addr] % (1 << xlen))} # test_data+{hex(addr)}\n" - else: - word = "" - try: - fill_len = (min(k for k in test_data.keys() if k > addr) - addr) // byte_width - 1 - if word == "": - fill_len += 1 - fill = f" .fill {fill_len}, {byte_width}, 0x0\n" - except: - fill = "" - case = word+fill - outfile.write(case) - -################################## -# main body -################################## - -widths = { - "lb": 8, - "lbu": 8, - "lh": 16, - "lhu": 16, - "lw": 32, - "lwu": 32, - "ld": 64, -} -instructions = [i for i in widths] -author = "Jarred Allen" -xlens = [32, 64] -numrand = 100; - -# setup -seed(0) # make tests reproducible - -for xlen in xlens: - testcase_num = 0 - fname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/src/WALLY-LOAD.S".format(xlen) - refname = "../../imperas-riscv-tests/riscv-test-suite/rv{}i/references/WALLY-LOAD.reference_output".format(xlen) - f = open(fname, "w") - r = open(refname, "w") - write_header(f) - test_data = dict() - corner_values = [0x00, 0xFFFFFFFF, 0x7F, 0x7FFF, 0x7FFFFFFF] - if xlen == 64: - corner_values += [0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF] - corner_offsets = [0x800, 0x000, 0x7FF] - for instruction in instructions: - print("Running xlen: %d, instruction: %s" % (xlen, instruction)) - if xlen == 32: - if instruction in ["lwu", "ld"]: - continue - for value in corner_values + [rand_value(widths[instruction]) for _ in range(3)]: - value = value % (1 << widths[instruction]) - source_reg = rand_source() - for offset in corner_offsets + [rand_offset() for _ in range(3)]: - offset = align(offset, widths[instruction]) - source_reg = align(source_reg, widths[instruction]) - if insert_into_data(test_data, source_reg, offset, value, widths[instruction], xlen): - data, output = generate_case(xlen, instruction, rand_reg(), rand_reg(), source_reg, offset, value) - f.write(data) - r.write(output) - while testcase_num % 4: - source = rand_source() - offset = rand_offset() - value = rand_value(widths[instruction]) - if insert_into_data(test_data, source, offset, value, widths['lb'], xlen): - data, output = generate_case(xlen, 'lb', rand_reg(), rand_reg(), source, offset, value) - f.write(data) - r.write(output) - f.write("""# --------------------------------------------------------------------------------------------- - - RVTEST_IO_WRITE_STR(x31, "Test End\\n") - - # --------------------------------------------------------------------------------------------- - - RV_COMPLIANCE_HALT - -RV_COMPLIANCE_CODE_END - - .data - # Input data section -""") - write_test_data(f, test_data, xlen) - f.write("""# Output data section. -RV_COMPLIANCE_DATA_BEGIN - -test_1_res: -""") - f.write(f".fill {testcase_num}, {xlen//8}, -1\n") - f.write("\nRV_COMPLIANCE_DATA_END\n") - f.close() - r.close() diff --git a/studies/testgen/testgen-PIPELINE.py b/studies/testgen/testgen-PIPELINE.py deleted file mode 100755 index 0a2a66491..000000000 --- a/studies/testgen/testgen-PIPELINE.py +++ /dev/null @@ -1,1917 +0,0 @@ -#!/usr/bin/env python3 -################################################################################################### -# testgen-PIPELINE.py -# -# Shriya Nadgauda: snadgauda@hmc.edu & Ethan Falicov: efalicov@hmc.edu -# Created: Feb 2, 2021 -# -# Generate random assembly code for RISC-V Processor Design Validation. -################################################################################################### - -# Many Functions Based On: https://github.com/wallento/riscv-python-model (MIT License) - - -################################################################################################### -# Libraries -################################################################################################### -from random import seed -from random import randint -from enum import Enum -import numpy as np - -import re - -from datetime import datetime - -MEMSTART = 'testdata' -################################################################################################### -# Main Body -################################################################################################### - -class InvalidImmediateValueException(Exception): - pass - -class InvalidRegisterNumberException(Exception): - pass - -class InvalidRegisterValueException(Exception): - pass - -class WriteToImmutableRegisterException(Exception): - pass - -class ReadFromUninitializedMemoryException(Exception): - pass - -class InvalidMemoryWriteLocation(Exception): - pass - -def zeroExtend(inputBits, resultNumBits): - numDigitsToAppend = resultNumBits - len(inputBits) - newBits = inputBits - if numDigitsToAppend > 0: - newBits = ('0' * numDigitsToAppend) + inputBits - return newBits - -def oneExtend(inputBits, resultNumBits): - numDigitsToAppend = resultNumBits - len(inputBits) - newBits = inputBits - if numDigitsToAppend > 0: - newBits = ('1' * numDigitsToAppend) + inputBits - return newBits - -def signExtend(inputBits, resultNumBits): - if inputBits[0] == '1': - return oneExtend(inputBits = inputBits, resultNumBits = resultNumBits) - return zeroExtend(inputBits = inputBits, resultNumBits = resultNumBits) - -def binToDec(inputBits): - if inputBits[0] == '0': - return int(inputBits, 2) - - numBits = len(inputBits) - twoCompMask = (1 << (numBits - 1)) - 1 - msbMask = (1 << (numBits -1)) - - return int((-1 * (msbMask * int(inputBits[0], 2))) + (twoCompMask & int(inputBits, 2))) - -def randBinary(signed, numBits, valueAlignment): - # use this for corners: xlen = 32 here - # corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - # 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - # when not biased don't gen numbers from (|2^(n-2) to 2^(n-2)|) - biased = np.random.randint(0, 3) # on 2 generate random edge case - returnVal = 0 - sign = 0 - if biased < 2: - # print("unbiased") - if not(signed): - returnVal = np.random.randint(0, 2**(numBits - 2)) - - else: - returnVal = np.random.randint(-2**(numBits - 2), 2**(numBits - 2)) - - else: - # print("corner") - if not(signed): - returnVal = np.random.randint(2**(numBits - 2)+1, 2**(numBits - 1)-2) - - else: - sign = np.random.randint(0, 2) # 0 is pos, 1 is neg - if sign: - returnVal = np.random.randint(2**(numBits - 2)+1, 2**(numBits - 1)-2) - else: - returnVal = np.random.randint(-2**(numBits - 1), -2**(numBits - 2)-1) - - binReturnVal = bin(returnVal) #remove "0b" - if returnVal >= 0: - binReturnVal = binReturnVal[2:] - - #make binary correct length - while(len(binReturnVal) < numBits): - binReturnVal = "0" + binReturnVal - else: - binReturnVal = binReturnVal[3:] - #two's compliment - flipped = ''.join('1' if x == '0' else '0' for x in binReturnVal) - added = bin(int(flipped, 2) + 1)[2:] - - while(len(added) < len(flipped)): - added = "0" + added - while(len(added) < numBits): - added = "1" + added - - binReturnVal = added - - # ensure correct value assignment - if valueAlignment == 1: - return binReturnVal - - indexVal = valueAlignment // 2 - returnValue = binReturnVal[:-indexVal] + "0"*indexVal - return returnValue - -def randHex(sign, numBits, divisibleByValue): - val = hex(int(randBinary(sign, numBits*4, divisibleByValue), 2)) - return val - -def randDec(valueRangeMin, valueRangeMax, divisibleByValue): - valRange = (valueRangeMax - valueRangeMin)//divisibleByValue - return (np.random.randint(0, valRange + 1) * divisibleByValue + valueRangeMin) - -class Label: - def __init__(self, name, pcValue): - self.name = name - self.pcValue = pcValue - -class Immediate: - def __init__(self, xlen, numBits = None, signed = 1): - self.xlen = int(xlen) - if numBits == None: - numBits = self.xlen - self.numBits = int(numBits) - self.signed = signed - self.bits = '0'*self.numBits - self.twoCompMask = (1 << (self.numBits - 1)) - 1 - self.msbMask = (1 << (self.numBits -1)) - - self.value = self.getDecValue() - - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - def getDecValue(self): - if self.signed == 1: - return self.getValueSigned() - return self.getValueUnsigned() - - def getMaxValue(self): - if self.signed == 1: - return ((2**(self.numBits - 1)) - 1) - return ((2**self.numBits) - 1) - - def getMinValue(self): - if self.signed == 1: - return (-1 * 2**(self.numBits - 1)) - return 0 - - def signExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return signExtend(inputBits, self.numBits) - - def oneExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return oneExtend(inputBits, self.numBits) - - def zeroExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return zeroExtend(inputBits, self.numBits) - - def setValue(self, newValue, signed = None): - if signed != None: - self.signed = signed - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - if newValue > self.maxValue: - errStr = 'Attempted: {}, Max: {}'.format(newValue, self.maxValue) - raise InvalidImmediateValueException(errStr) - newValue = self.maxValue - - elif newValue < self.minValue: - errStr = 'Attempted: {}, Min: {}'.format(newValue, self.minValue) - raise InvalidImmediateValueException(errStr) - newValue = self.minValue - - self.value = newValue - - bitValue = '' - if (self.signed == 1) and (newValue < 0): - bitValue = bin(self.value)[3:] # Remove the -0b - flipped = ''.join('1' if x == '0' else '0' for x in bitValue) - bitValue = bin(int(flipped, 2) + 1)[2:] - - if len(bitValue) < len(flipped): # Correction for removing sig figs - bitValue = '0'*(len(flipped)-len(bitValue)) + bitValue - - bitValue = self.oneExtend(bitValue) - elif self.signed == 1 and newValue >= 0: - bitValue = bin(self.value)[2:] # Remove the 0b - bitValue = self.zeroExtend(bitValue) - else: - bitValue = bitValue = bin(self.value)[2:] # Remove the 0b - bitValue = self.zeroExtend(bitValue) - - self.bits = bitValue - - def setBits(self, newBits, signed = None): - if signed != None: - self.signed = signed - - if len(newBits) != self.numBits: - errStr = 'Attempted to write {} bits into {} bit immediate'.format(len(newBits), self.numBits) - raise InvalidImmediateValueException(errStr) - - self.bits = newBits - self.value = self.getDecValue() - - def randomize(self, signed = None, minVal = None, maxVal = None, granularity = None): - if signed != None: - self.signed = signed - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - if minVal == None: - minVal = self.minValue - if maxVal == None: - maxVal = self.maxValue - if granularity == None: - granularity = GRANULARITY.BYTE - - granularityNum = 1 - if granularity == GRANULARITY.HALFWORD: - granularityNum = self.xlen // 16 - elif granularity == GRANULARITY.WORD: - granularityNum = self.xlen // 8 - - minVal = int(np.ceil(minVal / granularityNum) * granularityNum) - maxVal = int(np.floor(maxVal / granularityNum) * granularityNum) - - - valRange = (maxVal - minVal)//granularityNum - randValue = randint(0, valRange) * granularityNum + minVal - - self.setValue(randValue, signed=self.signed) - - def getValueSigned(self): - if self.bits[0] == '0': - return int(self.bits, 2) - else: - return int((-1 * (self.msbMask * int(self.bits[0], 2))) + (self.twoCompMask & int(self.bits, 2))) - - def getValueUnsigned(self): - return int(self.bits, 2) - - def __str__(self): - infoStr = '' - if self.signed == 1: - infoStr = 'Signed {} bit value: {}'.format(self.numBits, self.value) - infoStr = 'Unsigned {} bit value: {}'.format(self.numBits, self.value) - return 'Immediate bits {} ({})'.format(self.bits, infoStr) - - @classmethod - def randImm12(cls, xlen, signed = 1): - imm = cls(xlen = xlen, numBits = 12, signed = signed) - imm.randomize() - return imm - - @classmethod - def setImm12(cls, xlen, value, signed = 1): - imm = cls(xlen = xlen, numBits = 12, signed = signed) - imm.setValue(newValue = value) - return imm - - @classmethod - def setImm20(cls, xlen, value, signed = 1): - imm = cls(xlen = xlen, numBits = 20, signed = signed) - imm.setValue(newValue = value, signed=1) - return imm - - @classmethod - def randZImm5(cls, xlen, signed = 0): - imm = cls(xlen = xlen, numBits = 5, signed = signed) - imm.randomize() - return imm - - @classmethod - def randImm13(cls, xlen, signed = 1): - imm = cls(xlen = xlen, numBits = 13, signed = signed) - imm.randomize() - return imm - - @classmethod - def randImm20(cls, xlen, signed = 1): - imm = cls(xlen = xlen, numBits = 20, signed = signed) - imm.randomize() - return imm - -class Register: - def __init__(self, xlen, signed = 1): - self.xlen = int(xlen) - self.numBits = self.xlen - self.signed = signed - self.bits = '0'*self.numBits - self.twoCompMask = (1 << (self.numBits - 1)) - 1 - self.msbMask = (1 << (self.numBits -1)) - - self.value = self.getDecValue() - self.immutable = False - self.regName = None - - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - def getRegName(self): - return self.regName - - def setRegName(self, newName): - self.regName = newName - - def setImmutable(self, immutable): - self.immutable = immutable - - def getDecValue(self): - if self.signed == 1: - return self.getValueSigned() - return self.getValueUnsigned() - - def getMaxValue(self): - if self.signed == 1: - return (2**(self.numBits - 1) - 1) - return (2**(self.numBits) - 1) - - def getMinValue(self): - if self.signed == 1: - return (-1 * 2**(self.numBits - 1)) - return 0 - - def signExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return signExtend(inputBits, self.numBits) - - def oneExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return oneExtend(inputBits, self.numBits) - - def zeroExtend(self, inputBits = None): - if inputBits == None: - inputBits = self.bits - - return zeroExtend(inputBits, self.numBits) - - def setValue(self, newValue, signed = None): - if self.immutable: - raise(WriteToImmutableRegisterException) - else: - if signed != None: - self.signed = signed - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - if newValue > self.maxValue: - errStr = 'Attempted: {}, Max: {}'.format(newValue, self.maxValue) - raise InvalidRegisterValueException(errStr) - newValue = self.maxValue - - elif newValue < self.minValue: - errStr = 'Attempted: {}, Min: {}'.format(newValue, self.minValue) - raise InvalidRegisterValueException(errStr) - newValue = self.minValue - - self.value = newValue - - bitValue = '' - if signed == 1 and newValue < 0: - bitValue = bin(self.value)[3:] # Remove the -0b - flipped = ''.join('1' if x == '0' else '0' for x in bitValue) - bitValue = bin(int(flipped, 2) + 1)[2:] - - if len(bitValue) < len(flipped): # Correction for removing sig figs - bitValue = '0'*(len(flipped)-len(bitValue)) + bitValue - - bitValue = self.oneExtend(bitValue) - elif signed == 1 and newValue >= 0: - bitValue = bin(self.value)[2:] # Remove the 0b - bitValue = self.zeroExtend(bitValue) - else: - bitValue = bitValue = bin(self.value)[2:] # Remove the 0b - bitValue = self.zeroExtend(bitValue) - - self.bits = bitValue - - def setBits(self, newBits, signed = None): - if self.immutable: - raise(WriteToImmutableRegisterException) - else: - if signed != None: - self.signed = signed - - if len(newBits) != self.numBits: - errStr = 'Attempted to write {} bits into {} bit register'.format(len(newBits), self.numBits) - raise InvalidRegisterValueException(errStr) - - self.bits = newBits - self.value = self.getDecValue() - - def randomize(self, signed = None, minVal = None, maxVal = None, granularity = None): - if self.immutable: - raise(WriteToImmutableRegisterException) - else: - if signed != None: - self.signed = signed - self.maxValue = self.getMaxValue() - self.minValue = self.getMinValue() - - if minVal == None: - minVal = self.minValue - if maxVal == None: - maxVal = self.maxValue - if granularity == None: - granularity = GRANULARITY.BYTE - - granularityNum = 1 - if granularity == GRANULARITY.HALFWORD: - granularityNum = self.xlen // 16 - elif granularity == GRANULARITY.WORD: - granularityNum = self.xlen // 8 - - minVal = int(np.ceil(minVal / granularityNum) * granularityNum) - maxVal = int(np.floor(maxVal / granularityNum) * granularityNum) - - - valRange = (maxVal - minVal)//granularityNum - randValue = randint(0, valRange) * granularityNum + minVal - - self.setValue(randValue, signed=self.signed) - - def getValueSigned(self): - if self.bits[0] == 0: - return int(self.bits, 2) - else: - return int((-1 * (self.msbMask * int(self.bits[0], 2))) + (self.twoCompMask & int(self.bits, 2))) - - def getValueUnsigned(self): - return int(self.bits, 2) - - def __str__(self): - infoStr = '' - if self.signed == 1: - infoStr += 'Signed' - else: - infoStr += 'Unsigned' - - if self.immutable == True: - infoStr += ' Immutable' - - - return('Register {} bits: {} ({} value: {})'.format(self.regName, self.bits, infoStr, self.value)) - - def __add__(self, other): - self.setValue(self.value + int(other)) - return self - - @classmethod - def immutableRegister(cls, xlen, value, signed = 1): - reg = cls(xlen = xlen) - reg.setValue(newValue = value, signed = signed) - reg.setImmutable(immutable = True) - return reg - -class RegFile(): - def __init__(self, xlen, numRegs = 32, immutableRegsDict = {0 : 0}, prefix = 'x'): - self.xlen = xlen - self.numRegs = numRegs - self.regs = [] - self.immutableRegsList = [] - self.prefix = prefix - - for i in range(0, numRegs): - self.regs.append(Register(xlen)) - self.regs[-1].setRegName('{}{}'.format(prefix, i)) - - - for immutableRegKey, immutableRegVal in immutableRegsDict.items(): - self.regs[immutableRegKey].setValue(newValue = immutableRegVal, signed = 1) - self.immutableRegsList.append(immutableRegKey) - - def getRandReg(self): - reg = randint(1, len(self.regs)-1) - while(reg in self.immutableRegsList): - reg = randint(1, len(self.regs)-1) - return self.regs[reg] - - # def getRandMemReg(self): - # reg = randint(1, len(self.memoryreg)-1) - # while(reg in self.immutableRegsList): - # reg = randint(1, len(self.memoryreg)-1) - # return str(reg) - - def randomize(self): - for regNum in range(0, self.numRegs): - if regNum not in self.immutableRegsList: - self.regs[regNum].randomize() - - def setRegValue(self, regNum, newValue, signed = None): - if regNum in self.immutableRegsList: - errStr = 'Write to x{} not allowed'.format(regNum) - raise WriteToImmutableRegisterException(errStr) - if regNum > self.numRegs - 1: - errStr = 'Write to x{} exceeds number of registers: {}'.format(regNum, self.numRegs) - raise InvalidRegisterNumberException(errStr) - - - self.regs[regNum].setValue(newValue = newValue, signed = signed) - - def setRegBits(self, regNum, newBits, signed = None): - if regNum in self.immutableRegsList: - errStr = 'Write to x{} not allowed'.format(regNum) - raise WriteToImmutableRegisterException(errStr) - - if regNum > self.numRegs - 1: - errStr = 'Write to x{} exceeds number of registers: {}'.format(regNum, self.numRegs) - raise InvalidRegisterNumberException(errStr) - - self.regs[regNum].setBits(newBits = newBits, signed = signed) - - def __str__(self): - formattedString = '' - for x in range(0, len(self.regs)): - formattedString += 'x{}:\t{}\n'.format(str(x), str(self.regs[x])) - return formattedString - -class Memory(): - def __init__(self, xlen): - self.memDict = {} #keys: strings, values: binary strings - self.xlen = int(xlen) - self.minVal = 0 - self.maxVal = 2047 - def populateMemory(self, memDict): - # add all values of memDict to self.memDict - # overwrites any values that already exist - for key in memDict.keys(): - self.memDict[key] = memDict[key] - - def updateMemory(self, addr, granularity, value): - # sign extend value to 32 bits - if addr > self.maxVal: - errStr = 'Tried to write to invalid memory location {} max {}'.format(value, self.maxVal) - raise InvalidMemoryWriteLocation(errStr) - exValue = signExtend(value, self.xlen) - self.memDict[addr] = exValue - - def readMemory(self, addr, granularity): - # check if memory is unitilaized - if addr not in self.memDict.keys(): - errStr = 'Tried to read from uninitialized address: {}'.format(addr) - raise ReadFromUninitializedMemoryException(errStr) - - val = self.memDict[addr] - if granularity == GRANULARITY.WORD: - val = val - elif granularity == GRANULARITY.HALFWORD: - val = val[-(self.xlen//2):] - else: - val = val[-(self.xlen//4):] - if val == "": - return '0' - return val - - def genRandMemoryValue(self): - - #generate a random value - minVal = self.minVal - maxVal = self.maxVal - randValue = randint(0, self.maxVal + 1) - - # #convert to binary string - # bitValue = '' - # bitValue = bitValue = bin(randValue)[2:] # Remove the 0b - # bitValue = signExtend(bitValue, self.xlen) - - return randValue - -class Model(): - def __init__(self, xlen, numRegs, immutableRegsDict, initPc = 0): - self.xlen = int(xlen) - self.memory = Memory(xlen=self.xlen) - self.regFile = RegFile(xlen=self.xlen, immutableRegsDict = immutableRegsDict) - self.pc = Register(xlen=self.xlen, signed=0) - self.pc.setValue(newValue=initPc) - self.pc.setRegName(newName = 'PC') - self.memStart = 0x8000400 - self.memoryImmediateCounter = 0 - self.resultImmediateCounter = 0 - self.totalStoreCount = 0 - -class TestGen(): - def __init__(self, numInstr, immutableRegsDict, instrSet, imperasPath): - self.numInstr = numInstr - self.instrSet = instrSet - self.xlen = int((re.search(r'\d+', instrSet)).group()) - self.model = Model(xlen=self.xlen, numRegs=16, immutableRegsDict = immutableRegsDict) - - self.prevLabel = 0 - self.test_count = 0 - - self.imperasPath = imperasPath + instrSet.lower() + '/' - self.exportTestName = 'PIPELINE' - if (self.numInstr == 100000): - self.exportTestName += "-100K" - elif (self.numInstr == 1000000): - self.exportTestName += "-1M" - self.basename = 'WALLY-'+ self.exportTestName - self.fname = self.imperasPath + "src/" + self.basename + ".S" - self.refname = self.imperasPath + "references/" + self.basename + ".reference_output" - - def genTestInstr(self, reg): - imm = Immediate.setImm12(xlen = self.xlen, value = self.model.resultImmediateCounter) - reg6 = self.model.regFile.regs[6] - out = [Instr.issue(model = self.model, instrName = "sw", rs2 = reg, imm = imm, rs1 = reg6)] - self.model.resultImmediateCounter += 4 - if (self.model.resultImmediateCounter == 2040): - # Reset - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2040) - reg6.setImmutable(False) - wreset = Instr.issue(model = self.model, instrName = "addi", rd = reg6, imm = imm2, rs1 = reg6) - reg6.setImmutable(True) - self.model.resultImmediateCounter = 0 - out.append(wreset) - out.append('\n') - self.model.totalStoreCount += 1 - return out - - def branchInstruction(self, instr): - # get field and granularity of instruction - - # randomly determine forward or back branch direction - fwd = np.random.randint(0, 2) #fwd on 1, bwd on 0 - taken = np.random.randint(0,2) #not taken on 0, taken on 1 - - # pick 2 registers for branch comparison - reg1 = self.model.regFile.getRandReg() - reg2 = reg1 - reg0 = self.model.regFile.regs[0] - while(reg2 == reg1): - reg2 = self.model.regFile.getRandReg() - - instructions = [] - - - if (fwd == 1): - # set r1 and r2 to what they should be to do the branching we want - if (instr == "beq" and taken==1) or (instr == "bne" and taken==0) or \ - (instr == "blt" and taken==0) or (instr == "bge" and taken==1) or \ - (instr == "bltu" and taken==0) or (instr == "bgeu" and taken==1): #r1 = r2 - newInstr = Instr.issue(model = self.model, instrName="add", rd = reg1, rs1 = reg2, rs2 = reg0) - instructions.append(newInstr) - - elif (instr == "beq" and taken==0) or (instr == "bne" and taken==1) or \ - (instr == "blt" and taken==1) or (instr == "bltu" and taken==1): #r2 = r1 + 1 - imm = Immediate.setImm12(xlen = self.xlen, value = 1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - else: #r2 = r1 - 1 - imm = Immediate.setImm12(xlen = self.xlen, value = -1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - # add branching instruction - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - branch = Instr.issue(model = self.model, instrName = instr, rs1 = reg2, rs2 = reg1, label = label, dir = 'f') - instructions.append(branch) - numInstr = np.random.randint(0, 6) - # add random alu instructions after branching before branch point - for i in range(0, numInstr): - curr = "RAND ALU INSTRUCTION" - rd = self.model.regFile.getRandReg() - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instr = "add" - if (taken == 0): - instructions.append('add {}, {}, {}'.format(rd.getRegName(), r1.getRegName(), r2.getRegName())) - else: - instructions.append(Instr.issue(model = self.model, instrName = instr, rd = rd, rs1 = r1, rs2 = r2)) - - instructions.append(str(self.prevLabel) + ":") - self.prevLabel += 1 - return instructions - else: - if (not taken): - if instr == "beq": - randImm = np.random.randint(1, 10) - imm = Immediate.setImm12(xlen = self.xlen, value = randImm) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - elif instr == "bne": - imm = Immediate.setImm12(xlen = self.xlen, value = 0) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - elif instr == "bltu": - # deals with overflow - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - randImm = np.random.randint(1, 11) - imm = Immediate.setImm12(xlen = self.xlen, value = randImm) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - elif instr == "blt": - # deals with overflow - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - randImm = np.random.randint(1, 11) - imm = Immediate.setImm12(xlen = self.xlen, value = randImm) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - elif instr == "bgeu": - # deals with overflow - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - imm2 = Immediate.setImm12(xlen = self.xlen, value = 15) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - randImm = np.random.randint(-10, 0) - imm = Immediate.setImm12(xlen = self.xlen, value = randImm) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - elif instr == "bge": - imm2 = Immediate.setImm12(xlen = self.xlen, value = 15) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - randImm = np.random.randint(-10, 0) - imm = Immediate.setImm12(xlen = self.xlen, value = randImm) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - numInstr = np.random.randint(0, 6) - # add random alu instructions after branching before branch point - for i in range(0, numInstr): - curr = "RAND ALU INSTRUCTION" - rd = self.model.regFile.getRandReg() - while(rd == reg2 or rd == reg1): - rd = self.model.regFile.getRandReg() - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instrJunk = "add" - instructions.append('add {}, {}, {}'.format(rd.getRegName(), r1.getRegName(), r2.getRegName())) - branch = Instr.issue(model = self.model, instrName = instr, rs1 = reg2, rs2 = reg1, label = label, dir = 'b') - instructions.append(branch) - else: - #setup reg instructions before any branching stuff - if instr == "beq": - numTimesRepeat = 1 #can only be repeated once with the way we are doing this - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = -1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr) - - elif instr == "bne": - numTimesRepeat = np.random.randint(2, 6) - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = -1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr) - - elif instr == "bltu": - numTimesRepeat = np.random.randint(2, 6)*(-1) - # deals with overflow - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = 1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr) - - elif instr == "blt": - # deals with overflow - imm2 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - numTimesRepeat = np.random.randint(2, 6)*(-1) - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = 1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr) - - elif instr == "bgeu": - numTimesRepeat = np.random.randint(2, 6) - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - - # deals with overflow - imm1 = Immediate.setImm12(xlen = self.xlen, value = 2) - newInstr1 = Instr.issue(model = self.model, instrName="srli", rd = reg1, rs1 = reg1, imm = imm1) - instructions.append(newInstr1) - - imm2 = Immediate.setImm12(xlen = self.xlen, value = 15) - newInstr2 = Instr.issue(model = self.model, instrName="addi", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr2) - - newInstr3 = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr3) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = -1) - newInstr4 = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr4) - - elif instr == "bge": - imm2 = Immediate.setImm12(xlen = self.xlen, value = 15) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg1, rs1 = reg1, imm = imm2) - instructions.append(newInstr) - - numTimesRepeat = np.random.randint(2, 6) - imm = Immediate.setImm12(xlen = self.xlen, value = numTimesRepeat) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg1, imm = imm) - instructions.append(newInstr) - - label = Label(name = self.prevLabel, pcValue = self.model.pc.getValueUnsigned()) - instructions.append(str(self.prevLabel) + ":") - - imm = Immediate.setImm12(xlen = self.xlen, value = -1) - newInstr = Instr.issue(model = self.model, instrName="addi", rd = reg2, rs1 = reg2, imm = imm) - instructions.append(newInstr) - - numInstr = np.random.randint(0, 5) - for i in range(0, numInstr): - curr = "RAND ALU INSTRUCTION" - rd = self.model.regFile.getRandReg() - while(rd == reg2) or (rd == reg1): - rd = self.model.regFile.getRandReg() - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instrJunk = "add" - instructions.append(Instr.issue(model = self.model, instrName = instrJunk, rd = rd, rs1 = r1, rs2 = r2)) - - branch = Instr.issue(model = self.model, instrName = instr, rs1 = reg2, rs2 = reg1, label = label, dir = 'b') - instructions.append(branch) - self.prevLabel += 1 - return instructions - - - def getForwardingInstructions(self, instr): - ld_instr = instr - divBy = 1 - - granularity = None - if (instr == "lw"): - granularity = GRANULARITY.WORD - elif (instr == "lh") | (instr == 'lhu'): - divBy = self.xlen//2 - granularity = GRANULARITY.HALFWORD - else: - divBy = self.xlen//4 - granularity = GRANULARITY.BYTE - - instructions = [] - - rd = self.model.regFile.getRandReg() - reg1 = self.model.regFile.regs[7] - - memVal = self.model.memoryImmediateCounter - self.model.memoryImmediateCounter += 4 - if instr == "ld": - if ((memVal + reg1.getValueUnsigned()) % 8) != 0: - memVal -= 4 - self.model.memoryImmediateCounter -= 4 # we haven't read from a new location - - - - if (self.model.memoryImmediateCounter == 2040): - self.model.memoryImmediateCounter = 0 - immMem = Immediate.setImm12(xlen = self.model.xlen, value = 2040) - instructions.append(Instr.issue(model = self.model, instrName = "addi" , rd = reg1, rs1 = reg1, imm = immMem)) - - - imm1 = Immediate.setImm12(xlen = self.model.xlen, value = memVal) - - reg2 = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = "sw" , rs2 = reg2, rs1 = reg1, imm = imm1)) - - - while (rd == reg1): - rd = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = ld_instr, rd = rd, rs1 = reg1, imm = imm1)) - - return instructions - - def jumpInstruction(self, instr): - # fields, alignment = self.instrDict.instr[instr] - granularity = GRANULARITY.BYTE - divBy = 1 - - # randomly determine forward or back branch direction - fwd = np.random.randint(0, 2) #fwd on 1, bwd on 0 - taken = np.random.randint(0,2) #not taken on 0, taken on 1 - - reg_pc = self.model.regFile.getRandReg() - instructions = [] - - label1 = Label(name = 1, pcValue = self.model.pc.getValueUnsigned()) - label2 = Label(name = 2, pcValue = self.model.pc.getValueUnsigned()) - label3 = Label(name = 3, pcValue = self.model.pc.getValueUnsigned()) - - if fwd == 1: - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg_pc, label = label1, dir = "f") - instructions.append(newInstr) - - numInstr = np.random.randint(0, 6) - # add random alu instructions after jumping before jump point - reg_check = self.model.regFile.getRandReg() - for i in range(0, numInstr): - rd = self.model.regFile.getRandReg() - while (rd == reg_pc): - rd = self.model.regFile.getRandReg() - reg_check = rd - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = "and", rd = rd, rs1 = r1, rs2 = r2)) - instructions.append("1:") - self.model.pc += 4 - - # #make sure jump was taken - check_instr = self.genTestInstr(reg_check) - for check in check_instr: - instructions.append(check) - - # #check value in pc + 4 reg - check_instr = self.genTestInstr(reg_pc) - for check in check_instr: - instructions.append(check) - else: - reg1 = self.model.regFile.getRandReg() - reg2 = self.model.regFile.getRandReg() - while reg2 == reg1: - reg2 = self.model.regFile.getRandReg() - - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg1, label = label1, dir = "f") - instructions.append(newInstr) - # instructions.append("jal x" + reg1 + ", 1f") - - instructions.append("2:") - self.model.pc += 4 - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg2, label = label3, dir = "f") - instructions.append(newInstr) - # instructions.append("jal x" + reg2 + ", 3f") - - instructions.append("1:") - self.model.pc += 4 - - numInstr = np.random.randint(0,6) - for i in range(0, numInstr): - rd = self.model.regFile.getRandReg() - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = 'and', rd = rd, rs1 = r1, rs2 = r2)) - - #test case here - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg2, label = label2, dir = "b") - instructions.append(newInstr) - # instructions.append("jal x" + reg2 + ", 2b") - instructions.append("3:") - self.model.pc += 4 - - check_instr = self.genTestInstr(reg1) - for check in check_instr: - instructions.append(check) - - # jump to 1 - # #2 - # jump to 3 - # #1 - # junk here - # test: jump to 2 - # #3 - # check answer from 1 - return instructions - - - def jumpRInstruction(self, instr): - # fields, alignment = self.instrDict.instr[instr] - granularity = GRANULARITY.BYTE - divBy = 1 - - # randomly determine forward or back branch direction - fwd = np.random.randint(0, 2) #fwd on 1, bwd on 0 - - reg_pc = self.model.regFile.getRandReg() - instructions = [] - - label1 = Label(name = 1, pcValue = self.model.pc.getValueUnsigned()) - label2 = Label(name = 2, pcValue = self.model.pc.getValueUnsigned()) - label3 = Label(name = 3, pcValue = self.model.pc.getValueUnsigned()) - - if fwd == 1: - numInstr = np.random.randint(0, 6) - - rs1 = self.model.regFile.getRandReg() - while (rs1 == reg_pc): - rs1 = self.model.regFile.getRandReg() - - # TODO fix the value of rs1 - should be pc location of "1f" - rs1.setValue(newValue = 0) - - imm = Immediate.setImm12(xlen = self.model.xlen, value = 0) - - instructions.append('la {}, {}'.format(rs1.regName , "1f")) - self.model.pc += 8 - - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg_pc, rs1 = rs1, imm = imm) - instructions.append(newInstr) - - # add random alu instructions after jumping before jump point - reg_check = self.model.regFile.getRandReg() - for i in range(0, numInstr): - rd = self.model.regFile.getRandReg() - while (rd == reg_pc): - rd = self.model.regFile.getRandReg() - reg_check = rd - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = "and", rd = rd, rs1 = r1, rs2 = r2)) - - instructions.append("1:") - self.model.pc += 4 - - #make sure jump was taken - check_instr = self.genTestInstr(reg_check) - for check in check_instr: - instructions.append(check) - - #check value in pc + 4 reg - check_instr = self.genTestInstr(reg_pc) - for check in check_instr: - instructions.append(check) - else: - reg1 = self.model.regFile.getRandReg() - reg2 = self.model.regFile.getRandReg() - while reg2 == reg1: - reg2 = self.model.regFile.getRandReg() - - jumpDestVal = self.model.pc.value + 4 - newInstr = Instr.issue(model = self.model, instrName='jal', rd = reg1, label = label1, dir = "f") - instructions.append(newInstr) - # instructions.append("jal x" + reg1 + ", 1f") - - instructions.append("2:") - self.model.pc += 4 - - newInstr = Instr.issue(model = self.model, instrName='jal', rd = reg2, label = label3, dir = "f") - instructions.append(newInstr) - # instructions.append("jal x" + reg2 + ", 3f") - - instructions.append("1:") - self.model.pc += 4 - - - rs1 = self.model.regFile.getRandReg() - while (rs1 == reg_pc): - rs1 = self.model.regFile.getRandReg() - - imm = Immediate.setImm12(xlen = self.model.xlen, value = 0) - - - instructions.append('la {}, {}'.format(rs1.regName ,"2b")) - self.model.pc += 8 - - - rs1.setValue(newValue = 0) #TODO: this value is wrong, should be address of label - imm = Immediate.setImm12(xlen = self.model.xlen, value = 0) - - - numInstr = np.random.randint(0,6) - for i in range(0, numInstr): - rd = self.model.regFile.getRandReg() - while(rd == rs1) or (rd == reg_pc): - rd = self.model.regFile.getRandReg() - r1 = self.model.regFile.getRandReg() - r2 = self.model.regFile.getRandReg() - instructions.append(Instr.issue(model = self.model, instrName = 'and', rd = rd, rs1 = r1, rs2 = r2)) - - #test case here - newInstr = Instr.issue(model = self.model, instrName=instr, rd = reg_pc, rs1 = rs1, imm = imm) - instructions.append(newInstr) - # instructions.append("jal x" + reg2 + ", 2b") - instructions.append("3:") - self.model.pc += 4 - - check_instr = self.genTestInstr(reg1) - for check in check_instr: - instructions.append(check) - - check_instr = self.genTestInstr(reg_pc) - for check in check_instr: - instructions.append(check) - - # jump to 1 - # #2 - # jump to 3 - # #1 - # junk instructions - # ... - # ... - # test instruction to 2 - # #3 - # check answer from 1 - return instructions - - def generateASM(self, instrSet, instrTypes): - generatedInstructions = [] - - # for memLocation in self.model.memory.memDict.keys(): - # memData = self.model.memory.readMemory(addr = memLocation, granularity = GRANULARITY.WORD) - # memDataVal = hex(int(memData, 2)) - # generatedInstructions.append('li x2, MASK_XLEN({})'.format(memDataVal)) - # self.model.pc += 8 - # generatedInstructions.append('li x3, MASK_XLEN({})'.format(memLocation)) - # self.model.pc += 8 - # generatedInstructions.append('sw x2, 0(x3)') - # self.model.pc += 4 - - generatedInstructions.append('la x7, test_data') - self.model.pc += 8 - - for reg in self.model.regFile.regs: - if (int(reg.regName[-1:]) not in self.model.regFile.immutableRegsList) : - immHex = randHex(False, 5, 1) - imm = int(immHex, 16) - reg.setValue(imm) - generatedInstructions.append('li {}, MASK_XLEN({})'.format(reg.getRegName(), immHex)) - self.model.pc += 8 - elif (reg == self.model.regFile.regs[0]): - immHex = 0 - imm = 0 - reg.setValue(imm) - generatedInstructions.append('li {}, MASK_XLEN({})'.format(reg.getRegName(), immHex)) - self.model.pc += 8 - elif (reg == self.model.regFile.regs[6]): - # immHex = 0 - # imm = 0 - # reg.setValue(imm) - # generatedInstructions.append('la {}, {}'.format(reg.getRegName(), "test_1_res")) - # self.model.pc += 8 - pass - for i in range(0, self.numInstr): - # decide which instruction to issue - randInstr = instrSet[randint(0, len(instrSet)-1)] - - randNum = randint(0, 2) - if randInstr in InstrTypes['B']: - newInstr = self.branchInstruction(instr = randInstr) - for i in newInstr: - generatedInstructions.append(i) - elif randInstr in InstrTypes['J']: - newInstr = self.jumpInstruction(instr = randInstr) - for i in newInstr: - generatedInstructions.append(i) - elif randInstr[0] == 'l' and randNum == 0 and randInstr != "lui": - newInstr = self.getForwardingInstructions(instr = randInstr) - for i in newInstr: - generatedInstructions.append(i) - else: - if randInstr in InstrTypes['R']: - rd = self.model.regFile.getRandReg() - rs1 = self.model.regFile.getRandReg() - rs2 = self.model.regFile.getRandReg() - instr = Instr.issue(model = self.model, instrName = randInstr, rd = rd, rs1 = rs1, rs2 = rs2) - generatedInstructions.append(instr) - - testInstrs = self.genTestInstr(rd) - for testInstr in testInstrs: - generatedInstructions.append(testInstr) - - elif randInstr in InstrTypes['I']: - if randInstr == "jalr": - newInstr = self.jumpRInstruction(instr = randInstr) - for i in newInstr: - generatedInstructions.append(i) - # memory instruction - elif randInstr[0] == 'l': - rs1 = self.model.regFile.regs[7] - - memLocation = list(self.model.memory.memDict.keys())[randint(0, len(self.model.memory.memDict.keys()) -1)] - if randInstr == "ld": - if ((memLocation + rs1.getValueUnsigned()) % 8) != 0: - if (memLocation != 0): - memLocation -=4 - else: - memLocation = 4 - - rd = self.model.regFile.getRandReg() - - imm12 = Immediate.setImm12(xlen = self.model.xlen, value = memLocation) - instr = Instr.issue(model = self.model, instrName = randInstr, rd = rd, rs1 = rs1, imm = imm12) - generatedInstructions.append(instr) - - testInstrs = self.genTestInstr(rd) - for testInstr in testInstrs: - generatedInstructions.append(testInstr) - else: - rd = self.model.regFile.getRandReg() - rs1 = self.model.regFile.getRandReg() - imm12 = Immediate.randImm12(xlen = self.model.xlen) - - instr = Instr.issue(model = self.model, instrName = randInstr, rd = rd, rs1 = rs1, imm = imm12) - generatedInstructions.append(instr) - - testInstrs = self.genTestInstr(rd) - for testInstr in testInstrs: - generatedInstructions.append(testInstr) - - elif randInstr in InstrTypes['S']: - rs1 = self.model.regFile.regs[7] - - immValue = self.model.memoryImmediateCounter - self.model.memoryImmediateCounter += 4 - if randInstr == 'Sd': - if ((immValue + rs1.getValueUnsigned()) % 8) != 0: - immValue -= 4 - self.model.memoryImmediateCounter -= 4 #haven't put a value in a new mem locatoin - - rs2 = self.model.regFile.getRandReg() - - - immMem = Immediate.setImm12(xlen = self.model.xlen, value = 2040) - if (self.model.memoryImmediateCounter == 2040): - self.model.memoryImmediateCounter = 0 - generatedInstructions.append(Instr.issue(model = self.model, instrName = "addi" , rd = rs1, rs1 = rs1, imm = immMem)) - - imm12 = Immediate.setImm12(xlen = self.model.xlen, value = immValue) - instr = Instr.issue(model = self.model, instrName = randInstr, rs1 = rs1, rs2 = rs2, imm = imm12) - generatedInstructions.append(instr) - - elif randInstr in InstrTypes['U']: - rd = self.model.regFile.getRandReg() - imm20 = Immediate.randImm20(xlen = self.model.xlen, signed = 0) - instr = Instr.issue(model = self.model, instrName = randInstr, rd = rd, imm = imm20) - generatedInstructions.append(instr) - - testInstrs = self.genTestInstr(rd) - for testInstr in testInstrs: - generatedInstructions.append(testInstr) - - elif randInstr in InstrTypes['R4']: - continue - else: - # INVALID INSTR - print(randInstr) - print("You made a typo") - return generatedInstructions - - def exportASM(self, instrSet, instrTypes): - asmFile = open(self.fname, 'w') - refFile = open(self.refname, 'w') - - # Custom Header - line = "///////////////////////////////////////////\n" - asmFile.write(line) - line ="// "+self.fname+ "\n// " + "Ethan Falicov & Shriya Nadgauda" + "\n" - asmFile.write(line) - line ="// Created " + str(datetime.now()) + "\n" + "\n" - asmFile.write(line) - line = "// Begin Tests" + "\n" - asmFile.write(line) - - # Generic Header - headerFile = open("testgen_header.S", "r") - for line in headerFile: - asmFile.write(line) - asmFile.write("\n") - - - # Write Instructions - generatedInstructions = self.generateASM(instrSet = INSTRSETS[instrSet], instrTypes = instrType) - for generatedInstr in generatedInstructions: - asmFile.write("\t" + generatedInstr + "\n") - if ("RVTEST_IO_ASSERT_GPR_EQ" in generatedInstr): - asmFile.write("\n") - - # Footer - footerFile = open("testgen_footer.S", "r") - lineNum = 0 - for line in footerFile: - asmFile.write(line) - if lineNum == 14: - asmFile.write('test_data:\n') - memList = list(self.model.memory.memDict.keys()) - memList.sort() - paddingSize = 0 - for memLoc in memList: - hexVal = int(self.model.memory.memDict[memLoc],2) - hexDigitSize = self.model.xlen / 4 - formattedStr = '0x{0:0{1}x}'.format(hexVal, hexDigitSize) - if self.model.xlen == 64: - asmFile.write('\t.dword {}\n'.format(formattedStr)) - else: - asmFile.write('\t.word {}\n'.format(formattedStr)) - lineNum += 1 - - asmFile.write("\n") - line = "\t.fill " + str(self.model.totalStoreCount) + ", " + str(self.xlen//8) + ", -1\n" - asmFile.write(line) - asmFile.write("\n") - - line = "\nRV_COMPLIANCE_DATA_END\n" - asmFile.write(line) - - asmFile.close() - refFile.close() - -class Instr(): - @classmethod - def issue(self, model, instrName, **kwargs): - funcName = 'Instr_' + str(instrName) - return getattr(Instr, funcName)(model = model, **kwargs) - - @classmethod - def Instr_label(self, model, label = None): - label.pcValue = model.pc.value - model.pc += 4 - return '{}:'.format(label.name) - - ############################################################################################### - # RV32I Instructions - ############################################################################################### - @classmethod - def Instr_lb(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = signExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.BYTE), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lb {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_lh(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = signExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.HALFWORD), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lh {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_lw(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = signExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.WORD), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lw {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_lbu(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = zeroExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.BYTE), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lbu {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_lhu(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = zeroExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.HALFWORD), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lhu {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_addi(self, model, rd = None, rs1 = None, imm = None): - newValue = rs1.getDecValue() + imm.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'addi {}, {}, MASK_XLEN({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_slli(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[-(len(bits) - immShift):] - shiftedExt = binToDec(inputBits = shifted + '0'*(model.xlen - len(shifted))) - rd.setValue(newValue = shiftedExt, signed = 1) - model.pc += 4 - return 'slli {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_slti(self, model, rd = None, rs1 = None, imm = None): - if (rs1.getValueSigned() < imm.getValueSigned()): - rd.setValue(newValue = 1, signed = 1) - else: - rd.setValue(newValue = 0, signed = 1) - model.pc += 4 - return 'slti {}, {}, SEXT_IMM({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_sltiu(self, model, rd = None, rs1 = None, imm = None): - if (rs1.getValueUnsigned() < imm.getValueUnsigned()): - rd.setValue(newValue = 1, signed = 1) - else: - rd.setValue(newValue = 0, signed = 1) - model.pc += 4 - return 'slti {}, {}, SEXT_IMM({})'.format(rd.getRegName(),rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_xori(self, model, rd = None, rs1 = None, imm = None): - newValue = rs1.getDecValue() ^ imm.getDecValue() - rd.setValue(newValue = newValue, signed = rs1.signed) - model.pc += 4 - return 'xori {}, {}, SEXT_IMM({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_srli(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[0:len(bits) - immShift] - extShifted = zeroExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'srli {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_srai(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[0:len(bits) - immShift] - extShifted = signExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'srai {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_ori(self, model, rd = None, rs1 = None, imm = None): - rd.setValue(newValue = (rs1.getDecValue() | imm.getDecValue()), signed = rs1.signed) - return 'ori {}, {}, SEXT_IMM({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_andi(self, model, rd = None, rs1 = None, imm = None): - rd.setValue(newValue = (rs1.getDecValue() & imm.getDecValue()), signed = rs1.signed) - return 'andi {}, {}, SEXT_IMM({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_auipc(self, model, rd = None, imm = None): - rd.setValue(newValue = binToDec(inputBits = imm.bits[:-12] + '0'*12) + model.pc.getDecValue(), signed = 1) - return 'auipc {}, MASK_XLEN({})'.format(rd.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_sb(self, model, rs1 = None, rs2 = None, imm = None): - addr = imm.getDecValue() - if addr in model.memory.memDict.keys(): - originalMem = model.memory.readMemory(addr = addr, granularity = GRANULARITY.WORD) - model.memory.updateMemory(addr = addr, value = originalMem[:-8] + rs2.bits[-8:], granularity = GRANULARITY.WORD) - else: - model.memory.updateMemory(addr = addr, value = '0'*(model.xlen - 8) + rs2.bits[-8:], granularity = GRANULARITY.WORD) - model.pc += 4 - return 'sb {}, {}({})'.format(rs2.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_sh(self, model, rs1 = None, rs2 = None, imm = None): - addr = imm.getDecValue() - if addr in model.memory.memDict.keys(): - originalMem = model.memory.readMemory(addr = addr, granularity = GRANULARITY.WORD) - model.memory.updateMemory(addr = addr, value = originalMem[:-16] + rs2.bits[-16:], granularity = GRANULARITY.WORD) - else: - model.memory.updateMemory(addr = addr, value = '0'*(model.xlen - 16) + rs2.bits[-16:], granularity = GRANULARITY.WORD) - model.pc += 4 - return 'sh {}, {}({})'.format(rs2.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_sw(self, model, rs1 = None, rs2 = None, imm = None): - addr = imm.getDecValue() - model.memory.updateMemory(addr = addr, value = rs2.bits, granularity = GRANULARITY.WORD) - model.pc += 4 - return 'sw {}, {}({})'.format(rs2.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_add(self, model, rd = None, rs1 = None, rs2 = None): - newValue = rs1.getDecValue() + rs2.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'add {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_sub(self, model, rd = None, rs1 = None, rs2 = None): - newValue = rs1.getDecValue() - rs2.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'sub {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_sll(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[-(len(bits) - rs2Shift):] - shiftedExt = binToDec(inputBits = shifted + '0'*(model.xlen - len(shifted))) - rd.setValue(newValue = shiftedExt, signed = 1) - model.pc += 4 - return 'sll {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_slt(self, model, rd = None, rs1 = None, rs2 = None): - if (rs1.getDecValue() < rs2.getDecValue()): - rd.setValue(newValue = 1, signed = 1) - else: - rd.setValue(newValue = 0, signed = 1) - model.pc += 4 - return 'slt {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - - @classmethod - def Instr_sltu(self, model, rd = None, rs1 = None, rs2 = None): - if (rs1.getValueUnsigned() < rs2.getValueUnsigned()): - rd.setValue(newValue = 1, signed = 1) - else: - rd.setValue(newValue = 0, signed = 1) - model.pc += 4 - return 'sltu {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_xor(self, model, rd = None, rs1 = None, rs2 = None): - rd.setValue(newValue = (rs1.getDecValue() ^ rs2.getDecValue()), signed = rs1.signed) - model.pc += 4 - return 'xor {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_srl(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[0:len(bits) - rs2Shift] - extShifted = zeroExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'srl {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_sra(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[0:len(bits) - rs2Shift] - extShifted = signExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'sra {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_or(self, model, rd = None, rs1 = None, rs2 = None): - rd.setValue(newValue = (rs1.getDecValue() | rs2.getDecValue()), signed = rs1.signed) - model.pc += 4 - return 'or {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_and(self, model, rd = None, rs1 = None, rs2 = None): - rd.setValue(newValue = (rs1.getDecValue() & rs2.getDecValue()), signed = rs1.signed) - model.pc += 4 - return 'and {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_lui(self, model, rd = None, imm = None): - rd.setValue(newValue = binToDec(inputBits = imm.bits[:20] + '0'*(model.xlen-20)) , signed = 1) - model.pc += 4 - return 'lui {}, {}'.format(rd.getRegName(), imm.getDecValue()) - - - @classmethod - def Instr_beq(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueSigned() == rs2.getValueSigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'beq {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_bne(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueSigned() != rs2.getValueSigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'bne {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_blt(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueSigned() < rs2.getValueSigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'blt {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_bge(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueSigned() >= rs2.getValueSigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'bge {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_bltu(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueUnsigned() < rs2.getValueUnsigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'bltu {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_bgeu(self, model, rs1 = None, rs2 = None, label = None, dir = None): - if (rs1.getValueUnsigned() >= rs2.getValueUnsigned()): - model.pc.setValue(label.pcValue) - else: - model.pc += 4 - return 'bgeu {}, {}, {}{}'.format(rs1.getRegName(), rs2.getRegName(), label.name, dir) - - @classmethod - def Instr_jalr(self, model, rd = None, rs1 = None, imm = None): - rd.setValue(newValue = model.pc.getDecValue() + 4, signed = 1) - model.pc.setValue(rs1.getDecValue() + imm.getDecValue()) - return 'jalr {}, {}, MASK_XLEN({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_jal(self, model, rd = None, label = None, dir = None): - rd.setValue(newValue = model.pc.getDecValue() + 4, signed = 1) - model.pc.setValue(label.pcValue) - return 'jal {}, {}{}'.format(rd.getRegName(), label.name, dir) - - - - - ################################################################################################### - # RV 64I - ################################################################################################### - #TODO These may not keep the internal model consistent. You have been warned...sorry lol - - @classmethod - def Instr_ld(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = signExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.WORD), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'ld {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_lwu(self, model, rd = None, rs1 = None, imm = None): - addr = imm.getDecValue() - rd.setBits(newBits = zeroExtend(model.memory.readMemory(addr = addr, granularity = GRANULARITY.BYTE), \ - resultNumBits = model.xlen)) - model.pc += 4 - return 'lwu {}, {}({})'.format(rd.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_addiw(self, model, rd = None, rs1 = None, imm = None): - newValue = rs1.getDecValue() + imm.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'addiw {}, {}, MASK_XLEN({})'.format(rd.getRegName(), rs1.getRegName(), imm.getDecValue()) - - @classmethod - def Instr_slliw(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[-(len(bits) - immShift):] - shiftedExt = binToDec(inputBits = shifted + '0'*(model.xlen - len(shifted))) - rd.setValue(newValue = shiftedExt, signed = 1) - model.pc += 4 - return 'slliw {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_srliw(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[0:len(bits) - immShift] - extShifted = zeroExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'srliw {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_sraiw(self, model, rd = None, rs1 = None, imm = None): - bits = rs1.bits - immBits = imm.bits[-5:] - immShift = int(immBits, 2) - shifted = bits[0:len(bits) - immShift] - extShifted = signExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'sraiw {}, {}, 0b{}'.format(rd.getRegName(), rs1.getRegName(), immBits) - - @classmethod - def Instr_Sd(self, model, rs1 = None, rs2 = None, imm = None): - addr = imm.getDecValue() - model.memory.updateMemory(addr = addr, value = rs2.bits, granularity = GRANULARITY.WORD) - model.pc += 4 - return 'Sd {}, {}({})'.format(rs2.getRegName(), imm.getDecValue(), rs1.getRegName()) - - @classmethod - def Instr_addw(self, model, rd = None, rs1 = None, rs2 = None): - newValue = rs1.getDecValue() + rs2.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'addw {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_subw(self, model, rd = None, rs1 = None, rs2 = None): - newValue = rs1.getDecValue() - rs2.getDecValue() - newValueBin = 0 - if newValue > 0: - newValueBin = bin(newValue)[2:] - elif newValue == 0: - newValueBin = "0" * model.xlen - else: - newValueBin = bin(newValue)[3:] - newValueBinTrunk = newValueBin[-model.xlen:] - rd.setBits(newBits = signExtend(inputBits = newValueBinTrunk, resultNumBits = model.xlen), signed = 1) - model.pc += 4 - return 'subw {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_sllw(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[-(len(bits) - rs2Shift):] - shiftedExt = binToDec(inputBits = shifted + '0'*(model.xlen - len(shifted))) - rd.setValue(newValue = shiftedExt, signed = 1) - model.pc += 4 - return 'sllw {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_srlw(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[0:len(bits) - rs2Shift] - extShifted = zeroExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'srlw {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - @classmethod - def Instr_sraw(self, model, rd = None, rs1 = None, rs2 = None): - bits = rs1.bits - rs2Bin = rs2.bits[-5:] - rs2Shift = int(rs2Bin,2) - shifted = bits[0:len(bits) - rs2Shift] - extShifted = signExtend(inputBits = shifted, resultNumBits = model.xlen) - rd.setBits(newBits = extShifted, signed = 1) - model.pc += 4 - return 'sraw {}, {}, {}'.format(rd.getRegName(), rs1.getRegName(), rs2.getRegName()) - - -################################################################################################### -# Global Constants -################################################################################################### -GRANULARITY = Enum('granularity', ['WORD', 'HALFWORD', 'BYTE']) -# 'jalr', -INSTRSETS = {'RV32I': ['lb', 'lh', 'lw', 'lbu', 'lhu', 'addi', 'slli', 'slti', 'sltiu', 'xori', \ - 'srli', 'srai', 'ori', 'andi', 'auipc', 'sb', 'sh', 'sw', 'add', 'sub', \ - 'sll', 'slt', 'sltu', 'xor', 'srl', 'sra', 'or', 'and', 'lui', 'beq', \ - 'bne', 'blt', 'bge', 'bltu', 'bgeu', 'jal', 'jalr'], \ - 'RV64I': ['lb', 'lh', 'lw', 'lbu', 'lhu', 'addi', 'slli', 'slti', 'sltiu', 'xori', \ - 'srli', 'srai', 'ori', 'andi', 'auipc', 'sb', 'sh', 'sw', 'add', 'sub', \ - 'sll', 'slt', 'sltu', 'xor', 'srl', 'sra', 'or', 'and', 'lui', 'beq', \ - 'bne', 'blt', 'bge', 'bltu', 'bgeu', 'jalr', 'jal', \ - 'ld', 'lwu', 'addiw', 'slliw', 'srliw', 'sraiw', 'Sd', 'addw', 'subw', \ - 'sllw', 'srlw', 'sraw'] \ - } - - -InstrTypes = { 'R' : ['add', 'sub', 'sll', 'slt', 'sltu', 'xor', 'srl', 'sra', 'or', 'and', \ - 'addw', 'subw', 'sllw', 'srlw', 'sraw'], \ - 'I' : ['lb', 'lh', 'lw', 'lbu', 'lhu', 'addi', 'slli', 'slti', 'sltiu', 'xori', 'srli', 'srai', 'ori', 'andi', 'jalr', \ - 'ld', 'lwu', 'addiw', 'slliw', 'srliw', 'sraiw'], \ - 'S' : ['sw', 'sh', 'sb', 'Sd'], \ - 'B' : ['beq', 'bne', 'blt', 'bge', 'bltu', 'bgeu'], \ - 'U' : ['lui', 'auipc'], \ - 'J' : ['jal'], \ - 'R4': []} -################################################################################################### -# Main Body -################################################################################################### - -XLEN = ['32', '64'] -INSTRUCTION_TYPE = ['I'] -NUMINSTR = [100000, 1000000] -IMPERASPATH = "../../imperas-riscv-tests/riscv-test-suite/" - -seed(42) -np.random.seed(42) -for num_instructions in NUMINSTR: - for xlen in XLEN: - memInit = {} - for i in range(0, 400, 4): - val = randBinary(signed = 0, numBits = int(xlen), valueAlignment = 1) - memInit[i] = val - for instrType in INSTRUCTION_TYPE: - instrSet = 'RV' + xlen + instrType - - print('Generating {} Assembly Instructions for {}'.format(num_instructions, instrSet)) - - dut = TestGen(numInstr=num_instructions, immutableRegsDict = {0 : 0, 6 : 0, 7 : 0}, instrSet=instrSet, imperasPath=IMPERASPATH) - # regFile = - dut.model.memory.populateMemory(memDict = memInit) - dut.exportASM(instrSet = instrSet, instrTypes = instrType) \ No newline at end of file diff --git a/studies/testgen/testgen-SLL-SRL-SRA.py b/studies/testgen/testgen-SLL-SRL-SRA.py deleted file mode 100755 index ede82af48..000000000 --- a/studies/testgen/testgen-SLL-SRL-SRA.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-SLL-SRL-SRA.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def twoscomp(a): - amsb = a >> (xlen-1) - alsbs = ((1 << (xlen-1)) - 1) & a - if (amsb): - asigned = a - (1<> b - elif (test == "SRA"): - return asigned >> b - else: - die("bad test name ", test) - # exit(1) - -def randRegs(): - reg1 = randint(1,31) - reg2 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2): - return randRegs() - else: - return reg1, reg2, reg3 - -def writeVector(a, b, storecmd, xlen): - global testnum - expected = computeExpected(a, b, test, xlen) - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - reg1, reg2, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), rs2:x" + str(reg2) + "(" +formatstr.format(b) - lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + "li x" + str(reg2) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", x" + str(reg2) + "\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg3) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["SLL", "SRL", "SRA"] -author = "David_Harris@hmc.edu" -xlens = [32, 64] -numrand = 48 - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - for test in tests: - corners = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - if (xlen == 32): - shamt = [0, 1, 2, 3, 4, 8, 15, 16, 29, 30, 31] - else: - shamt = [0, 1, 3, 8, 15, 16, 29, 31, 32, 47, 48, 62, 63] - - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners: - for b in shamt: - writeVector(a, b, storecmd, xlen) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(xlen) - writeVector(a, b, storecmd, xlen) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - - diff --git a/studies/testgen/testgen-SLLI-SRLI-SRAI.py b/studies/testgen/testgen-SLLI-SRLI-SRAI.py deleted file mode 100644 index cc01f1eb8..000000000 --- a/studies/testgen/testgen-SLLI-SRLI-SRAI.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADD-SUB.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def computeExpected(a, b, test): - if (test == "SLLI"): - return a << b - elif (test == "SRLI"): - return srli(a,b) - elif (test == "SRAI"): - return a >> b - else: - die("bad test name ", test) - # exit(1) - -def signExt(b, bits): - a_str = bin(b)[2::] - if (a_str[0] == "b"): - a_str = a_str[1:] - - if (len(a_str) < 12): - zeroPadding = "0" * (bits - len(a_str)) - a_str = zeroPadding + a_str - - print( "{:x}, {:s} ".format(b, a_str)) - padding = a_str[len(a_str)-1] * (bits - len(a_str)) - return int(padding + a_str, 2) - - -def evaluateTwoComplement(b, bits): - if (b & (1 << (bits -1))!= 0): - b = b - (1 << bits) - return b - - -def srli(a,b): - if (a < 0): - a = 2**xlen + a - if (b==0): - return a - a_str = bin(a)[2:] - if a_str[0]== "b": - a_str = a_str[1:] - # print(a_str) - numZeroPad = (len(a_str)-abs(b)) - out = a_str[:numZeroPad] - if (numZeroPad <= 0): - return 0 - print("a: {:b}, b: {:d}, out:{:b}".format(a, b, int(out,2))) - return int(out,2) - -def randRegs(): - reg1 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg3 == 6): - return randRegs() - else: - return reg1, reg3 - -def writeVector(a, b, storecmd): - global testnum - - - - - expected = computeExpected(evaluateTwoComplement(a, xlen), b, test) -# print( "original {:x}, sign Extended {:x} ".format(b, signExt(b,xlen))) -# print (str(a) + "<" + str(signExt(b,xlen)) + " : " + str(expected)) - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - - - - reg1, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), imm5:" + "(" +formatstrimm5.format(b) - lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", " + formatstrimm5.format(b) + "\n" - # lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["SLLI", "SRLI", "SRAI"] -author = "Shriya Nadgauda & Ethan Falicov" -xlens = [32, 64] -numrand = 100 - - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - - formatstrimm5 = "0b{:05b}" # format as 5-bit binary number - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for test in tests: - corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - - immBitSize = 5 - corners2 = [0, 1, 2, 0x07, 0x14 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1, - 2**(immBitSize-1), 2**(immBitSize-1)+1, 0x06 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1] - - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners1: - for b in corners2: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(5) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - diff --git a/studies/testgen/testgen-SLTIU.py b/studies/testgen/testgen-SLTIU.py deleted file mode 100644 index 8642a7aec..000000000 --- a/studies/testgen/testgen-SLTIU.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-ADD-SUB.py -# -# David_Harris@hmc.edu 19 January 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint -from random import seed -from random import getrandbits - -################################## -# functions -################################## - -def computeExpected(a, b, test): - if (test == "SLTIU"): - return a < b - else: - die("bad test name ", test) - # exit(1) - -def signExt(b, bits): - a_str = bin(b)[2::] - if (a_str[0] == "b"): - a_str = a_str[1:] - - if (len(a_str) < 12): - zeroPadding = "0" * (12 - len(a_str)) - a_str = zeroPadding + a_str - - - padding = a_str[0] * (bits - len(a_str)) - print( "b {:x}, sign extended {:s} ".format(b, padding + a_str)) - return int(padding + a_str, 2) - - - -def evaluateTwoComplement(b, bits): - if (b & (1 << (bits -1))!= 0): - b = b - (1 << bits) - return b - - -def randRegs(): - reg1 = randint(1,31) - reg3 = randint(1,31) - if (reg1 == 6 or reg3 == 6): - return randRegs() - else: - return reg1, reg3 - -def writeVector(a, b, storecmd): - global testnum - - - - signExtImm = signExt(b,xlen) - if signExtImm < 0: - signExtImm = signExtImm + 2 ** xlen - expected = computeExpected(a, signExtImm, test) - # s - - expected = expected % 2**xlen # drop carry if necessary - if (expected < 0): # take twos complement - expected = 2**xlen + expected - - - - reg1, reg3 = randRegs() - lines = "\n# Testcase " + str(testnum) + ": rs1:x" + str(reg1) + "(" + formatstr.format(a) - lines = lines + "), imm12:" + "(" +formatstrimm12.format(b) - lines = lines + "), result rd:x" + str(reg3) + "(" + formatstr.format(expected) +")\n" - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(a) + ")\n" - lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", SEXT_IMM(" + formatstrimm12.format(b) + ")\n" - # lines = lines + test + " x" + str(reg3) + ", x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(b) + ")\n" - lines = lines + storecmd + " x" + str(reg3) + ", " + str(wordsize*testnum) + "(x6)\n" - lines = lines + "RVTEST_IO_ASSERT_GPR_EQ(x7, " +"x" + str(reg3) +", "+formatstr.format(expected)+")\n" - f.write(lines) - if (xlen == 32): - line = formatrefstr.format(expected)+"\n" - else: - line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n" - r.write(line) - testnum = testnum+1 - -################################## -# main body -################################## - -# change these to suite your tests -tests = ["SLTIU"] -author = "Shriya Nadgauda & Ethan Falicov" -xlens = [32, 64] -numrand = 100 - - -# setup -seed(0) # make tests reproducible - -# generate files for each test -for xlen in xlens: - formatstrlen = str(int(xlen/4)) - formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number - formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x - - formatstrimm12 = "0x{:03x}" # format as 3-bit hexadecimal number - if (xlen == 32): - storecmd = "sw" - wordsize = 4 - else: - storecmd = "sd" - wordsize = 8 - - for test in tests: - corners1 = [0, 1, 2, 0xFF, 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, - 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1] - - immBitSize = 12 - corners2 = [0, 1, 2, 0xFF, 0x624 % 2**immBitSize, 2**(immBitSize-1)-2, 2**(immBitSize-1)-1, - 2**(immBitSize-1), 2**(immBitSize-1)+1, 0xC36 % 2**immBitSize, 2**(immBitSize)-2, 2**(immBitSize)-1] - - imperaspath = "../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "i/" - basename = "WALLY-" + test - fname = imperaspath + "src/" + basename + ".S" - refname = imperaspath + "references/" + basename + ".reference_output" - testnum = 0 - - # print custom header part - f = open(fname, "w") - r = open(refname, "w") - line = "///////////////////////////////////////////\n" - f.write(line) - lines="// "+fname+ "\n// " + author + "\n" - f.write(lines) - line ="// Created " + str(datetime.now()) - f.write(line) - - # insert generic header - h = open("testgen_header.S", "r") - for line in h: - f.write(line) - - # print directed and random test vectors - for a in corners1: - for b in corners2: - writeVector(a, b, storecmd) - for i in range(0,numrand): - a = getrandbits(xlen) - b = getrandbits(12) - writeVector(a, b, storecmd) - - - # print footer - h = open("testgen_footer.S", "r") - for line in h: - f.write(line) - - # Finish - lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" - lines = lines + "\nRV_COMPLIANCE_DATA_END\n" - f.write(lines) - f.close() - r.close() - - - diff --git a/studies/testgen/testgen-STORE.py b/studies/testgen/testgen-STORE.py deleted file mode 100755 index 4f3944c70..000000000 --- a/studies/testgen/testgen-STORE.py +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-STORE.py -# -# Jessica Torrey 03 February 2021 -# Thomas Fleming 03 February 2021 -# -# Generate directed and random test vectors for RISC-V Design Validation. -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint, seed, getrandbits -from textwrap import dedent - -################################## -# global structures -################################## -size_to_store = {8: "sd", 4: "sw", 2: "sh", 1: "sb"} -size_to_load = {8: "ld", 4: "lw", 2: "lh", 1: "lb"} -store_to_size = {"sd": 8, "sw": 4, "sh": 2, "sb": 1} -testcase_num = 0 -signature_len = 2000 -signature = [0xff for _ in range(signature_len)] - -################################## -# functions -################################## - -def rand_reg(): - """ - Produce a random register from 1 to 31 (skipping 6, since r6 is used for - other things). - """ - r = randint(1,30) - if r >= 6: - r += 1 - return r - -def rand_regs(): - """ - Generate two random, unequal register numbers (skipping x6). - """ - rs1 = rand_reg() - rs2 = rand_reg() - while rs1 == rs2: - rs2 = rand_reg() - - return rs1, rs2 - -def generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta): - """ - Create assembly code for a given STORE test case, returned as a string. - - Generates an `xlen`-bit test case for `instruction` (one of sb, sh, sw, or - sd) that loads `value` into `value_register`, then attempts to store that - value in memory at address (x6 + `base_delta`). The test case - assumes the current base address for the signature is in register x6. - - The form of the STORE instruction is as follows: - - `instruction` `value_register` `offset`(`addr_register`) - """ - global testcase_num - - hex_value = f"{value:0{xlen // 4}x}" - - data = f"""# Testcase {testcase_num}: source: x{value_register} (value 0x{hex_value}), destination: {offset}(x{addr_register}) ({base_delta} bytes into signature) - addi x{addr_register}, x6, {base_delta} - li x{value_register}, MASK_XLEN({-offset}) - add x{addr_register}, x{addr_register}, x{value_register} - li x{value_register}, 0x{hex_value} - {instruction} x{value_register}, {offset}(x{addr_register}) - """ - - update_signature(store_to_size[instruction], value, base_delta) - - testcase_num += 1 - return data - -def validate_memory(scratch_register, value_register, value, base_delta, length): - """ - Create assembly code to verify that `length` bytes at mem[x6 + `base_delta`] - store `value`. - - Assumes x6 stores the current base address for the signature. - """ - truncated_value = value & (2**(length * 8) - 1) - hex_value = f"{truncated_value:0{length * 2}x}" - - load = size_to_load[length] - data = f"""addi x{scratch_register}, x6, {base_delta} - {load} x{value_register}, 0(x{scratch_register}) - RVTEST_IO_ASSERT_GPR_EQ(x{scratch_register}, x{value_register}, 0x{hex_value}) - - """ - return data - -def update_signature(length, value, base_delta): - """ - Write the lower `length` bytes of `value` to the little-endian signature - array, starting at byte `base_delta`. - """ - truncated_value = value & (2**(length * 8) - 1) - value_bytes = truncated_value.to_bytes(length, 'little') - #print("n: {}, value: {:x}, trunc: {:x}, length: {}, bd: {:x}".format(testcase_num, value, truncated_value, length, base_delta)) - for i in range(length): - signature[base_delta + i] = value_bytes[i] - -def write_signature(outfile): - """ - Writes successive 32-bit words from the signature array into a given file. - """ - for i in range(0, signature_len, 4): - word = list(reversed(signature[i:i+4])) - hexword = bytearray(word).hex() - outfile.write(f"{hexword}\n") - -def write_header(outfile): - """ - Write the name of the test file, authors, and creation date. - """ - outfile.write(dedent(f"""\ - /////////////////////////////////////////// - // - // WALLY-STORE - // - // Author: {author} - // - // Created {str(datetime.now())} - """)) - outfile.write(open("testgen_header.S", "r").read()) - -def write_footer(outfile): - """ - Write necessary closing code, including a data section for the signature. - """ - outfile.write(open("testgen_footer.S", 'r').read()) - data_section = dedent(f"""\ - \t.fill {signature_len}, 1, -1 - RV_COMPLIANCE_DATA_END - """) - outfile.write(data_section) - -################################## -# test cases -################################## - -def write_basic_tests(outfile, xlen, instr_len, num, base_delta): - """ - Test basic functionality of STORE, using random registers, offsets, and - values. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory at consecutive locations, starting `base_delta` bytes from - the start of the signature. - - Returns the number of bytes from the start of the signature where testing - ended. - """ - instruction = size_to_store[instr_len] - for i in range(num): - value_register, addr_register = rand_regs() - offset = randint(-2**(12 - 1), 2**(12 - 1) - 1) - value = randint(0, 2**(instr_len * 8) - 1) - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - outfile.write(test) - outfile.write(validate) - base_delta += instr_len - return base_delta - -def write_random_store_tests(outfile, xlen, instr_len, num, min_base_delta): - """ - Test random access of STORE, using random registers, offsets, values, and - memory locations. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory at random locations between `min_base_delta` bytes past - the start of the signature to the end of the signature. - """ - instruction = size_to_store[instr_len] - for i in range(num): - base_delta = randint(min_base_delta, signature_len - 1) - base_delta -= (base_delta % instr_len) - value_register, addr_register = rand_regs() - offset = randint(-2**(12 - 1), 2**(12 - 1) - 1) - value = randint(0, 2**(instr_len * 8) - 1) - - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - outfile.write(test) - outfile.write(validate) - -def write_repeated_store_tests(outfile, xlen, instr_len, num, base_delta): - """ - Test repeated access of STORE, using random registers, offsets, values, and a - single memory location. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory `base_delta` bytes past the start of the signature. - """ - instruction = size_to_store[instr_len] - for i in range(num): - value_register, addr_register = rand_regs() - offset = 0 - value = (1 << ((2 * i) % xlen)) - - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - - outfile.write(test) - outfile.write(validate) - -def write_corner_case_tests(outfile, xlen, instr_len, base_delta): - instruction = size_to_store[instr_len] - - corner_cases_32 = [0x0, 0x10000001, 0x01111111] - corner_cases_64 = [0x1000000000000001, 0x0111111111111111] - corner_cases = corner_cases_32 - if xlen == 64: - corner_cases += corner_cases_64 - - for offset in corner_cases: - for value in corner_cases: - value_register, addr_register = rand_regs() - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - - outfile.write(test) - outfile.write(validate) - - base_delta += instr_len - - return base_delta - -################################## -# main body -################################## - -instructions = ["sd", "sw", "sh", "sb"] -author = "Jessica Torrey & Thomas Fleming " -xlens = [32, 64] -numrand = 100 - -# setup -seed(0) # make tests reproducible - -for xlen in xlens: - if (xlen == 32): - wordsize = 4 - else: - wordsize = 8 - - fname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/src/WALLY-STORE.S" - refname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/references/WALLY-STORE.reference_output" - f = open(fname, "w") - r = open(refname, "w") - - write_header(f) - - base_delta = 0 - - for instruction in instructions: - if xlen == 32 and instruction == 'sd': - continue - instr_len = store_to_size[instruction] - base_delta = write_basic_tests(f, xlen, instr_len, 5, base_delta) - write_repeated_store_tests(f, xlen, instr_len, 32, base_delta) - write_random_store_tests(f, xlen, instr_len, 5, base_delta + wordsize) - - write_footer(f) - - write_signature(r) - f.close() - r.close() - - # Reset testcase_num and signature - testcase_num = 0 - signature = [0xff for _ in range(signature_len)] diff --git a/studies/testgen/testgen-VIRTUALMEMORY.py b/studies/testgen/testgen-VIRTUALMEMORY.py deleted file mode 100644 index 310e96b3c..000000000 --- a/studies/testgen/testgen-VIRTUALMEMORY.py +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/env python3 -################################## -# testgen-VIRTUALMEMORY.py -# -# Jessica Torrey 01 March 2021 -# Thomas Fleming 01 March 2021 -# -# Generate an ad-hoc test program for RISC-V Design Validation. Tests the -# functionality of the memory management unit (MMU). -################################## - -################################## -# libraries -################################## -from datetime import datetime -from random import randint, seed, getrandbits -from textwrap import dedent -from virtual_memory_util import * - -################################## -# global structures -################################## - -testcase_num = 0 -signature_len = 2000 -signature = [0xff for _ in range(signature_len)] - -################################## -# functions -################################## - -def rand_reg(): - """ - Produce a random register from 1 to 31 (skipping 6, since r6 is used for - other things). - """ - r = randint(1,30) - if r >= 6: - r += 1 - return r - -def rand_regs(): - """ - Generate two random, unequal register numbers (skipping x6). - """ - rs1 = rand_reg() - rs2 = rand_reg() - while rs1 == rs2: - rs2 = rand_reg() - - return rs1, rs2 - -def initialize_page_directory() - -def generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta): - """ - Create assembly code for a given STORE test case, returned as a string. - - Generates an `xlen`-bit test case for `instruction` (one of sb, sh, sw, or - sd) that loads `value` into `value_register`, then attempts to store that - value in memory at address (x6 + `base_delta`). The test case - assumes the current base address for the signature is in register x6. - - The form of the STORE instruction is as follows: - - `instruction` `value_register` `offset`(`addr_register`) - """ - global testcase_num - - hex_value = f"{value:0{xlen // 4}x}" - - data = f"""# Testcase {testcase_num}: source: x{value_register} (value 0x{hex_value}), destination: {offset}(x{addr_register}) ({base_delta} bytes into signature) - addi x{addr_register}, x6, {base_delta} - li x{value_register}, MASK_XLEN({-offset}) - add x{addr_register}, x{addr_register}, x{value_register} - li x{value_register}, 0x{hex_value} - {instruction} x{value_register}, {offset}(x{addr_register}) - """ - - #update_signature(store_to_size[instruction], value, base_delta) - - testcase_num += 1 - return data - -def validate_memory(scratch_register, value_register, value, base_delta, length): - """ - Create assembly code to verify that `length` bytes at mem[x6 + `base_delta`] - store `value`. - - Assumes x6 stores the current base address for the signature. - """ - truncated_value = value & (2**(length * 8) - 1) - hex_value = f"{truncated_value:0{length * 2}x}" - - load = size_to_load[length] - data = f"""addi x{scratch_register}, x6, {base_delta} - {load} x{value_register}, 0(x{scratch_register}) - RVTEST_IO_ASSERT_GPR_EQ(x{scratch_register}, x{value_register}, 0x{hex_value}) - - """ - return data - -def update_signature(length, value, base_delta): - """ - Write the lower `length` bytes of `value` to the little-endian signature - array, starting at byte `base_delta`. - """ - truncated_value = value & (2**(length * 8) - 1) - value_bytes = truncated_value.to_bytes(length, 'little') - #print("n: {}, value: {:x}, trunc: {:x}, length: {}, bd: {:x}".format(testcase_num, value, truncated_value, length, base_delta)) - for i in range(length): - signature[base_delta + i] = value_bytes[i] - -def write_signature(outfile): - """ - Writes successive 32-bit words from the signature array into a given file. - """ - for i in range(0, signature_len, 4): - word = list(reversed(signature[i:i+4])) - hexword = bytearray(word).hex() - outfile.write(f"{hexword}\n") - -def write_header(outfile): - """ - Write the name of the test file, authors, and creation date. - """ - outfile.write(dedent(f"""\ - /////////////////////////////////////////// - // - // WALLY-STORE - // - // Author: {author} - // - // Created {str(datetime.now())} - """)) - outfile.write(open("testgen_header.S", "r").read()) - -def write_footer(outfile): - """ - Write necessary closing code, including a data section for the signature. - """ - outfile.write(open("testgen_footer.S", 'r').read()) - data_section = dedent(f"""\ - \t.fill {signature_len}, 1, -1 - RV_COMPLIANCE_DATA_END - """) - outfile.write(data_section) - -################################## -# test cases -################################## - -def write_basic_tests(outfile, xlen, instr_len, num, base_delta): - """ - Test basic functionality of STORE, using random registers, offsets, and - values. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory at consecutive locations, starting `base_delta` bytes from - the start of the signature. - - Returns the number of bytes from the start of the signature where testing - ended. - """ - instruction = size_to_store[instr_len] - for i in range(num): - value_register, addr_register = rand_regs() - offset = randint(-2**(12 - 1), 2**(12 - 1) - 1) - value = randint(0, 2**(instr_len * 8) - 1) - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - outfile.write(test) - outfile.write(validate) - base_delta += instr_len - return base_delta - -def write_random_store_tests(outfile, xlen, instr_len, num, min_base_delta): - """ - Test random access of STORE, using random registers, offsets, values, and - memory locations. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory at random locations between `min_base_delta` bytes past - the start of the signature to the end of the signature. - """ - instruction = size_to_store[instr_len] - for i in range(num): - base_delta = randint(min_base_delta, signature_len - 1) - base_delta -= (base_delta % instr_len) - value_register, addr_register = rand_regs() - offset = randint(-2**(12 - 1), 2**(12 - 1) - 1) - value = randint(0, 2**(instr_len * 8) - 1) - - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - outfile.write(test) - outfile.write(validate) - -def write_repeated_store_tests(outfile, xlen, instr_len, num, base_delta): - """ - Test repeated access of STORE, using random registers, offsets, values, and a - single memory location. - - Creates `num` tests for a single store instruction of length `instr_len`, - writing to memory `base_delta` bytes past the start of the signature. - """ - instruction = size_to_store[instr_len] - for i in range(num): - value_register, addr_register = rand_regs() - offset = 0 - value = (1 << ((2 * i) % xlen)) - - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - - outfile.write(test) - outfile.write(validate) - -def write_corner_case_tests(outfile, xlen, instr_len, base_delta): - instruction = size_to_store[instr_len] - - corner_cases_32 = [0x0, 0x10000001, 0x01111111] - corner_cases_64 = [0x1000000000000001, 0x0111111111111111] - corner_cases = corner_cases_32 - if xlen == 64: - corner_cases += corner_cases_64 - - for offset in corner_cases: - for value in corner_cases: - value_register, addr_register = rand_regs() - test = generate_case(xlen, instruction, value_register, value, addr_register, offset, base_delta) - validate = validate_memory(addr_register, value_register, value, base_delta, instr_len) - - outfile.write(test) - outfile.write(validate) - - base_delta += instr_len - - return base_delta - -################################## -# main body -################################## - -if __name__ == "__main__": - instructions = ["sd", "sw", "sh", "sb"] - author = "Jessica Torrey & Thomas Fleming " - xlens = [32, 64] - numrand = 100 - - # setup - seed(0) # make tests reproducible - - for xlen in xlens: - if (xlen == 32): - wordsize = 4 - else: - wordsize = 8 - - fname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/src/WALLY-VIRTUALMEMORY.S" - refname = f"../../imperas-riscv-tests/riscv-test-suite/rv{xlen}i/references/WALLY-VIRTUALMEMORY.reference_output" - f = open(fname, "w") - r = open(refname, "w") - - write_header(f) - - base_delta = 0 - - for instruction in instructions: - if xlen == 32 and instruction == 'sd': - continue - instr_len = store_to_size[instruction] - base_delta = write_basic_tests(f, xlen, instr_len, 5, base_delta) - write_repeated_store_tests(f, xlen, instr_len, 32, base_delta) - write_random_store_tests(f, xlen, instr_len, 5, base_delta + wordsize) - - write_footer(f) - - write_signature(r) - f.close() - r.close() - - # Reset testcase_num and signature - testcase_num = 0 - signature = [0xff for _ in range(signature_len)] \ No newline at end of file From bcbc2f2eed5e5db6e012135139cb83fbfe789bef Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Tue, 1 Oct 2024 12:18:54 -0700 Subject: [PATCH 4/7] Remove fpga/sim --- fpga/sim/bufgce.sv | 11 ----------- fpga/sim/bufgce_div.sv | 32 -------------------------------- fpga/sim/bufgmux.sv | 4 ---- 3 files changed, 47 deletions(-) delete mode 100644 fpga/sim/bufgce.sv delete mode 100644 fpga/sim/bufgce_div.sv delete mode 100644 fpga/sim/bufgmux.sv diff --git a/fpga/sim/bufgce.sv b/fpga/sim/bufgce.sv deleted file mode 100644 index becf25eba..000000000 --- a/fpga/sim/bufgce.sv +++ /dev/null @@ -1,11 +0,0 @@ -module BUFGCE (input logic I, input logic CE, output logic O); - - logic CE_Q; - always_latch begin - if(~I) begin - CE_Q <= CE; - end - end - assign O = CE_Q & I; - -endmodule diff --git a/fpga/sim/bufgce_div.sv b/fpga/sim/bufgce_div.sv deleted file mode 100644 index da2aa059c..000000000 --- a/fpga/sim/bufgce_div.sv +++ /dev/null @@ -1,32 +0,0 @@ -module BUFGCE_DIV #(parameter string DivideAmt = "1") - (input logic I, input logic CLR, input logic CE, output logic O); - - integer PulseCount = 0; - logic Q; - - always_ff @(posedge I, posedge CLR) begin - if(CLR) PulseCount <= 0; - else begin - if(PulseCount < (DivideAmt.atoi()/2 - 1)) - PulseCount <= PulseCount + 1; - else - PulseCount <= 0; - end - end - - assign zero = PulseCount == 0; - - - flopenr #(1) ToggleFlipFLop - (.d(~Q), - .q(Q), - .clk(I), - .reset(CLR), // reset when told by outside - .en(zero)); // only update when counter overflows - - if (DivideAmt != "1") - assign O = Q; - else - assign O = I; - -endmodule diff --git a/fpga/sim/bufgmux.sv b/fpga/sim/bufgmux.sv deleted file mode 100644 index 047a6e529..000000000 --- a/fpga/sim/bufgmux.sv +++ /dev/null @@ -1,4 +0,0 @@ -module BUFGMUX(input logic I1, input logic I0, input logic S, output logic O); - - assign O = S ? I1 : I0; -endmodule From 6d21e272d0b1ddb52286d3f958e35ef032c561d2 Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Tue, 1 Oct 2024 12:19:12 -0700 Subject: [PATCH 5/7] Remove fpga bootrom.txt --- fpga/generator/bootrom.txt | 42 -------------------------------------- 1 file changed, 42 deletions(-) delete mode 100644 fpga/generator/bootrom.txt diff --git a/fpga/generator/bootrom.txt b/fpga/generator/bootrom.txt deleted file mode 100644 index b49f25c09..000000000 --- a/fpga/generator/bootrom.txt +++ /dev/null @@ -1,42 +0,0 @@ -94e1819300002197 -4281420141014081 -4481440143814301 -4681460145814501 -4881480147814701 -4a814a0149814901 -4c814c014b814b01 -4e814e014d814d01 -0110011b4f814f01 -059b45011161016e -0004063705fe0010 -05a000ef8006061b -0ff003930000100f -4e952e3110060e37 -c602829b0053f2b7 -2023fe02dfe312fd -829b0053f2b7007e -fe02dfe312fdc602 -4de31efd000e2023 -059bf1402573fdd0 -0000061705e20870 -0010029b01260613 -11010002806702fe -84b2842ae426e822 -892ee04aec064505 -06e000ef07e000ef -979334fd02905563 -07930177d4930204 -4089093394be2004 -04138522008905b3 -19e3014000ef2004 -64a2644260e2fe94 -6749808261056902 -dfed8b8510472783 -2423479110a73823 -10472783674910f7 -20058693ffed8b89 -05a1118737836749 -fed59be3fef5bc23 -1047278367498082 -67c98082dfed8b85 -0000808210a7a023 From 9363379b55e27a5a19ffe7ed02b009a7abdf29aa Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Tue, 1 Oct 2024 12:44:47 -0700 Subject: [PATCH 6/7] Combine floating point test documentation --- sim/FPbuild.txt | 56 --------------------------------------- tests/fp/README.md | 65 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 73 deletions(-) delete mode 100644 sim/FPbuild.txt diff --git a/sim/FPbuild.txt b/sim/FPbuild.txt deleted file mode 100644 index 99f414804..000000000 --- a/sim/FPbuild.txt +++ /dev/null @@ -1,56 +0,0 @@ -Procedure for Runnning SoftFloat/TestFloat with Wally - -1.) First, compile SoftFloat and TestFloat by going to the addins -directory and finding the specific build directory (e.g., -Linux_x86_64-GCC. Currently, we are using v3e of -SoftFloat/TestFloat. I am not sure of the order, but I always compile -SoftFloat first as I believe TestFloat uses the static library -SoftFloat creates. - -2.) Once compiled both, go to the tests/fp directory and run the -create_vectors.sh Linux script. In the past, we have automated this, -but I believe this has fallen into more of a manual state lately. - -3.) Then, run remove_spaces.sh which will remove spaces from the -output and put underscores between vectors (this helps differentiate -the vectors that are generated). Again, this can be combined with -Step 2. - -4.) TestFloat is run from wally/cvw/sim and sim-testfloat-batch with -its respective test. The format is ./sim-testfloat-add add. All of -the tests are listed below. This can be augmented or added to for -other FP tests given by the great SoftFloat/TestFloat output. - - cvtint - test integer conversion unit (fcvtint) - cvtfp - test floating-point conversion unit (fcvtfp) - cmp - test comparison unit's LT, LE, EQ opperations (fcmp) - add - test addition - fma - test fma - mul - test mult with fma - sub - test subtraction - div - test division - sqrt - test square root - all - test everything - -4a.) Each test will test all its vectors - if you want to test a -subset of the vectors (e.g., only binary16), you should modify the -testfloat.do in the sim directory. Change the TEST_SIZE="all" to the -specific test you want to run. For example, if you want to run only -binary16, you should set this variable to TEST_SIZE="HP". - -4b.) If you want to turn off the generation of wlf files while running -sim-testfloat-batch, you can modify testfloat.do in the sim -directory. Inside this DO file, modify the WAV file to 0 --> i.e., -set "quietly set WAV 0;" - - - - - - - - - - - - diff --git a/tests/fp/README.md b/tests/fp/README.md index ae60d0b5e..440f5eea8 100644 --- a/tests/fp/README.md +++ b/tests/fp/README.md @@ -1,27 +1,58 @@ james.stine@okstate.edu 14 Jan 2022 +jcarlin@hmc.edu Sept 2024 -These are the testvectors (TV) to test the floating-point unit using -Berkeley TestFloat written originally by John Hauser. TestFloat -requires both TestFloat and SoftFloat. +## TestFloat for CVW -The locations of these tools at time of this README is found here: -TestFloat-3e: http://www.jhauser.us/arithmetic/TestFloat.html -SoftFloat-3e: http://www.jhauser.us/arithmetic/SoftFloat.html +The CVW floating point unit is tested using testvectors from the Berkeley TestFloat suite, written originally by John Hauser. -These tools have been compiled on a x86_64 environment by going into -their respective build/Linux-x86_64-GCC directories and running make. +TestFloat and SoftFloat can be found as submodules in the addins directory, and are linked here: +- TestFloat: https://github.com/ucb-bar/berkeley-testfloat-3 +- SoftFloat: https://github.com/ucb-bar/berkeley-softfloat-3 -The makefile in the vectors subdirectory of this directory will generate TV -for each rounding mode and operation. It also puts an underscore between each -vector instead of a space to allow SystemVerilog readmemh to read correctly. +### Compiling SoftFloat/TestFloat and Generating Testvectors -The makefile at the top level of this directory will compile SoftFloat and -TestFloat and then generate all of the TVs. It also generates TVs for the -combined integer floating-point divider. +The entire testvector generation process can be performed by running make in this directory. -Although not needed, a case.sh script is included to change the case -of the hex output. This is for those that do not like to see -hexadecimal capitalized :P. +```bash +make --jobs +``` + +This compiles SoftFloat for an x86_64 environment in its build/Linux-x86_64-GCC directory using the `SPECIALIZE_TYPE=RISCV` flag to get RISC-V behavior. TestFloat is then compiled in its build/Linux-x86_64-GCC directory using this SoftFloat library. + +The Makefile in the vectors subdirectory of this directory is then called to generate testvectors for each rounding mode and operation. It also puts an underscore between each vector instead of a space to allow SystemVerilog `$readmemh` to read correctly. + +Testvectors for the combined integer floating-point divider are also generated. + +Although not needed, a `case.sh` script is included to change the case of the hex output. This is for those that do not like to see hexadecimal capitalized :P. + +### Running TestFloat Vectors on Wally + +TestFloat is run using the standard Wally simulation commands. + +To run all TestFloat tests on many different derived configurations of Wally, use +```bash +regression-wally --testfloat +``` + +To run a single test, use +```bash +wsim --tb testbench_fp +``` +The choices for `` are as follows: + +>cvtint - test integer conversion unit (fcvtint) +cvtfp - test floating-point conversion unit (fcvtfp) +cmp - test comparison unit's LT, LE, EQ opperations (fcmp) +add - test addition +fma - test fma +mul - test mult with fma +sub - test subtraction +div - test division +sqrt - test square root + +Any config that includes floating point support can be used. Each test will test all its vectors for all precisions supported by the given config. + +### Testvector Count 46464 185856 836352 f16_add_rd.tv 46464 185856 836352 f16_add_rne.tv From 29801485de01ca3b8941c8d397588e2e51f33970 Mon Sep 17 00:00:00 2001 From: Jordan Carlin Date: Tue, 1 Oct 2024 12:48:10 -0700 Subject: [PATCH 7/7] Add Xcelium readme --- sim/xcelium/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 sim/xcelium/README.md diff --git a/sim/xcelium/README.md b/sim/xcelium/README.md new file mode 100644 index 000000000..094a939e3 --- /dev/null +++ b/sim/xcelium/README.md @@ -0,0 +1,3 @@ +## Xcelium Simulation with CVW + +NOTE: Xcelium is not regularly tested and may not work correctly. It is also not integrated with the `wsim` command used for CVW, so the config and testsuite must be manually modified in `wally.xrun` and it does not support all of the other options provided by `wsim `.