From 4f784ca9b8d3536c16061518c1c2b66e3118cc5c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 11 Mar 2019 08:43:14 -0700 Subject: Add SmpSimultaneousRunHalt test. (#181) This test confirms that in SMP configurations OpenOCD halts the harts near-simulatenously. (It'll also check for resume, but that's not implemented yet so commented out for now.) --- debug/Makefile | 3 +++ debug/gdbserver.py | 49 ++++++++++++++++++++++++++++++++++++++++ debug/programs/run_halt_timing.c | 17 ++++++++++++++ debug/testlib.py | 30 ++++++++++++++++-------- 4 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 debug/programs/run_halt_timing.c diff --git a/debug/Makefile b/debug/Makefile index 75900df..41d08f5 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -11,6 +11,9 @@ all-tests: spike32 spike32-2 spike32-2-rtos spike32-2-hwthread \ all: pylint all-tests +# Target to check all the multicore options. +multi-tests: spike32-2 spike64-2-rtos spike32-2-hwthread + pylint: pylint --rcfile=pylint.rc `git ls-files '*.py'` diff --git a/debug/gdbserver.py b/debug/gdbserver.py index adcb6b2..e7f0701 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -842,6 +842,55 @@ class MulticoreRtosSwitchActiveHartTest(GdbTest): assertIn("set_trap_handler", output) assertNotIn("received signal SIGTRAP", output) +class SmpSimultaneousRunHalt(GdbTest): + compile_args = ("programs/run_halt_timing.c", "-DMULTICORE") + + def early_applicable(self): + return len(self.target.harts) > 1 + + def setup(self): + self.gdb.select_hart(self.target.harts[0]) + self.gdb.load() + for hart in self.target.harts: + self.gdb.select_hart(hart) + self.gdb.p("$pc=_start") + + def test(self): + if self.gdb.one_hart_per_gdb() or not self.server.smp(): + return 'not_applicable' + + old_mtime = set() + for _ in range(5): + self.gdb.c_all(wait=False) + time.sleep(2) + self.gdb.interrupt_all() + + mtime_value = [] + counter = [] + for hart in self.target.harts: + self.gdb.select_hart(hart) + mv = self.gdb.p("mtime_value") + assertNotIn(mv, old_mtime, + "mtime doesn't appear to be changing at all") + mtime_value.append(mv) + c = self.gdb.p("counter") + assertNotEqual(c, 0, + "counter didn't increment; code didn't run?") + counter.append(c) + self.gdb.p("counter=0") + + old_mtime.update(mtime_value) + + mtime_spread = max(mtime_value) - min(mtime_value) + print "mtime_spread:", mtime_spread + counter_spread = max(counter) - min(counter) + print "counter_spread:", counter_spread + + assertLess(mtime_spread, 100 * len(self.target.harts), + "Harts don't halt around the same time.") +#TODO assertLess(counter_spread, 100 * len(self.target.harts), +#TODO "Harts don't resume around the same time.") + class StepTest(GdbSingleHartTest): compile_args = ("programs/step.S", ) diff --git a/debug/programs/run_halt_timing.c b/debug/programs/run_halt_timing.c new file mode 100644 index 0000000..1c9a8ba --- /dev/null +++ b/debug/programs/run_halt_timing.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +#include "init.h" + +int main() +{ + int counter = 0; + volatile uint64_t mtime_value; + + while (1) { + counter = counter + 1; + mtime_value = MTIME; + } +} diff --git a/debug/testlib.py b/debug/testlib.py index 9c620b2..c4b785c 100644 --- a/debug/testlib.py +++ b/debug/testlib.py @@ -245,12 +245,12 @@ class Openocd(object): ] if config: - f = find_file(config) - if f is None: + self.config_file = find_file(config) + if self.config_file is None: print "Unable to read file " + config exit(1) - cmd += ["-f", f] + cmd += ["-f", self.config_file] if debug: cmd.append("-d") @@ -318,6 +318,14 @@ class Openocd(object): except (OSError, AttributeError): pass + def smp(self): + """Return true iff OpenOCD internally sees the harts as part of an SMP + group.""" + for line in file(self.config_file, "r"): + if "target smp" in line: + return True + return False + class OpenocdCli(object): def __init__(self, port=4444): self.child = pexpect.spawn( @@ -967,9 +975,11 @@ class ExamineTarget(GdbTest): print txt, class TestFailed(Exception): - def __init__(self, message): + def __init__(self, message, comment=None): Exception.__init__(self) self.message = message + if comment: + self.message += ": %s" % comment class TestNotApplicable(Exception): def __init__(self, message): @@ -980,25 +990,25 @@ def assertEqual(a, b): if a != b: raise TestFailed("%r != %r" % (a, b)) -def assertNotEqual(a, b): +def assertNotEqual(a, b, comment=None): if a == b: - raise TestFailed("%r == %r" % (a, b)) + raise TestFailed("%r == %r" % (a, b), comment) def assertIn(a, b): if a not in b: raise TestFailed("%r not in %r" % (a, b)) -def assertNotIn(a, b): +def assertNotIn(a, b, comment=None): if a in b: - raise TestFailed("%r in %r" % (a, b)) + raise TestFailed("%r in %r" % (a, b), comment) def assertGreater(a, b): if not a > b: raise TestFailed("%r not greater than %r" % (a, b)) -def assertLess(a, b): +def assertLess(a, b, comment=None): if not a < b: - raise TestFailed("%r not less than %r" % (a, b)) + raise TestFailed("%r not less than %r" % (a, b), comment) def assertTrue(a): if not a: -- cgit v1.1