#!/usr/bin/python3 ################################## # covergen.py # # David_Harris@hmc.edu 27 March 2024 # # Generate directed tests for functional coverage ################################## ################################## # libraries ################################## from datetime import datetime from random import randint from random import seed from random import getrandbits ################################## # functions ################################## def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen): rdval = randint(0, 2**xlen-1) lines = "\n# Testcase " + str(desc) + "\n" lines = lines + "li x" + str(rd) + ", MASK_XLEN(" + formatstr.format(rdval) + ") # initialize rd to a random value that should get changed\n" lines = lines + "li x" + str(rs1) + ", MASK_XLEN(" + formatstr.format(rs1val) + ") # initialize rs1 to a random value \n" lines = lines + "li x" + str(rs2) + ", MASK_XLEN(" + formatstr.format(rs2val) + ") # initialize rs2 to a random value\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n" f.write(lines) def make_cp_rd(rd, test, storecmd, xlen): rs1 = randint(0, 31) rs2 = randint(0, 31) rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cp_rd (Test destination rd = x" + str(rd) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cp_rs1(rs1, test, storecmd, xlen): rd = randint(0, 31) rs2 = randint(0, 31) rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cp_rs1 (Test source rs1 = x" + str(rs1) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cp_rs2(rs2, test, storecmd, xlen): rd = randint(0, 31) rs1 = randint(0, 31) rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cp_rs2 (Test source rs2 = x" + str(rs2) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cmp_rd_rs1(r, test, storecmd, xlen): rd = r rs1 = r rs2 = randint(0, 31) rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cmp_rd_rs1 (Test destination rd = source rs1 = x" + str(r) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cmp_rd_rs2(r, test, storecmd, xlen): rd = r rs1 = randint(0, 31) rs2 = r rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cmp_rd_rs2 (Test destination rd = source rs2 = x" + str(r) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cmp_rd_rs1_rs2(r, test, storecmd, xlen): rd = r rs1 = r rs2 = r rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cmp_rd_rs1_rs2 (Test destination rd = source rs1 = source rs2 = x" + str(r) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cp_gpr_hazard(test, storecmd, xlen): rs1val = randint(0, 2**xlen-1) rs2val = randint(0, 2**xlen-1) desc = "cp_gpr_hazard" writeCovVector(desc, 20, 21, 22, rs1val, rs2val, test, storecmd, xlen) lines = test + " x23, x22, x20 # RAW\n" lines = lines + test + " x22, x23, x20 # WAR\n" lines = lines + test + " x22, x21, x20 # WAW\n" f.write(lines) def make_cp_rs1_maxvals(test, storecmd, xlen): for rs1val in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: rd = randint(1, 31) rs1 = randint(0, 31) rs2 = randint(0, 31) rs2val = randint(0, 2**xlen-1) desc = "cp_rs1_maxvals (rs1 = " + str(rs1val) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def make_cp_rs2_maxvals(test, storecmd, xlen): for rs2val in [0, 2**(xlen-1), 2**(xlen-1)-1, 2**xlen-1, 1, 2**(xlen-1)+1]: rd = randint(1, 31) rs1 = randint(0, 31) rs2 = randint(0, 31) rs1val = randint(0, 2**xlen-1) desc = "cp_rs2_maxvals (rs2 = " + str(rs2val) + ")" writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen) def writeCovVector(desc, rs1, rs2, rd, rs1val, rs2val, test, storecmd, xlen): rdval = randint(0, 2**xlen-1) lines = "\n# Testcase " + str(desc) + "\n" lines = lines + "li x" + str(rd) + ", MASK_XLEN(" + formatstr.format(rdval) + ") # initialize rd to a random value that should get changed\n" lines = lines + "li x" + str(rs1) + ", MASK_XLEN(" + formatstr.format(rs1val) + ") # initialize rs1 to a random value \n" lines = lines + "li x" + str(rs2) + ", MASK_XLEN(" + formatstr.format(rs2val) + ") # initialize rs2 to a random value\n" lines = lines + test + " x" + str(rd) + ", x" + str(rs1) + ", x" + str(rs2) + " # perform operation\n" f.write(lines) def write_rtype_arith_vectors(test, storecmd, xlen): for r in range(32): make_cp_rd(r, test, storecmd, xlen) for r in range(32): make_cp_rs1(r, test, storecmd, xlen) for r in range(32): make_cp_rs2(r, test, storecmd, xlen) for r in range(32): make_cmp_rd_rs2(r, test, storecmd, xlen) for r in range(32): make_cmp_rd_rs1(r, test, storecmd, xlen) for r in range(32): make_cmp_rd_rs1_rs2(r, test, storecmd, xlen) make_cp_gpr_hazard(test, storecmd, xlen) make_cp_rs1_maxvals(test, storecmd, xlen) make_cp_rs2_maxvals(test, storecmd, xlen) ################################## # main body ################################## # change these to suite your tests rtests = ["ADD", "SUB", "SLT", "SLTU", "XOR"] tests = rtests author = "David_Harris@hmc.edu" xlens = [64] numrand = 3 # 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] corners = [0, 1, 2**(xlen)-1] pathname = "../wally-riscv-arch-test/riscv-test-suite/rv" + str(xlen) + "i_m/I/" basename = "WALLY-COV-" + test fname = pathname + "src/" + basename + ".S" # print custom header part f = open(fname, "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("covergen_header.S", "r") for line in h: f.write(line) # print directed and random test vectors # Coverage for R-type arithmetic instructions if (test not in rtests): exit("Error: %s not implemented yet" % test) else: write_rtype_arith_vectors(test, storecmd, xlen) # print footer line = "\n.EQU NUMTESTS," + str(1) + "\n\n" f.write(line) h = open("covergen_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()