mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			249 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python3
 | |
| ##################################
 | |
| # testgen-CSR-PERMISSIONS.py
 | |
| #
 | |
| # dottolia@hmc.edu 1 May 2021
 | |
| #
 | |
| # Generate directed and random test vectors for RISC-V Design Validation.
 | |
| # Verify that an illegal instruction is raised when trying to write to csrs of a higher privilege
 | |
| #
 | |
| ##################################
 | |
| # DOCUMENTATION:
 | |
| #
 | |
| # Most of the comments explaining what everything
 | |
| # does and the layout of the privileged tests
 | |
| # can be found in this file
 | |
| #
 | |
| ###################################
 | |
| 
 | |
| ##################################
 | |
| # libraries
 | |
| ##################################
 | |
| from datetime import datetime
 | |
| from random import randint 
 | |
| from random import seed
 | |
| from random import getrandbits
 | |
| 
 | |
| ##################################
 | |
| # functions
 | |
| ##################################
 | |
| 
 | |
| testCount = 2
 | |
| 
 | |
| def writeVectors(storecmd, testMode):
 | |
|   global testnum
 | |
| 
 | |
|   csrs = ["status", "edeleg", "ideleg", "ie", "tvec", "counteren", "scratch", "epc", "cause", "tval", "ip"]
 | |
|   if testMode == "s":
 | |
|     csrs.append("atp")
 | |
|   #csrs = ["status"]
 | |
|   for csrStart in csrs:
 | |
|     for i in range(0, testCount):
 | |
|       a = 1
 | |
| 
 | |
|       csr = testMode + csrStart
 | |
| 
 | |
|       # only check for CSR changes if testing machine-mode registers
 | |
|       csrWillChange = testMode == "s" or csrStart == "status" or csrStart == "epc" or csrStart == "cause" or csrStart == "tval"
 | |
|       newCSRValue = "" if testMode == "s" else "csrr x24, " + csr
 | |
| 
 | |
|       f.write(f"""
 | |
|         li x13, 1
 | |
|       """)
 | |
| 
 | |
|       fromModeOptions = ["s", "u"] if testMode == "m" else ["u"]
 | |
|       for fromMode in fromModeOptions:
 | |
|         label = f"""{fromMode}_{csr}_{testnum}"""
 | |
|         endlabel = f"""_j_end_{label}"""
 | |
|         # This is all from testgen-TVAL.py, within the for loop on returningInstruction
 | |
|         #
 | |
|         # x25: mepc value
 | |
|         # x24: new csr value
 | |
|         # x23: original csr value
 | |
|         lines = f"""
 | |
|           li x30, 0
 | |
|           la x1, _m_trap_from_{label}
 | |
|           csrw mtvec, x1
 | |
| 
 | |
|           csrr x23, {csr}
 | |
| 
 | |
|           j _j_test_{label}
 | |
| 
 | |
|           _m_trap_from_{label}:
 | |
|           bnez x30, {endlabel}
 | |
| 
 | |
|           csrr x25, mcause
 | |
|           {newCSRValue}
 | |
| 
 | |
|           csrrs x20, mepc, x0
 | |
|           addi x20, x20, 4
 | |
|           csrrw x0, mepc, x20
 | |
|         
 | |
|           mret
 | |
| 
 | |
|           _j_test_{label}:
 | |
|         """
 | |
| 
 | |
|         lines += f"""
 | |
|           li x1, 0b110000000000
 | |
|           csrrc x0, mstatus, x1
 | |
|           li x1, 0b0100000000000
 | |
|           csrrs x0, mstatus, x1
 | |
| 
 | |
|           auipc x1, 0
 | |
|           addi x1, x1, 16 # x1 is now right after the mret instruction
 | |
|           csrw mepc, x1
 | |
|           mret
 | |
| 
 | |
|           # We're now in supervisor mode...
 | |
|         """
 | |
| 
 | |
|         # Code to bring us down to user mode
 | |
|         if fromMode == "u":
 | |
|           lines += f"""
 | |
| 
 | |
|           li x1, 0b110000000000
 | |
|           csrrc x0, sstatus, x1
 | |
| 
 | |
|           auipc x1, 0
 | |
|           addi x1, x1, 16 # x1 is now right after the sret instruction
 | |
|           csrw sepc, x1
 | |
|           sret
 | |
| 
 | |
|           # We're now in user mode...
 | |
|           """
 | |
| 
 | |
|         f.write(lines)
 | |
| 
 | |
| 
 | |
|         writeTest(storecmd, f, r, f"""csrrw x1, {csr}, x0""", csrWillChange)
 | |
|         writeTest(storecmd, f, r, f"""csrrw x0, {csr}, x13""", csrWillChange)
 | |
|         writeTest(storecmd, f, r, f"""csrrwi x0, {csr}, {a}""", csrWillChange)
 | |
|         if a != 0:
 | |
|           writeTest(storecmd, f, r, f"""csrrs x0, {csr}, x13""", csrWillChange)
 | |
|           writeTest(storecmd, f, r, f"""csrrc x0, {csr}, x13""", csrWillChange)
 | |
|           writeTest(storecmd, f, r, f"""csrrsi x0, {csr}, {a}""", csrWillChange)
 | |
|           writeTest(storecmd, f, r, f"""csrrci x0, {csr}, {a}""", csrWillChange)
 | |
| 
 | |
|         f.write(f"""
 | |
|           li x30, 1
 | |
|           ebreak
 | |
|           {endlabel}:
 | |
|         """)
 | |
| 
 | |
| 
 | |
|   
 | |
| 
 | |
| def writeTest(storecmd, f, r, test, csrWillChange):
 | |
|   global testnum
 | |
| 
 | |
|   test = f"""
 | |
|     _jdo{testnum}:
 | |
|     li x25, 0xDEADBEA7
 | |
| 
 | |
|     {test}
 | |
| 
 | |
|     {storecmd} x25, 0(x7)
 | |
|     addi x7, x7, {wordsize}
 | |
|   """
 | |
| 
 | |
|   # We expect x25 to always be an illegal instruction
 | |
|   expected = 2
 | |
| 
 | |
|   f.write(test)
 | |
|   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
 | |
| 
 | |
|   if not csrWillChange:
 | |
|     # We expect x24 should be equal to x23
 | |
|     expected = 0
 | |
| 
 | |
|     f.write(f"""
 | |
|       sub x25, x24, x23
 | |
|       {storecmd} x25, 0(x7)
 | |
|       addi x7, x7, {wordsize}
 | |
|     """)
 | |
|     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
 | |
| ##################################
 | |
| 
 | |
| author = "dottolia@hmc.edu"
 | |
| xlens = [32, 64]
 | |
| 
 | |
| # setup
 | |
| # Change this seed to a different constant value for every test
 | |
| seed(0xC363DAEB9193AB45) # 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 testMode in ["m", "s"]:
 | |
|     imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/"
 | |
|     basename = "WALLY-CSR-PERMISSIONS-" + testMode.upper()
 | |
|     fname = imperaspath + "src/" + basename + ".S"
 | |
|     refname = imperaspath + "references/" + basename + ".reference_output"
 | |
|     testnum = 0
 | |
|     storeAddressOffset = 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)
 | |
| 
 | |
|     f.write(f"""
 | |
|       add x7, x6, x0
 | |
|       csrr x19, mtvec
 | |
|     """)
 | |
| 
 | |
|     writeVectors(storecmd, testMode)
 | |
| 
 | |
|     f.write(f"""
 | |
|       csrw mtvec, x19
 | |
|     """)
 | |
| 
 | |
|     # 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()
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |