debug: Need to apply remotetimeout before connecting to remote target (#94)
[riscv-tests.git] / debug / testlib.py
index 385034b82a9103989059703c7d5a7e39b185b87a..f6643ac267a82f0230d0417c99903f47e16d41b8 100644 (file)
@@ -314,6 +314,7 @@ class Gdb(object):
 
     def __init__(self, ports,
             cmd=os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb"),
+            timeout=60,
             binary=None):
         assert ports
 
@@ -340,6 +341,7 @@ class Gdb(object):
             self.command("set height 0")
             # Force consistency.
             self.command("set print entry-values no")
+            self.command("set remotetimeout %d" % timeout)
             self.command("target extended-remote localhost:%d" % port)
             if binary:
                 self.command("file %s" % binary)
@@ -420,7 +422,17 @@ class Gdb(object):
             self.active_child.expect("Continuing")
 
     def c_all(self):
-        """Resume every hart."""
+        """
+        Resume every hart.
+
+        This function works fine when using multiple gdb sessions, but the
+        caller must be careful when using it nonetheless. gdb's behavior is to
+        not set breakpoints until just before the hart is resumed, and then
+        clears them as soon as the hart halts. That means that you can't set
+        one software breakpoint, and expect multiple harts to hit it. It's
+        possible that the first hart completes set/run/halt/clear before the
+        second hart even gets to resume, so it will never hit the breakpoint.
+        """
         with PrivateState(self):
             for child in self.children:
                 child.sendline("c")
@@ -532,18 +544,20 @@ def run_all_tests(module, target, parsed):
     gdb_cmd = parsed.gdb
 
     todo = []
+    examine_added = False
     for hart in target.harts:
         if parsed.misaval:
             hart.misa = int(parsed.misaval, 16)
             print "Using $misa from command line: 0x%x" % hart.misa
         elif hart.misa:
             print "Using $misa from hart definition: 0x%x" % hart.misa
-        else:
-            todo.append(("ExamineTarget", ExamineTarget, hart))
+        elif not examine_added:
+            todo.append(("ExamineTarget", ExamineTarget, None))
+            examine_added = True
 
     for name in dir(module):
         definition = getattr(module, name)
-        if type(definition) == type and hasattr(definition, 'test') and \
+        if isinstance(definition, type) and hasattr(definition, 'test') and \
                 (not parsed.test or any(test in name for test in parsed.test)):
             todo.append((name, definition, None))
 
@@ -658,7 +672,6 @@ class BaseTest(object):
         compile_args = getattr(self, 'compile_args', None)
         if compile_args:
             if compile_args not in BaseTest.compiled:
-                # pylint: disable=star-args
                 BaseTest.compiled[compile_args] = \
                         self.target.compile(self.hart, *compile_args)
         self.binary = BaseTest.compiled.get(compile_args)
@@ -746,16 +759,15 @@ class GdbTest(BaseTest):
         BaseTest.classSetup(self)
 
         if gdb_cmd:
-            self.gdb = Gdb(self.server.gdb_ports, gdb_cmd, binary=self.binary)
+            self.gdb = Gdb(self.server.gdb_ports, gdb_cmd, timeout=self.target.timeout_sec, binary=self.binary)
         else:
-            self.gdb = Gdb(self.server.gdb_ports, binary=self.binary)
+            self.gdb = Gdb(self.server.gdb_ports, timeout=self.target.timeout_sec, binary=self.binary)
 
         self.logs += self.gdb.lognames()
 
-        if self.target:
-            self.gdb.global_command("set arch riscv:rv%d" % self.hart.xlen)
-            self.gdb.global_command("set remotetimeout %d" %
-                    self.target.timeout_sec)
+        self.gdb.global_command("set arch riscv:rv%d" % self.hart.xlen)
+        self.gdb.global_command("set remotetimeout %d" %
+            self.target.timeout_sec)
 
         for cmd in self.target.gdb_setup:
             self.gdb.command(cmd)
@@ -788,23 +800,26 @@ class GdbSingleHartTest(GdbTest):
 
 class ExamineTarget(GdbTest):
     def test(self):
-        self.hart.misa = self.gdb.p("$misa")
-
-        txt = "RV"
-        if (self.hart.misa >> 30) == 1:
-            txt += "32"
-        elif (self.hart.misa >> 62) == 2:
-            txt += "64"
-        elif (self.hart.misa >> 126) == 3:
-            txt += "128"
-        else:
-            raise TestFailed("Couldn't determine XLEN from $misa (0x%x)" %
-                    self.hart.misa)
+        for hart in self.target.harts:
+            self.gdb.select_hart(hart)
+
+            hart.misa = self.gdb.p("$misa")
+
+            txt = "RV"
+            if (hart.misa >> 30) == 1:
+                txt += "32"
+            elif (hart.misa >> 62) == 2:
+                txt += "64"
+            elif (hart.misa >> 126) == 3:
+                txt += "128"
+            else:
+                raise TestFailed("Couldn't determine XLEN from $misa (0x%x)" %
+                        self.hart.misa)
 
-        for i in range(26):
-            if self.hart.misa & (1<<i):
-                txt += chr(i + ord('A'))
-        print txt,
+            for i in range(26):
+                if hart.misa & (1<<i):
+                    txt += chr(i + ord('A'))
+            print txt,
 
 class TestFailed(Exception):
     def __init__(self, message):