From efe2f16d12c23eca1e66d2a304d89aafb22f005f Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 10 Aug 2017 11:27:04 -0700 Subject: [PATCH] WIP multicore testing. --- debug/gdbserver.py | 36 +++++++++++++++++--- debug/programs/entry.S | 43 ++++++++++++++++++++---- debug/targets/RISC-V/spike32.lds | 2 ++ debug/targets/RISC-V/spike64.lds | 2 ++ debug/targets/SiFive/Freedom/Freedom.lds | 2 ++ debug/targets/SiFive/HiFive1.lds | 2 ++ debug/testlib.py | 26 ++++++++++---- 7 files changed, 95 insertions(+), 18 deletions(-) diff --git a/debug/gdbserver.py b/debug/gdbserver.py index 092f018..7ae3aa3 100755 --- a/debug/gdbserver.py +++ b/debug/gdbserver.py @@ -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", ) diff --git a/debug/programs/entry.S b/debug/programs/entry.S index c3be611..866636b 100755 --- a/debug/programs/entry.S +++ b/debug/programs/entry.S @@ -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 diff --git a/debug/targets/RISC-V/spike32.lds b/debug/targets/RISC-V/spike32.lds index 01d0e3d..84216db 100755 --- a/debug/targets/RISC-V/spike32.lds +++ b/debug/targets/RISC-V/spike32.lds @@ -22,11 +22,13 @@ SECTIONS } /* bss segment */ + __bss_start = .; .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon) } .bss : { *(.bss) } + __bss_end = .; __malloc_start = .; . = . + 512; diff --git a/debug/targets/RISC-V/spike64.lds b/debug/targets/RISC-V/spike64.lds index dc7cb63..2e7d65d 100755 --- a/debug/targets/RISC-V/spike64.lds +++ b/debug/targets/RISC-V/spike64.lds @@ -20,11 +20,13 @@ SECTIONS } /* bss segment */ + __bss_start = .; .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon) } .bss : { *(.bss) } + __bss_end = .; __malloc_start = .; . = . + 512; diff --git a/debug/targets/SiFive/Freedom/Freedom.lds b/debug/targets/SiFive/Freedom/Freedom.lds index 1e0645a..9354d3f 100644 --- a/debug/targets/SiFive/Freedom/Freedom.lds +++ b/debug/targets/SiFive/Freedom/Freedom.lds @@ -20,11 +20,13 @@ SECTIONS } /* bss segment */ + __bss_start = .; .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon) } .bss : { *(.bss) } + __bss_end = .; __malloc_start = .; . = . + 512; diff --git a/debug/targets/SiFive/HiFive1.lds b/debug/targets/SiFive/HiFive1.lds index 1e0645a..9354d3f 100755 --- a/debug/targets/SiFive/HiFive1.lds +++ b/debug/targets/SiFive/HiFive1.lds @@ -20,11 +20,13 @@ SECTIONS } /* bss segment */ + __bss_start = .; .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon) } .bss : { *(.bss) } + __bss_end = .; __malloc_start = .; . = . + 512; diff --git a/debug/testlib.py b/debug/testlib.py index 856b903..8ef50e6 100644 --- a/debug/testlib.py +++ b/debug/testlib.py @@ -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 -- 2.30.2