mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge conflict fixing
This commit is contained in:
		
						commit
						f778f464b7
					
				@ -146,6 +146,13 @@ string tests64iNOc[] = {
 | 
			
		||||
                     "rv64i/WALLY-SLLI", "3000",
 | 
			
		||||
                     "rv64i/WALLY-SRLI", "3000",
 | 
			
		||||
                     "rv64i/WALLY-SRAI", "3000"
 | 
			
		||||
                     "rv64i/WALLY-LOAD", "11bf0",
 | 
			
		||||
                     "rv64i/WALLY-JAL", "4000",
 | 
			
		||||
                     "rv64i/WALLY-STORE", "3000",
 | 
			
		||||
                     "rv64i/WALLY-ADDIW", "3000",
 | 
			
		||||
                     "rv64i/WALLY-SLLIW", "3000",
 | 
			
		||||
                     "rv64i/WALLY-SRLIW", "3000",
 | 
			
		||||
                     "rv64i/WALLY-SRAIW", "3000"
 | 
			
		||||
  };
 | 
			
		||||
string tests32ic[] = '{
 | 
			
		||||
//                     "rv32ic/WALLY-C-ADHOC-01", "2000",
 | 
			
		||||
@ -226,6 +233,7 @@ string tests32i[] = {
 | 
			
		||||
                     "rv32i/I-XOR-01","2000",
 | 
			
		||||
                     "rv32i/I-XORI-01","2000",
 | 
			
		||||
                     "rv32i/WALLY-ADD", "3000",
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
                     "rv32i/WALLY-SUB", "3000",
 | 
			
		||||
                     "rv32i/WALLY-ADDI", "2000",
 | 
			
		||||
                     "rv32i/WALLY-ANDI", "2000",
 | 
			
		||||
@ -236,6 +244,12 @@ string tests32i[] = {
 | 
			
		||||
                     "rv32i/WALLY-SLLI", "2000",
 | 
			
		||||
                     "rv32i/WALLY-SRLI", "2000",
 | 
			
		||||
                     "rv32i/WALLY-SRAI", "2000"
 | 
			
		||||
=======
 | 
			
		||||
                     "rv32i/WALLY-LOAD", "11c00",
 | 
			
		||||
                     "rv32i/WALLY-SUB", "3000",
 | 
			
		||||
                     "rv32i/WALLY-STORE", "2000",
 | 
			
		||||
                     "rv32i/WALLY-JAL", "3000"
 | 
			
		||||
>>>>>>> 88ccaff534d6bc14ccf767006b2d25505d0ce674
 | 
			
		||||
};
 | 
			
		||||
  string tests[];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										182
									
								
								wally-pipelined/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										182
									
								
								wally-pipelined/testgen/testgen-ADDIW-SLLIW-SRLIW-SRAIW.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,182 @@
 | 
			
		||||
#!/usr/bin/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()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										260
									
								
								wally-pipelined/testgen/testgen-JAL.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										260
									
								
								wally-pipelined/testgen/testgen-JAL.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,260 @@
 | 
			
		||||
#!/usr/bin/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
 | 
			
		||||
 | 
			
		||||
##################################
 | 
			
		||||
# 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)
 | 
			
		||||
  rs = choice(UnusedRegs)
 | 
			
		||||
  UnusedRegs.remove(rd)
 | 
			
		||||
  OtherRegs = deepcopy(AllRegs)
 | 
			
		||||
  OtherRegs.remove(StoreAdrReg)
 | 
			
		||||
  OtherRegs.remove(rd)
 | 
			
		||||
  try:
 | 
			
		||||
    OtherRegs.remove(0)
 | 
			
		||||
  except:
 | 
			
		||||
    pass
 | 
			
		||||
  try:
 | 
			
		||||
    OtherRegs.remove(rs)
 | 
			
		||||
  except:
 | 
			
		||||
    pass
 | 
			
		||||
  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):
 | 
			
		||||
    CurrAdr += 8 if (xlen == 32) else 20
 | 
			
		||||
  elif ("la x" in line):
 | 
			
		||||
    CurrAdr += 8
 | 
			
		||||
  else:
 | 
			
		||||
    CurrAdr += 4
 | 
			
		||||
 | 
			
		||||
def writeForwardsJumpVector(spacers):
 | 
			
		||||
  global TestNum
 | 
			
		||||
  rd, rs, DataReg, OtherRd = registerSelect()
 | 
			
		||||
  if (xlen==64):
 | 
			
		||||
    expected = int("fedbca9876540000",16)
 | 
			
		||||
    unexpected = int("ffff0000ffff0000",16)
 | 
			
		||||
  else:
 | 
			
		||||
    expected = int("fedbca98",16)
 | 
			
		||||
    unexpected = int("ff00ff00",16)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  f.write("\n")
 | 
			
		||||
  f.write("    # Testcase "+str(TestNum)+"  address cmp result rd:x"+str(rd)+"("+formatstr.format(CurrAdr+44)+")  data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
 | 
			
		||||
  addInst("    li x"+str(DataReg)+", "+formatstr.format(expected)+"\n")
 | 
			
		||||
  addInst("    JAL x"+str(rd)+", 1f\n")
 | 
			
		||||
  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")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
 | 
			
		||||
  writeExpectedToRef(LinkAdr)
 | 
			
		||||
  writeExpectedToRef(expected) 
 | 
			
		||||
  TestNum = TestNum+1
 | 
			
		||||
 | 
			
		||||
def writeBackwardsJumpVector(spacers):
 | 
			
		||||
  global TestNum
 | 
			
		||||
  rd, rs, DataReg,OtherRd = registerSelect()
 | 
			
		||||
  if (xlen==64):
 | 
			
		||||
    expected = int("fedbca9876540000",16)
 | 
			
		||||
    unexpected = int("ffff0000ffff0000",16)
 | 
			
		||||
  else:
 | 
			
		||||
    expected = int("fedbca98",16)
 | 
			
		||||
    unexpected = int("ff00ff00",16)
 | 
			
		||||
 | 
			
		||||
  f.write("\n")
 | 
			
		||||
  f.write("    # Testcase "+str(TestNum)+"  address cmp result rd:x"+str(rd)+"("+formatstr.format(CurrAdr+20+8*spacers)+")  data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
 | 
			
		||||
  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")
 | 
			
		||||
  addInst("    JAL x"+str(rd)+", 1b\n")
 | 
			
		||||
  LinkAdr = CurrAdr if (rd!=0) else 0 # rd's expected value
 | 
			
		||||
  f.write("3:\n")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
 | 
			
		||||
  writeExpectedToRef(LinkAdr)
 | 
			
		||||
  writeExpectedToRef(expected) 
 | 
			
		||||
  TestNum = TestNum+1
 | 
			
		||||
 | 
			
		||||
def writeChainVector(repetitions,spacers):
 | 
			
		||||
  global TestNum
 | 
			
		||||
  rd, rs, DataReg,OtherRd = registerSelect()
 | 
			
		||||
  if (xlen==64):
 | 
			
		||||
    expected = int("fedbca9876540000",16)
 | 
			
		||||
    unexpected = int("ffff0000ffff0000",16)
 | 
			
		||||
  else:
 | 
			
		||||
    expected = int("fedbca98",16)
 | 
			
		||||
    unexpected = int("ff00ff00",16)
 | 
			
		||||
 | 
			
		||||
  f.write("\n")
 | 
			
		||||
  f.write("    # Testcase "+str(TestNum)+"  address cmp result rd:x"+str(rd)+"(ugh; if you really wanted to, you could figure it out)  data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n")
 | 
			
		||||
  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")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(rd)+", "+str(wordsize*(2*TestNum+0))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(rd)+", "+formatstr.format(LinkAdr)+")\n")
 | 
			
		||||
  addInst("    "+storecmd+" x"+str(DataReg)+", "+str(wordsize*(2*TestNum+1))+"(x"+str(StoreAdrReg)+")\n")
 | 
			
		||||
  f.write("    RVTEST_IO_ASSERT_GPR_EQ(x"+str(StoreAdrReg+1)+", x"+str(DataReg)+", "+formatstr.format(expected)+")\n")
 | 
			
		||||
  writeExpectedToRef(LinkAdr)
 | 
			
		||||
  writeExpectedToRef(expected) 
 | 
			
		||||
  TestNum = TestNum+1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def writeExpectedToRef(expected):
 | 
			
		||||
  global TestGroupSizes
 | 
			
		||||
  TestGroupSizes[TestGroup-1] += 1
 | 
			
		||||
  if (xlen == 32):
 | 
			
		||||
    r.write(formatrefstr.format(expected)+"\n")
 | 
			
		||||
  else:
 | 
			
		||||
    r.write(formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32)+"\n")
 | 
			
		||||
 | 
			
		||||
##################################
 | 
			
		||||
# main body
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
# change these to suite your tests
 | 
			
		||||
tests = ["JAL"]
 | 
			
		||||
author = "Ben Bracker (bbracker@hmc.edu)"
 | 
			
		||||
xlens = [32,64]
 | 
			
		||||
numtests = 100;
 | 
			
		||||
 | 
			
		||||
# setup
 | 
			
		||||
seed(0) # make tests reproducible
 | 
			
		||||
 | 
			
		||||
# generate files for each test
 | 
			
		||||
for xlen in xlens:
 | 
			
		||||
  CurrAdr = int("80000108",16)
 | 
			
		||||
  TestNum = 0
 | 
			
		||||
  TestGroup = 1
 | 
			
		||||
  TestGroupSizes = [0]
 | 
			
		||||
  AllRegs = list(range(0,32))
 | 
			
		||||
  UnusedRegs = deepcopy(AllRegs) 
 | 
			
		||||
  StoreAdrReg = 6 # matches what's in header script 
 | 
			
		||||
  UnusedRegs.remove(6)
 | 
			
		||||
 | 
			
		||||
  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:
 | 
			
		||||
    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 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
 | 
			
		||||
    for i in range(0,31):
 | 
			
		||||
      writeForwardsJumpVector(randint(0,4))
 | 
			
		||||
    for i in range(0,31):
 | 
			
		||||
      writeBackwardsJumpVector(randint(0,4))
 | 
			
		||||
    writeForwardsJumpVector(100)
 | 
			
		||||
    writeBackwardsJumpVector(100)
 | 
			
		||||
    writeChainVector(6,True)
 | 
			
		||||
    writeChainVector(16,False)
 | 
			
		||||
 | 
			
		||||
    # 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()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -18,15 +18,56 @@ from random import randint, seed, getrandbits
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
def rand_reg():
 | 
			
		||||
  """Produce a random register (skipping 6, since r6 is used for other things"""
 | 
			
		||||
  r = randint(1,30)
 | 
			
		||||
  """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 string"""
 | 
			
		||||
    """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"
 | 
			
		||||
@ -36,35 +77,89 @@ def generate_case(xlen, instruction, load_register, source_register, source_regi
 | 
			
		||||
        store = "sw"
 | 
			
		||||
    else:
 | 
			
		||||
        raise Exception("Unknown xlen value: %s" % xlen)
 | 
			
		||||
    data = f"""# Testcase {testcase_num}: source {offset}(x{source_register} == {source_register_value}), rresult: x{load_register} == {expected}
 | 
			
		||||
    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}(x6)
 | 
			
		||||
    {store} x{load_register}, {(testcase_num*xlen//8) % 0x800}(x6)
 | 
			
		||||
    RVTEST_IO_ASSERT_GPR_EQ(x8, x{load_register}, {expected})
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    testcase_num += 1
 | 
			
		||||
    return data
 | 
			
		||||
    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: f{author}
 | 
			
		||||
    //
 | 
			
		||||
    // Created {str(datetime.now())}
 | 
			
		||||
    // 
 | 
			
		||||
    ///////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    """)
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
##################################
 | 
			
		||||
 | 
			
		||||
instructions = ["lb", "lbu", "lh", "lhu", "lw", "lwu", "ld"]
 | 
			
		||||
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;
 | 
			
		||||
@ -73,16 +168,60 @@ numrand = 100;
 | 
			
		||||
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.S.reference_output".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, 0xFF, 0xFFFF, 0xFFFFFFFF, 0x7F, 0x7FFF, 0x7FFFFFFF, 0x01]
 | 
			
		||||
    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()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										282
									
								
								wally-pipelined/testgen/testgen-STORE.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										282
									
								
								wally-pipelined/testgen/testgen-STORE.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,282 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
##################################
 | 
			
		||||
# testgen-STORE.py
 | 
			
		||||
#
 | 
			
		||||
# Jessica Torrey <jtorrey@hmc.edu>  03 February 2021
 | 
			
		||||
# Thomas Fleming <tfleming@hmc.edu> 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 <jtorrey@hmc.edu> & Thomas Fleming <tfleming@hmc.edu>"
 | 
			
		||||
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)]
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user