WIP multicore testing.
authorTim Newsome <tim@sifive.com>
Thu, 10 Aug 2017 18:27:04 +0000 (11:27 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 28 Aug 2017 19:16:39 +0000 (12:16 -0700)
debug/gdbserver.py
debug/programs/entry.S
debug/targets/RISC-V/spike32.lds
debug/targets/RISC-V/spike64.lds
debug/targets/SiFive/Freedom/Freedom.lds
debug/targets/SiFive/HiFive1.lds
debug/testlib.py

index 092f0181907f31db82b9806c2e574bbfdef7c381..7ae3aa3b1ba56dc57a443e367342c5b62b29fa2f 100755 (executable)
@@ -114,7 +114,6 @@ class SimpleF18Test(SimpleRegisterTest):
         assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - b), .001)
 
     def early_applicable(self):
-        print repr(self.hart)
         return self.hart.extensionSupported('F')
 
     def test(self):
@@ -416,20 +415,19 @@ class UserInterrupt(DebugTest):
         self.gdb.p("i=0")
         self.exit()
 
-class MulticoreTest(GdbTest):
-    compile_args = ("programs/infinite_loop.S", )
+class MulticoreRegTest(GdbTest):
+    compile_args = ("programs/infinite_loop.S", "-DMULTICORE")
 
     def early_applicable(self):
         return len(self.target.harts) > 1
 
     def setup(self):
         self.gdb.load()
-
-    def test(self):
         for hart in self.target.harts:
             self.gdb.select_hart(hart)
             self.gdb.p("$pc=_start")
 
+    def test(self):
         # Run to main
         self.gdb.b("main")
         self.gdb.c()
@@ -470,6 +468,34 @@ class MulticoreTest(GdbTest):
                 value = self.gdb.p("$x%d" % n)
                 assertEqual(value, hart.index * 0x800 + n - 1)
 
+class MulticoreRunHaltTest(GdbTest):
+    compile_args = ("programs/multicore.c", "-DMULTICORE")
+
+    def early_applicable(self):
+        return len(self.target.harts) > 1
+
+    def setup(self):
+        self.gdb.load()
+        for hart in self.target.harts:
+            self.gdb.select_hart(hart)
+            self.gdb.p("$pc=_start")
+
+    def test(self):
+        previous_hart_count = [0 for h in self.target.harts]
+        for _ in range(10):
+            self.gdb.c(wait=False)
+            time.sleep(1)
+            self.gdb.interrupt()
+            self.gdb.p("buf", fmt="")
+            hart_count = self.gdb.p("hart_count")
+            for i, h in enumerate(self.target.harts):
+                assertGreater(hart_count[i], previous_hart_count[i])
+                self.gdb.select_hart(h)
+                pc = self.gdb.p("$pc")
+                self.gdb.stepi()
+                stepped_pc = self.gdb.p("$pc")
+                assertNotEqual(pc, stepped_pc)
+
 class StepTest(GdbTest):
     compile_args = ("programs/step.S", )
 
index c3be61108e4a129b0ab2b087754d78d9d0ed1972..866636b1b50b7e052faaf150ae62752623a9f68d 100755 (executable)
@@ -3,7 +3,7 @@
 
 #include "encoding.h"
 
-#define STACK_SIZE 512
+#define STACK_SIZE 1024
 
 #if XLEN == 64
 # define LREG ld
@@ -61,8 +61,14 @@ handle_reset:
   la gp, __global_pointer$
 .option pop
 
-  # initialize stack pointer
-  la sp, stack_top
+  # Initialize stack pointer.
+  # Support up to 4 harts, with IDs 0--3.
+  csrr  t0, CSR_MHARTID
+  addi  t0, t0, 1
+  li    t1, STACK_SIZE / 4
+  mul   t0, t0, t1
+  la    sp, stack_bottom
+  add   sp, sp, t0
 
   # Clear all hardware triggers
   li    t0, ~0
@@ -73,8 +79,33 @@ handle_reset:
   csrr  t1, CSR_TSELECT
   beq   t0, t1, 1b
 
+#ifdef MULTICORE
+  csrr  t0, CSR_MHARTID
+  bnez  t0, wait_until_initialized
+#endif
+
+  la    t0, __bss_start
+  la    t1, __bss_end
+1:
+  bge   t0, t1, 2f
+  sb    zero, 0(t0)
+  addi  t0, t0, 1
+  j     1b
+2:
+#ifdef MULTICORE
+  la    t0, initialized
+  li    t1, 1
+  sw    t1, 0(t0)
+
+wait_until_initialized:      # Wait for hart 0 to perform initialization.
+  la    t0, initialized
+1:
+  lw    t1, 0(t0)
+  beqz  t1, 1b
+#endif
+
   # perform the rest of initialization in C
-  j _init
+  j     _init
 
 
 trap_entry:
@@ -165,8 +196,6 @@ loop_forever:
 stack_bottom:
   .fill STACK_SIZE/4, 4, 0x22446688
 stack_top:
-  // Prevent stack_top from being identical to next symbol, which may cause gdb
-  // to report we're halted at stack_top which happens to be the same address
-  // as main.
+initialized:
   .word 0
 #endif
index 01d0e3d0f7861ac5d6766cf4af4754630072ceca..84216dbac808ad27520bb1a16fbbb93306abf721 100755 (executable)
@@ -22,11 +22,13 @@ SECTIONS
   }
 
   /* bss segment */
+  __bss_start = .;
   .sbss : {
     *(.sbss .sbss.* .gnu.linkonce.sb.*)
     *(.scommon)
   }
   .bss : { *(.bss) }
+  __bss_end = .;
 
   __malloc_start = .;
   . = . + 512;
index dc7cb63a86f9ddce9a662f0a6d09033bdfe046d3..2e7d65d177f8ef470a4b4da54769f5b3b3f777eb 100755 (executable)
@@ -20,11 +20,13 @@ SECTIONS
   }
 
   /* bss segment */
+  __bss_start = .;
   .sbss : {
     *(.sbss .sbss.* .gnu.linkonce.sb.*)
     *(.scommon)
   }
   .bss : { *(.bss) }
+  __bss_end = .;
 
   __malloc_start = .;
   . = . + 512;
index 1e0645a34ef8ac6f1c6f0fd23b0bab9d4ee52ed4..9354d3fa49f5e3df67cb0c284f0ebb39b160cbfa 100644 (file)
@@ -20,11 +20,13 @@ SECTIONS
   }
 
   /* bss segment */
+  __bss_start = .;
   .sbss : {
     *(.sbss .sbss.* .gnu.linkonce.sb.*)
     *(.scommon)
   }
   .bss : { *(.bss) }
+  __bss_end = .;
 
   __malloc_start = .;
   . = . + 512;
index 1e0645a34ef8ac6f1c6f0fd23b0bab9d4ee52ed4..9354d3fa49f5e3df67cb0c284f0ebb39b160cbfa 100755 (executable)
@@ -20,11 +20,13 @@ SECTIONS
   }
 
   /* bss segment */
+  __bss_start = .;
   .sbss : {
     *(.sbss .sbss.* .gnu.linkonce.sb.*)
     *(.scommon)
   }
   .bss : { *(.bss) }
+  __bss_end = .;
 
   __malloc_start = .;
   . = . + 512;
index 856b9031e6b0077c97e1f1313ce5c7d32f6f5701..8ef50e657527138905a34c067823f809a3150810 100644 (file)
@@ -17,8 +17,11 @@ import pexpect
 def find_file(path):
     for directory in (os.getcwd(), os.path.dirname(__file__)):
         fullpath = os.path.join(directory, path)
-        if os.path.exists(fullpath):
-            return fullpath
+        relpath = os.path.relpath(fullpath)
+        if len(relpath) >= len(fullpath):
+            relpath = fullpath
+        if os.path.exists(relpath):
+            return relpath
     return None
 
 def compile(args, xlen=32): # pylint: disable=redefined-builtin
@@ -363,13 +366,23 @@ class Gdb(object):
             raise CannotAccess(int(m.group(1), 0))
         return output.split('=')[-1].strip()
 
-    def p(self, obj):
-        output = self.command("p/x %s" % obj)
+    def parse_string(self, text):
+        text = text.strip()
+        if text.startswith("{") and text.endswith("}"):
+            inner = text[1:-1]
+            return [self.parse_string(t) for t in inner.split(", ")]
+        elif text.startswith('"') and text.endswith('"'):
+            return text[1:-1]
+        else:
+            return int(text, 0)
+
+    def p(self, obj, fmt="/x"):
+        output = self.command("p%s %s" % (fmt, obj))
         m = re.search("Cannot access memory at address (0x[0-9a-f]+)", output)
         if m:
             raise CannotAccess(int(m.group(1), 0))
-        value = int(output.split('=')[-1].strip(), 0)
-        return value
+        rhs = output.split('=')[-1]
+        return self.parse_string(rhs)
 
     def p_string(self, obj):
         output = self.command("p %s" % obj)
@@ -530,6 +543,7 @@ class BaseTest(object):
             self.hart = hart
         else:
             self.hart = random.choice(target.harts)
+            self.hart = target.harts[-1]    #<<<
         self.server = None
         self.target_process = None
         self.binary = None