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