Skip to content

Commit

Permalink
Create a more sophisticated vector test (riscv-software-src#284)
Browse files Browse the repository at this point in the history
* WIP

* WIP

* Vector test seems to work well with spike.

* Check a0 in case the program didn't work right.

* Return not applicable if compile doesn't support V
  • Loading branch information
timsifive authored Jun 25, 2020
1 parent fbe74f4 commit 944704e
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 10 deletions.
62 changes: 61 additions & 1 deletion debug/gdbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn
from testlib import assertGreater, assertRegex, assertLess
from testlib import GdbTest, GdbSingleHartTest, TestFailed
from testlib import assertTrue, TestNotApplicable
from testlib import assertTrue, TestNotApplicable, CompileError

MSTATUS_UIE = 0x00000001
MSTATUS_SIE = 0x00000002
Expand Down Expand Up @@ -1389,6 +1389,66 @@ def test(self):
self.gdb.p("vms=&sv48")
self.test_translation()

class VectorTest(GdbSingleHartTest):
compile_args = ("programs/vectors.S", )

def early_applicable(self):
if not self.hart.extensionSupported('V'):
return False
# If the compiler can't build this test, say it's not applicable. At
# some time all compilers will support the V extension, but we're not
# there yet.
try:
self.compile()
except CompileError as e:
if b"Error: unknown CSR `vlenb'" in e.stderr:
return False
return True

def setup(self):
self.gdb.load()
self.gdb.b("main")
self.gdb.c()

def test(self):
vlenb = self.gdb.p("$vlenb")
self.gdb.command("delete")
self.gdb.b("_exit")
self.gdb.b("trap_entry")

self.gdb.b("test0")

output = self.gdb.c()
assertIn("Breakpoint", output)
assertIn("test0", output)

assertEqual(self.gdb.p("$a0"), 0)
a = self.gdb.x("&a", 'b', vlenb)
b = self.gdb.x("&b", 'b', vlenb)
v4 = self.gdb.p("$v4")
assertEqual(a, b)
assertEqual(b, v4["b"])
assertEqual(0, self.gdb.p("$a0"))

self.gdb.b("test1")

output = self.gdb.c()
assertIn("Breakpoint", output)
assertIn("test1", output)

assertEqual(self.gdb.p("$a0"), 0)
b = self.gdb.x("&b", 'b', vlenb)
c = self.gdb.x("&c", 'b', vlenb)
v4 = self.gdb.p("$v4")
assertEqual(b, c)
assertEqual(c, v4["b"])
assertEqual(0, self.gdb.p("$a0"))

output = self.gdb.c()
assertIn("Breakpoint", output)
assertIn("_exit", output)
assertEqual(self.gdb.p("status"), 0)

parsed = None
def main():
parser = argparse.ArgumentParser(
Expand Down
159 changes: 159 additions & 0 deletions debug/programs/vectors.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include "encoding.h"

#if XLEN == 64
# define LREG ld
# define SREG sd
# define REGBYTES 8
#else
# define LREG lw
# define SREG sw
# define REGBYTES 4
#endif

#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))

.global main
.global main_end
.global main_post_csrr

// Load constants into all registers so we can test no register are
// clobbered after attaching.
main:
SREG ra, 0(sp)
addi sp, sp, REGBYTES

// Set VS=1
csrr t0, CSR_MSTATUS
li t1, set_field(0, MSTATUS_VS, 1)
or t0, t0, t1
csrw CSR_MSTATUS, t0

// copy a to b
la a0, a
jal vector_load_v4
la a0, b
jal shift_store_v4

// assert a == b
la a0, a
la a1, b
jal check_equal
test0:
bne a0, zero, return_from_main

// copy b to c
la a0, b
jal shift_load_v4
la a0, c
jal vector_store_v4

// assert b == c
la a0, b
la a1, c
jal check_equal
test1:
bne a0, zero, return_from_main

return_from_main:
addi sp, sp, -REGBYTES
LREG ra, 0(sp)
ret

vector_load_v4:
// a0: point to memory to load from
csrr s0, vlenb
vsetvli zero, s0, e8, m1 # Vectors of 8b
vle8.v v4, 0(a0) # Load bytes
ret

vector_store_v4:
// a0: point to memory to store to
csrr s0, vlenb
vsetvli zero, s0, e8, m1 # Vectors of 8b
vse8.v v4, 0(a0) # Load bytes
ret

shift_load_v4:
// a0: pointer to memory to load from

// Configure all elements in the chain
csrr s0, vlenb
#if XLEN == 32
vsetvli zero, s0, e32
#else
vsetvli zero, s0, e64
#endif

// Figure out how long the chain is.
csrr s0, vlenb
li s1, XLEN/8
divu s0, s0, s1

1:
LREG s2, 0(a0)
vslide1down.vx v4, v4, s2
addi a0, a0, REGBYTES
addi s0, s0, -1
bne s0, zero, 1b

ret

shift_store_v4:
// a0: pointer to memory to store to

// Configure all elements in the chain
csrr s0, vlenb
#if XLEN == 32
vsetvli zero, s0, e32
#else
vsetvli zero, s0, e64
#endif

// Figure out how long the chain is.
csrr s0, vlenb
li s1, XLEN/8
divu s0, s0, s1

1:
vmv.x.s s2, v4
SREG s2, 0(a0)
vslide1down.vx v4, v4, s2
addi a0, a0, REGBYTES
addi s0, s0, -1
bne s0, zero, 1b

ret

check_equal:
csrr s0, vlenb
1:
lb s1, 0(a0)
lb s2, 0(a1)
bne s1, s2, 2f
addi a0, a0, 1
addi a1, a1, 1
addi s0, s0, -1
bne s0, zero, 1b
li a0, 0 // equal
ret
2: // unequal
li a0, 1
ret

.data
.align 6
a: .word 0xaa00, 0xaa01, 0xaa02, 0xaa03, 0xaa04, 0xaa05, 0xaa06, 0xaa07
.word 0xaa08, 0xaa09, 0xaa0a, 0xaa0b, 0xaa0c, 0xaa0d, 0xaa0e, 0xaa0f
.word 0xaa10, 0xaa11, 0xaa12, 0xaa13, 0xaa14, 0xaa15, 0xaa16, 0xaa17
.word 0xaa18, 0xaa19, 0xaa1a, 0xaa1b, 0xaa1c, 0xaa1d, 0xaa1e, 0xaa1f

b: .word 0xbb00, 0xbb01, 0xbb02, 0xbb03, 0xbb04, 0xbb05, 0xbb06, 0xbb07
.word 0xbb08, 0xbb09, 0xbb0b, 0xbb0b, 0xbb0c, 0xbb0d, 0xbb0e, 0xbb0f
.word 0xbb10, 0xbb11, 0xbb13, 0xbb13, 0xbb14, 0xbb15, 0xbb16, 0xbb17
.word 0xbb18, 0xbb19, 0xbb1b, 0xbb1b, 0xbb1c, 0xbb1d, 0xbb1e, 0xbb1f

c: .word 0xcc00, 0xcc01, 0xcc02, 0xcc03, 0xcc04, 0xcc05, 0xcc06, 0xcc07
.word 0xcc08, 0xcc09, 0xcc0c, 0xcc0c, 0xcc0c, 0xcc0d, 0xcc0e, 0xcc0f
.word 0xcc10, 0xcc11, 0xcc13, 0xcc13, 0xcc14, 0xcc15, 0xcc16, 0xcc17
.word 0xcc18, 0xcc19, 0xcc1c, 0xcc1c, 0xcc1c, 0xcc1d, 0xcc1e, 0xcc1f
2 changes: 1 addition & 1 deletion debug/targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def compile(self, hart, *sources):
args.append("-DRV32E")
else:
march = "rv%dima" % hart.xlen
for letter in "fdc":
for letter in "fdcv":
if hart.extensionSupported(letter):
march += letter
args.append("-march=%s" % march)
Expand Down
35 changes: 27 additions & 8 deletions debug/testlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,18 @@ def find_file(path):
return relpath
return None

class CompileError(Exception):
def __init__(self, stdout, stderr):
self.stdout = stdout
self.stderr = stderr

gcc_cmd = None
def compile(args): # pylint: disable=redefined-builtin
cmd = ["riscv64-unknown-elf-gcc", "-g"]
if gcc_cmd:
cmd = [gcc_cmd]
else:
cmd = ["riscv64-unknown-elf-gcc"]
cmd.append("-g")
for arg in args:
found = find_file(arg)
if found:
Expand All @@ -43,10 +53,10 @@ def compile(args): # pylint: disable=redefined-builtin
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if process.returncode:
print(stdout, end=" ")
print(stderr, end=" ")
print(stdout.decode('ascii'), end=" ")
print(stderr.decode('ascii'), end=" ")
header("")
raise Exception("Compile failed!")
raise CompileError(stdout, stderr)

class Spike:
# pylint: disable=too-many-instance-attributes
Expand Down Expand Up @@ -666,10 +676,15 @@ def interrupt_all(self):
self.select_child(child)
self.interrupt()

def x(self, address, size='w'):
output = self.command("x/%s %s" % (size, address))
value = int(output.split(':')[1].strip(), 0)
return value
def x(self, address, size='w', count=1):
output = self.command("x/%d%s %s" % (count, size, address))
values = []
for line in output.splitlines():
for value in line.split(':')[1].strip().split():
values.append(int(value, 0))
if len(values) == 1:
return values[0]
return values

def p_raw(self, obj):
output = self.command("p %s" % obj)
Expand Down Expand Up @@ -806,6 +821,8 @@ def run_all_tests(module, target, parsed):

global gdb_cmd # pylint: disable=global-statement
gdb_cmd = parsed.gdb
global gcc_cmd # pylint: disable=global-statement
gcc_cmd = parsed.gcc

examine_added = False
for hart in target.harts:
Expand Down Expand Up @@ -889,6 +906,8 @@ def add_test_run_options(parser):
help="Print out a list of tests, and exit immediately.")
parser.add_argument("test", nargs='*',
help="Run only tests that are named here.")
parser.add_argument("--gcc",
help="The command to use to start gcc.")
parser.add_argument("--gdb",
help="The command to use to start gdb.")
parser.add_argument("--misaval",
Expand Down

0 comments on commit 944704e

Please sign in to comment.