aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-06-22 18:37:55 -0700
committerTim Newsome <tim@sifive.com>2017-06-22 18:37:55 -0700
commit806deb8e53e029df31defc88d09c6c2c2b08e8f3 (patch)
treea3398c2fffaadc24296f245a7e69356a22e4b466
parent9ff4594d26f485495f47d4473905af9c4f10caa8 (diff)
downloadriscv-tests-806deb8e53e029df31defc88d09c6c2c2b08e8f3.zip
riscv-tests-806deb8e53e029df31defc88d09c6c2c2b08e8f3.tar.gz
riscv-tests-806deb8e53e029df31defc88d09c6c2c2b08e8f3.tar.bz2
Add basic multicore test.
-rwxr-xr-xdebug/gdbserver.py64
-rw-r--r--debug/programs/infinite_loop.S69
-rw-r--r--debug/testlib.py37
3 files changed, 128 insertions, 42 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index 4dc00c4..2dcd404 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -10,7 +10,7 @@ import os
import targets
import testlib
-from testlib import assertEqual, assertNotEqual, assertIn
+from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn
from testlib import assertGreater, assertRegexpMatches, assertLess
from testlib import GdbTest
@@ -399,6 +399,68 @@ class UserInterrupt(DebugTest):
self.gdb.p("i=0")
self.exit()
+class MulticoreTest(GdbTest):
+ compile_args = ("programs/infinite_loop.S", )
+
+ def setup(self):
+ self.gdb.load()
+ self.gdb.b("main")
+ self.gdb.b("main_end")
+ self.gdb.command("set non-stop on")
+ self.gdb.c()
+
+ def test(self):
+ threads = self.gdb.threads()
+ if len(threads) < 2:
+ return 'not_applicable'
+ # Run through the entire loop.
+ for t in threads:
+ self.gdb.thread(t)
+ self.gdb.p("$pc=_start")
+ # Run to main
+ for t in threads:
+ self.gdb.thread(t)
+ self.gdb.c()
+ for t in self.gdb.threads():
+ assertIn("main", t.frame)
+ # Run to end
+ for t in threads:
+ self.gdb.thread(t)
+ self.gdb.c()
+ hart_ids = []
+ for t in self.gdb.threads():
+ assertIn("main_end", t.frame)
+ # Check register values.
+ self.gdb.thread(t)
+ hart_id = self.gdb.p("$x1")
+ assertNotIn(hart_id, hart_ids)
+ hart_ids.append(hart_id)
+ for n in range(2, 32):
+ value = self.gdb.p("$x%d" % n)
+ assertEqual(value, hart_ids[-1] + n - 1)
+
+ # Confirmed that we read different register values for different harts.
+ # Write a new value to x1, and run through the add sequence again.
+
+ # This part isn't working right, because gdb doesn't resume Thread 2
+ # when asked. I don't know the root cause for that, but up to this
+ # point the test is still useful.
+
+# for t in threads:
+# self.gdb.thread(t)
+# self.gdb.p("$x1=0x%x" % (int(t.id) + 0x800))
+# self.gdb.p("$pc=main_post_csrr")
+# for t in threads:
+# self.gdb.thread(t)
+# self.gdb.c()
+# for t in self.gdb.threads():
+# assertIn("main_end", t.frame)
+# # Check register values.
+# self.gdb.thread(t)
+# for n in range(1, 32):
+# value = self.gdb.p("$x%d" % n)
+# assertEqual(value, int(t.id) + 0x800 + n - 1)
+
class StepTest(GdbTest):
compile_args = ("programs/step.S", )
diff --git a/debug/programs/infinite_loop.S b/debug/programs/infinite_loop.S
index 4b83143..6f15f45 100644
--- a/debug/programs/infinite_loop.S
+++ b/debug/programs/infinite_loop.S
@@ -1,40 +1,43 @@
#include "encoding.h"
.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:
- csrr x1, CSR_MISA
- slli x2, x1, 1
- slli x3, x2, 1
- slli x4, x3, 1
- slli x5, x4, 1
- slli x6, x5, 1
- slli x7, x6, 1
- slli x8, x7, 1
- slli x9, x8, 1
- slli x10, x9, 1
- slli x11, x10, 1
- slli x12, x11, 1
- slli x13, x12, 1
- slli x14, x13, 1
- slli x15, x14, 1
- slli x16, x15, 1
- slli x17, x16, 1
- slli x18, x17, 1
- slli x19, x18, 1
- slli x20, x19, 1
- slli x21, x20, 1
- slli x22, x21, 1
- slli x23, x22, 1
- slli x24, x23, 1
- slli x25, x24, 1
- slli x26, x25, 1
- slli x27, x26, 1
- slli x28, x27, 1
- slli x29, x28, 1
- slli x30, x29, 1
- slli x31, x30, 1
-1:
- j 1b
+ csrr x1, CSR_MHARTID
+main_post_csrr:
+ addi x2, x1, 1
+ addi x3, x2, 1
+ addi x4, x3, 1
+ addi x5, x4, 1
+ addi x6, x5, 1
+ addi x7, x6, 1
+ addi x8, x7, 1
+ addi x9, x8, 1
+ addi x10, x9, 1
+ addi x11, x10, 1
+ addi x12, x11, 1
+ addi x13, x12, 1
+ addi x14, x13, 1
+ addi x15, x14, 1
+ addi x16, x15, 1
+ addi x17, x16, 1
+ addi x18, x17, 1
+ addi x19, x18, 1
+ addi x20, x19, 1
+ addi x21, x20, 1
+ addi x22, x21, 1
+ addi x23, x22, 1
+ addi x24, x23, 1
+ addi x25, x24, 1
+ addi x26, x25, 1
+ addi x27, x26, 1
+ addi x28, x27, 1
+ addi x29, x28, 1
+ addi x30, x29, 1
+ addi x31, x30, 1
+main_end:
+ j main
diff --git a/debug/testlib.py b/debug/testlib.py
index b8ff5c2..b59e6e8 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -1,3 +1,4 @@
+import collections
import os.path
import random
import re
@@ -294,6 +295,9 @@ class CannotAccess(Exception):
Exception.__init__(self)
self.address = address
+Thread = collections.namedtuple('Thread', ('id', 'target_id', 'name',
+ 'frame'))
+
class Gdb(object):
logfile = tempfile.NamedTemporaryFile(prefix="gdb", suffix=".log")
logname = logfile.name
@@ -320,13 +324,17 @@ class Gdb(object):
self.child.expect(r"\(gdb\)", timeout=timeout)
return self.child.before.strip()
- def c(self, wait=True, timeout=-1):
+ def c(self, wait=True, timeout=-1, async=False):
+ if async:
+ async = "&"
+ else:
+ async = ""
if wait:
- output = self.command("c", timeout=timeout)
+ output = self.command("c%s" % async, timeout=timeout)
assert "Continuing" in output
return output
else:
- self.child.sendline("c")
+ self.child.sendline("c%s" % async)
self.child.expect("Continuing")
def interrupt(self):
@@ -380,6 +388,22 @@ class Gdb(object):
assert "Hardware assisted breakpoint" in output
return output
+ def threads(self):
+ output = self.command("info threads")
+ threads = []
+ for line in output.splitlines():
+ m = re.match(
+ r"[\s\*]*(\d+)\s*Thread (\d+)\s*\(Name: ([^\)]+)\s*(.*)",
+ line)
+ if m:
+ threads.append(Thread(*m.groups()))
+ if not threads:
+ threads.append(Thread('1', '1', 'Default', '???'))
+ return threads
+
+ def thread(self, thread):
+ return self.command("thread %s" % thread.id)
+
def run_all_tests(module, target, parsed):
if not os.path.exists(parsed.logs):
os.makedirs(parsed.logs)
@@ -594,11 +618,8 @@ class GdbTest(BaseTest):
"target extended-remote localhost:%d" % self.server.port)
# Select a random thread.
# TODO: Allow a command line option to force a specific thread.
- output = self.gdb.command("info threads")
- threads = re.findall(r"Thread (\d+)", output)
- if threads:
- thread = random.choice(threads)
- self.gdb.command("thread %s" % thread)
+ thread = random.choice(self.gdb.threads())
+ self.gdb.thread(thread)
# FIXME: OpenOCD doesn't handle PRIV now
#self.gdb.p("$priv=3")