forked from Github_Repos/cvw
Complete STORE tests
This commit is contained in:
parent
79cb7ed571
commit
8588a1ed6b
@ -136,7 +136,8 @@ string tests64iNOc[] = {
|
|||||||
"rv64i/I-XOR-01", "3000",
|
"rv64i/I-XOR-01", "3000",
|
||||||
"rv64i/I-XORI-01", "3000",
|
"rv64i/I-XORI-01", "3000",
|
||||||
"rv64i/WALLY-ADD", "4000",
|
"rv64i/WALLY-ADD", "4000",
|
||||||
"rv64i/WALLY-SUB", "4000"
|
"rv64i/WALLY-SUB", "4000",
|
||||||
|
"rv64i/WALLY-STORE", "3000"
|
||||||
};
|
};
|
||||||
string tests32ic[] = '{
|
string tests32ic[] = '{
|
||||||
// "rv32ic/WALLY-C-ADHOC-01", "2000",
|
// "rv32ic/WALLY-C-ADHOC-01", "2000",
|
||||||
@ -217,7 +218,8 @@ string tests32i[] = {
|
|||||||
"rv32i/I-XOR-01","2000",
|
"rv32i/I-XOR-01","2000",
|
||||||
"rv32i/I-XORI-01","2000",
|
"rv32i/I-XORI-01","2000",
|
||||||
"rv32i/WALLY-ADD", "3000",
|
"rv32i/WALLY-ADD", "3000",
|
||||||
"rv32i/WALLY-SUB", "3000"
|
"rv32i/WALLY-SUB", "3000",
|
||||||
|
"rv32i/WALLY-STORE", "2000"
|
||||||
};
|
};
|
||||||
string tests[];
|
string tests[];
|
||||||
|
|
||||||
|
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