debug: Use a more practical debug ROM
authorMegan Wachs <megan@sifive.com>
Tue, 18 Apr 2017 02:36:01 +0000 (19:36 -0700)
committerMegan Wachs <megan@sifive.com>
Tue, 18 Apr 2017 02:36:01 +0000 (19:36 -0700)
debug_rom/Makefile
debug_rom/debug_rom.S
debug_rom/debug_rom.h
debug_rom/link.ld

index b72f37db7b6193bff825d0e0974302bc4aab66a8..fa0154533b152c717e296ffdab835e8d1fe4657a 100644 (file)
@@ -6,7 +6,7 @@ OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy
 
 COMPILE = $(CC) -nostdlib -nostartfiles -I.. -Tlink.ld
 
-ELFS = debug_rom debug_rom32 debug_rom64
+ELFS = debug_rom
 DEPS = debug_rom.S link.ld
 
 all: $(patsubst %,%.h,$(ELFS))
@@ -18,13 +18,7 @@ all: $(patsubst %,%.h,$(ELFS))
        $(OBJCOPY) -O binary --only-section .text $^ $@
 
 debug_rom:     $(DEPS)
-       $(COMPILE) -DRV32 -DRV64 -o $@ $^
-
-debug_rom32:   $(DEPS)
-       $(COMPILE) -DRV32 -DDEBUG_RAM_SIZE=28 -o $@ $^
-
-debug_rom64:   $(DEPS)
-       $(COMPILE) -DRV64 -o $@ $^
+       $(COMPILE) -o $@ $^
 
 clean:
        rm -f $(ELFS) debug_rom*.raw debug_rom*.h
index 74a934b201a94a31be63b24dd7c68a1149dcdecc..8f7be00634cb6c11f02807e053a766adc4ab3fb8 100755 (executable)
-# This code should be functional. Doesn't have to be optimal.
-# I'm writing it to prove that it can be done.
+// See LICENSE.SiFive for license details.
 
-#include "riscv/encoding.h"
+#include "spike/encoding.h"
 
-# TODO: Update these constants once they're finalized in the doc.
+// These are implementation-specific addresses in the Debug Module
+#define HALTED    0x100
+#define GOING     0x104
+#define RESUMING  0x108
+#define EXCEPTION 0x10C
 
-#define DEBUG_RAM               0x400
-#ifndef DEBUG_RAM_SIZE
-# define DEBUG_RAM_SIZE          64
-#endif
-
-#define CLEARDEBINT             0x100
-#define SETHALTNOT              0x10c
-
-#if (defined(RV32) + defined(RV64) + defined(RV128)) > 1
-# define MULTI_XLEN
-#elif (defined(RV32) + defined(RV64) + defined(RV128)) == 0
-# error define one or more of RV32, RV64, RV128
-#endif
+// Region of memory where each hart has 1
+// byte to read.
+#define FLAGS 0x400
+#define FLAG_GO     0
+#define FLAG_RESUME 1
 
+        .option norvc
         .global entry
-        .global resume
         .global exception
 
-        # Automatically called when Debug Mode is first entered.
-entry:  j       _entry
-        # Should be called by Debug RAM code that has finished execution and
-        # wants to return to Debug Mode.
+        // Entry location on ebreak, Halt, or Breakpoint
+        // It is the same for all harts. They branch when 
+        // their GO or RESUME bit is set.
+
+entry:
+       jal zero, _entry
 resume:
-        j       _resume
+       jal zero, _resume
 exception:
-        # Set the last word of Debug RAM to all ones, to indicate that we hit
-        # an exception.
-        li      s0, ~0
-        j       _resume2
+       jal zero, _exception
 
-_resume:
-        li      s0, 0
-_resume2:
+_entry:
+        // This fence is required because the execution may have written something
+        // into the Abstract Data or Program Buffer registers.
         fence
-
-        # Restore s1.
-#ifdef MULTI_XLEN
-        csrr    s1, CSR_MISA
-#endif
-
-#ifdef RV32
-# ifdef MULTI_XLEN
-        bltz    s1, restore_not_32
-# endif
-
-restore_32:
-        lw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-# if defined(RV64) || defined(RV128)
-        j       finish_restore
-# endif
-#endif
-
-restore_not_32:
-#if defined(RV64) && defined(RV128)
-        slli    s1, s1, 1
-        bltz    s1, restore_128
-#endif
-
-#ifdef RV64
-restore_64:
-        ld      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
-#endif
-#if defined(RV64) && defined(RV128)
-        j       finish_restore
-#endif
-#ifdef RV128
-restore_128:
-        lq      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
-#endif
-
-finish_restore:
-        # s0 contains ~0 if we got here through an exception, and 0 otherwise.
-        # Store this to the last word in Debug RAM so the debugger can tell if
-        # an exception occurred.
-        sw      s0, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-
-        # Clear debug interrupt.
-        csrr    s0, CSR_MHARTID
-        sw      s0, CLEARDEBINT(zero)
-
-check_halt:
-        csrr    s0, CSR_DCSR
-        andi    s0, s0, DCSR_HALT
-        bnez    s0, wait_for_interrupt
-
-exit:
-        # Restore s0.
-        csrr    s0, CSR_DSCRATCH
+        csrw CSR_DSCRATCH, s0  // Save s0 to allow signaling MHARTID
+
+        // We continue to let the hart know that we are halted in order that
+        // a DM which was reset is still made aware that a hart is halted.
+        // We keep checking both whether there is something the debugger wants
+        // us to do, or whether we should resume.
+entry_loop:
+        csrr s0, CSR_MHARTID
+        sw   s0, HALTED(zero)
+        lbu  s0, FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
+        andi s0, s0, (1 << FLAG_GO)
+        bnez s0, going
+        csrr s0, CSR_MHARTID
+        lbu  s0, FLAGS(s0) // multiple harts can resume  here
+        andi s0, s0, (1 << FLAG_RESUME)
+        bnez s0, resume
+        jal  zero, entry_loop
+
+_exception:
+        sw      zero, EXCEPTION(zero) // Let debug module know you got an exception.
+        ebreak
+
+going:
+        csrr s0, CSR_DSCRATCH          // Restore s0 here
+        sw zero, GOING(zero)           // When debug module sees this write, the GO flag is reset.
+        jalr zero, zero, %lo(whereto)          // Rocket-Chip has a specific hack which is that jalr in
+                                       // Debug Mode will flush the I-Cache. We need that so that the
+                                       // remainder of the variable instructions will be what Debug Module
+                                       // intends.
+_resume:
+        csrr s0, CSR_MHARTID
+        sw   s0, RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
+        csrr s0, CSR_DSCRATCH   // Restore s0
         dret
 
-_entry:
-        # Save s0 in DSCRATCH
-        csrw    CSR_DSCRATCH, s0
-
-        # Check why we're here
-        csrr    s0, CSR_DCSR
-        # cause is in bits 8:6 of dcsr
-        andi    s0, s0, DCSR_CAUSE
-        addi    s0, s0, -(DCSR_CAUSE_DEBUGINT<<6)
-        bnez    s0, spontaneous_halt
-
-jdebugram:
-        # Save s1 so that the debug program can use two registers.
-#ifdef MULTI_XLEN
-        csrr    s0, CSR_MISA
-#endif
-
-#ifdef RV32
-# ifdef MULTI_XLEN
-        bltz    s0, save_not_32
-# endif
-save_32:
-        sw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
-        jr      zero, DEBUG_RAM
-#endif
-
-save_not_32:
-#if defined(RV64) && defined(RV128)
-        slli    s0, s0, 1
-        bltz    s0, save_128
-#endif
-
-#ifdef RV64
-save_64:
-        sd      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 8)(zero)
-        jr      zero, DEBUG_RAM
-#endif
-
-#ifdef RV128
-save_128:
-        sq      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 16)(zero)
-        jr      zero, DEBUG_RAM
-#endif
-
-spontaneous_halt:
-        csrr    s0, CSR_MHARTID
-        sw      s0, SETHALTNOT(zero)
-        csrsi   CSR_DCSR, DCSR_HALT
-
-wait_for_interrupt:
-        csrr    s0, CSR_DCSR
-        andi    s0, s0, DCSR_DEBUGINT
-        beqz    s0, wait_for_interrupt
-
-        j       jdebugram
+        // END OF ACTUAL "ROM" CONTENTS. BELOW IS JUST FOR LINKER SCRIPT.
+
+.section .whereto
+whereto:
+        nop
+        // Variable "ROM" This is : jal x0 abstract, jal x0 program_buffer,
+        //                or jal x0 resume, as desired.
+        //                Debug Module state machine tracks what is 'desired'.
+        //                We don't need/want to use jalr here because all of the
+        //                Variable ROM contents are set by
+        //                Debug Module before setting the OK_GO byte.
index b1e3beaef653d5d91de4b8a9dc942add69ef0d79..f389bf8edbfdcdf069b59459f4c6e839248c9bfe 100644 (file)
@@ -1,16 +1,11 @@
 static const unsigned char debug_rom_raw[] = {
-  0x6f, 0x00, 0xc0, 0x04, 0x6f, 0x00, 0xc0, 0x00, 0x13, 0x04, 0xf0, 0xff,
-  0x6f, 0x00, 0x80, 0x00, 0x13, 0x04, 0x00, 0x00, 0x0f, 0x00, 0xf0, 0x0f,
-  0xf3, 0x24, 0x10, 0x30, 0x63, 0xc6, 0x04, 0x00, 0x83, 0x24, 0xc0, 0x43,
-  0x6f, 0x00, 0x80, 0x00, 0x83, 0x34, 0x80, 0x43, 0x23, 0x2e, 0x80, 0x42,
-  0x73, 0x24, 0x40, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x73, 0x24, 0x00, 0x7b,
-  0x13, 0x74, 0x84, 0x00, 0x63, 0x12, 0x04, 0x04, 0x73, 0x24, 0x20, 0x7b,
-  0x73, 0x00, 0x20, 0x7b, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x00, 0x7b,
-  0x13, 0x74, 0x04, 0x1c, 0x13, 0x04, 0x04, 0xf4, 0x63, 0x1e, 0x04, 0x00,
-  0x73, 0x24, 0x10, 0x30, 0x63, 0x46, 0x04, 0x00, 0x23, 0x2e, 0x90, 0x42,
-  0x67, 0x00, 0x00, 0x40, 0x23, 0x3c, 0x90, 0x42, 0x67, 0x00, 0x00, 0x40,
-  0x73, 0x24, 0x40, 0xf1, 0x23, 0x26, 0x80, 0x10, 0x73, 0x60, 0x04, 0x7b,
-  0x73, 0x24, 0x00, 0x7b, 0x13, 0x74, 0x04, 0x02, 0xe3, 0x0c, 0x04, 0xfe,
-  0x6f, 0xf0, 0x1f, 0xfd
+  0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0xc0, 0x04, 0x6f, 0x00, 0x40, 0x03,
+  0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1,
+  0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00,
+  0x63, 0x10, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40,
+  0x13, 0x74, 0x24, 0x00, 0xe3, 0x18, 0x04, 0xfc, 0x6f, 0xf0, 0xdf, 0xfd,
+  0x23, 0x26, 0x00, 0x10, 0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x20, 0x7b,
+  0x23, 0x22, 0x00, 0x10, 0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1,
+  0x23, 0x24, 0x80, 0x10, 0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b
 };
-static const unsigned int debug_rom_raw_len = 148;
+static const unsigned int debug_rom_raw_len = 96;
index aba6ae802e13f23a2c8edaf656f8535255a0fd53..897c42da001d1009bceb3bee32a83b7693d019cd 100644 (file)
@@ -2,6 +2,10 @@ OUTPUT_ARCH( "riscv" )
 ENTRY( entry )
 SECTIONS
 {
+    .whereto 0x300 :
+    {
+        *(.whereto)
+    }   
     . = 0x800;
     .text :
     {