diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index e810eae83..49a5263d6 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -162,6 +162,7 @@ string tests64iNOc[] = { "rv64i/WALLY-SRAI", "3000", "rv64i/WALLY-LOAD", "11bf0", "rv64i/WALLY-JAL", "4000", + "rv64i/WALLY-JALR", "3000", "rv64i/WALLY-STORE", "3000", "rv64i/WALLY-ADDIW", "3000", "rv64i/WALLY-SLLIW", "3000", @@ -288,6 +289,7 @@ string tests32i[] = { "rv32i/WALLY-SUB", "3000", "rv32i/WALLY-STORE", "2000", "rv32i/WALLY-JAL", "3000", + "rv32i/WALLY-JALR", "2000", "rv32i/WALLY-BEQ" ,"4000", "rv32i/WALLY-BNE", "4000 ", "rv32i/WALLY-BLTU", "4000 ", diff --git a/wally-pipelined/testgen/testgen-JAL.py b/wally-pipelined/testgen/testgen-JAL-JALR.py similarity index 53% rename from wally-pipelined/testgen/testgen-JAL.py rename to wally-pipelined/testgen/testgen-JAL-JALR.py index 09f58a566..87c0c423d 100755 --- a/wally-pipelined/testgen/testgen-JAL.py +++ b/wally-pipelined/testgen/testgen-JAL-JALR.py @@ -19,9 +19,8 @@ from random import getrandbits from copy import deepcopy ################################## -# functions +# helper functions ################################## - def InitTestGroup(): global TestGroup,TestGroupSizes,AllRegs,UnusedRegs,StoreAdrReg TestGroup += 1 @@ -44,19 +43,21 @@ def registerSelect(): if len(UnusedRegs)==0: InitTestGroup() rd = choice(UnusedRegs) - rs = 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) - try: + if 0 in OtherRegs: OtherRegs.remove(0) - except: - pass - try: + if rs in OtherRegs: OtherRegs.remove(rs) - except: - pass DataReg = choice(OtherRegs) OtherRegs.remove(DataReg) OtherRd = choice(OtherRegs) @@ -65,52 +66,74 @@ def registerSelect(): def addInst(line): global CurrAdr f.write(line) - if ("li x" in 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 writeForwardsJumpVector(spacers): - global TestNum - rd, rs, DataReg, OtherRd = registerSelect() - if (xlen==64): - expected = int("fedbca9876540000",16) - unexpected = int("ffff0000ffff0000",16) +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: - expected = int("fedbca98",16) - unexpected = int("ff00ff00",16) + 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)+" address cmp result rd:x"+str(rd)+"("+formatstr.format(CurrAdr+44)+") data result rd:x"+str(DataReg)+"("+formatstr.format(expected)+")\n") + f.write(" # Testcase "+str(TestNum)+"\n") + # Test Code addInst(" li x"+str(DataReg)+", "+formatstr.format(expected)+"\n") - addInst(" JAL x"+str(rd)+", 1f\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") - 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 + # Store values to be verified + expectValue(rd, LinkAdr, 2*TestNum+0) + expectValue(DataReg, expected, 2*TestNum+1) -def writeBackwardsJumpVector(spacers): +def writeBackwardsJumpVector(spacers,instr): 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) - + TestNum += 1 + rd, rs, DataReg, OtherRd = registerSelect() + # Header 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") + 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") @@ -118,29 +141,27 @@ def writeBackwardsJumpVector(spacers): 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") + 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") - 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 + # 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() - if (xlen==64): - expected = int("fedbca9876540000",16) - unexpected = int("ffff0000ffff0000",16) - else: - expected = int("fedbca98",16) - unexpected = int("ff00ff00",16) - + # Header 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") + 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") @@ -159,57 +180,56 @@ def writeChainVector(repetitions,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") + # 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 -tests = ["JAL"] +test = 0 +tests = ["JAL","JALR"] author = "Ben Bracker (bbracker@hmc.edu)" xlens = [32,64] -numtests = 100; +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) +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 - 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" @@ -221,7 +241,7 @@ for xlen in xlens: 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("// 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") @@ -235,14 +255,24 @@ for xlen in xlens: 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) + 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") @@ -254,7 +284,3 @@ for xlen in xlens: f.write("\nRV_COMPLIANCE_DATA_END\n") f.close() r.close() - - - -