Compare commits

...

2 commits

Author SHA1 Message Date
c9ad69a32d
nemu: break before executing instruction
Some checks failed
Build abstract machine with nix / build-abstract-machine (push) Failing after 45s
Run CTests within npc / npc-test (push) Failing after 47s
2024-07-25 17:56:30 +08:00
385d448746
abstract-machine(nemu): support context switch 2024-07-25 17:16:41 +08:00
23 changed files with 238 additions and 89 deletions

2
.gitmodules vendored
View file

@ -4,4 +4,4 @@
branch = dev branch = dev
[submodule "diffu"] [submodule "diffu"]
path = diffu path = diffu
url = https://git.xinyang.life/xin/diffu.git url = git@github.com:xinyangli/diffu.git

View file

@ -76,7 +76,8 @@ target_include_directories(
INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/include> INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/include>
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/src> $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_definitions(am_interface INTERFACE ARCH_H=<arch/${ISA}.h>) target_compile_definitions(am_interface INTERFACE ARCH_H=<arch/${ISA}.h>
"__ISA__=\"${ISA}\"")
file(GLOB_RECURSE AM_HEADERS "${CMAKE_SOURCE_DIR}/am/include/*.h") file(GLOB_RECURSE AM_HEADERS "${CMAKE_SOURCE_DIR}/am/include/*.h")
target_sources( target_sources(
am_interface am_interface

View file

@ -1,5 +1,6 @@
#ifndef ARCH_H__ #ifndef ARCH_H__
#define ARCH_H__ #define ARCH_H__
#include <stdint.h>
#ifdef __riscv_e #ifdef __riscv_e
#define NR_REGS 16 #define NR_REGS 16
@ -9,10 +10,13 @@
struct Context { struct Context {
// TODO: fix the order of these members to match trap.S // TODO: fix the order of these members to match trap.S
uintptr_t mepc, mcause, gpr[NR_REGS], mstatus; uintptr_t gpr[NR_REGS];
uintptr_t mcause, mstatus, mepc;
void *pdir; void *pdir;
}; };
enum Cause { CauseEnvironmentCallFromMMode = 11 };
#ifdef __riscv_e #ifdef __riscv_e
#define GPR1 gpr[15] // a5 #define GPR1 gpr[15] // a5
#else #else

View file

@ -6,7 +6,7 @@ int main(const char *args);
Area heap = RANGE(&_heap_start, PMEM_END); Area heap = RANGE(&_heap_start, PMEM_END);
#ifndef MAINARGS #ifndef MAINARGS
#define MAINARGS "5" #define MAINARGS "i"
#endif #endif
static const char mainargs[] = MAINARGS; static const char mainargs[] = MAINARGS;

View file

@ -1,6 +1,8 @@
#include "arch/riscv.h"
#include <am.h> #include <am.h>
#include <riscv/riscv.h>
#include <klib.h> #include <klib.h>
#include <riscv/riscv.h>
#include <stdint.h>
static Context *(*user_handler)(Event, Context *) = NULL; static Context *(*user_handler)(Event, Context *) = NULL;
@ -8,7 +10,12 @@ Context* __am_irq_handle(Context *c) {
if (user_handler) { if (user_handler) {
Event ev = {0}; Event ev = {0};
switch (c->mcause) { switch (c->mcause) {
default: ev.event = EVENT_ERROR; break; case CauseEnvironmentCallFromMMode:
ev.event = EVENT_YIELD;
break;
default:
ev.event = EVENT_ERROR;
break;
} }
c = user_handler(ev, c); c = user_handler(ev, c);
@ -31,7 +38,10 @@ bool cte_init(Context*(*handler)(Event, Context*)) {
} }
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) { Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
return NULL; Context *c = kstack.end - sizeof(Context);
c->mepc = (uintptr_t)entry;
c->gpr[10] = (uintptr_t)arg;
return c;
} }
void yield() { void yield() {
@ -42,9 +52,6 @@ void yield() {
#endif #endif
} }
bool ienabled() { bool ienabled() { return false; }
return false;
}
void iset(bool enable) { void iset(bool enable) {}
}

View file

@ -60,6 +60,8 @@ __am_asm_trap:
mv a0, sp mv a0, sp
jal __am_irq_handle jal __am_irq_handle
mv sp, a0
LOAD t1, OFFSET_STATUS(sp) LOAD t1, OFFSET_STATUS(sp)
LOAD t2, OFFSET_EPC(sp) LOAD t2, OFFSET_EPC(sp)
csrw mstatus, t1 csrw mstatus, t1

View file

@ -15,6 +15,9 @@ stdenv.mkDerivation {
(lib.cmakeFeature "ISA" isa) (lib.cmakeFeature "ISA" isa)
] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform; ] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform;
cmakeBuildType = "Debug";
dontStrip = true;
nativeBuildInputs = [ nativeBuildInputs = [
cmake cmake
]; ];

@ -1 +1 @@
Subproject commit 02b38e7b44f673f808abcb3bf9464811f8c58d4b Subproject commit 8c4ea046225e2dce599dc36aeef6c4c857996d00

View file

@ -128,11 +128,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1721457008, "lastModified": 1721891452,
"narHash": "sha256-ekpve0om5hzC1Ntd3zm1cZ9oS5pnr7a2n/tueyqFOsg=", "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "e7aa3319d52fa987ac2192f63aef3dcb1b057e3a", "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570",
"revCount": 151, "revCount": 152,
"type": "git", "type": "git",
"url": "https://git.xinyang.life/xin/nur.git" "url": "https://git.xinyang.life/xin/nur.git"
}, },

View file

@ -64,13 +64,14 @@
abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; }; abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; };
am-kernels-npc = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-npc"; }; am-kernels-npc = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-npc"; };
am-kernels-nemu = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-nemu"; }; am-kernels-nemu = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-nemu"; };
am-kernels = rv32CrossConfig.callPackage ./am-kernels { abstract-machine = abstract-machine; arch = "riscv"; };
}; };
}; };
devShells.nemu = pkgs.mkShell { devShells.nemu = pkgs.mkShell {
packages = with pkgs; [ packages = with pkgs; [
clang-tools clang-tools
gdb gef
SDL2 SDL2
gnumake gnumake
pkg-config pkg-config

1
nemu/.gitignore vendored
View file

@ -9,6 +9,7 @@ build/
.envrc .envrc
.metals/ .metals/
.vscode/ .vscode/
.zed/
compile_commands.json compile_commands.json
### C ### ### C ###

View file

@ -20,7 +20,14 @@
// ----------- state ----------- // ----------- state -----------
enum { NEMU_RUNNING, NEMU_STOP, NEMU_END, NEMU_ABORT, NEMU_QUIT }; enum {
NEMU_RUNNING,
NEMU_GDB_INTERRUPT,
NEMU_STOP,
NEMU_END,
NEMU_ABORT,
NEMU_QUIT
};
typedef struct { typedef struct {
int state; int state;
@ -56,16 +63,16 @@ uint64_t get_time();
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE #define ANSI_FMT(str, fmt) fmt str ANSI_NONE
#define log_write(...) IFDEF(CONFIG_TARGET_NATIVE_ELF, \ #define log_write(...) \
do { \ IFDEF( \
CONFIG_TARGET_NATIVE_ELF, do { \
extern FILE *log_fp; \ extern FILE *log_fp; \
extern bool log_enable(); \ extern bool log_enable(); \
if (log_enable()) { \ if (log_enable()) { \
fprintf(log_fp, __VA_ARGS__); \ fprintf(log_fp, __VA_ARGS__); \
fflush(log_fp); \ fflush(log_fp); \
} \ } \
} while (0) \ } while (0))
)
#define _Log(...) \ #define _Log(...) \
do { \ do { \
@ -73,5 +80,4 @@ uint64_t get_time();
log_write(__VA_ARGS__); \ log_write(__VA_ARGS__); \
} while (0) } while (0)
#endif #endif

View file

@ -158,8 +158,6 @@ breakpoint_t *cpu_exec_with_bp(uint64_t n, breakpoint_t *bp, size_t len) {
static Decode s; static Decode s;
nemu_state.state = NEMU_RUNNING; nemu_state.state = NEMU_RUNNING;
do { do {
exec_once(&s, cpu.pc);
g_nr_guest_inst++;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
size_t addr = bp[i].addr; size_t addr = bp[i].addr;
bp_type_t bptype = bp[i].type; bp_type_t bptype = bp[i].type;
@ -176,6 +174,8 @@ breakpoint_t *cpu_exec_with_bp(uint64_t n, breakpoint_t *bp, size_t len) {
return bp + i; return bp + i;
} }
} }
exec_once(&s, cpu.pc);
g_nr_guest_inst++;
if (nemu_state.state != NEMU_RUNNING) if (nemu_state.state != NEMU_RUNNING)
return NULL; return NULL;
} while (--n); } while (--n);

View file

@ -13,7 +13,10 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
***************************************************************************************/ ***************************************************************************************/
#include <assert.h>
#include <debug.h>
#include <device/map.h> #include <device/map.h>
#include <generated/autoconf.h>
#include <utils.h> #include <utils.h>
#define KEYDOWN_MASK 0x8000 #define KEYDOWN_MASK 0x8000
@ -23,27 +26,26 @@
// Note that this is not the standard // Note that this is not the standard
#define NEMU_KEYS(f) \ #define NEMU_KEYS(f) \
f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) f(F11) f(F12) \ f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) \
f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) f(MINUS) f(EQUALS) f(BACKSPACE) \ f(F11) f(F12) f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) \
f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \ f(MINUS) f(EQUALS) f(BACKSPACE) f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) \
f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) f(SEMICOLON) f(APOSTROPHE) f(RETURN) \ f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
f(LSHIFT) f(Z) f(X) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) f(RSHIFT) \ f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) \
f(LCTRL) f(APPLICATION) f(LALT) f(SPACE) f(RALT) f(RCTRL) \ f(SEMICOLON) f(APOSTROPHE) f(RETURN) f(LSHIFT) f(Z) f(X) \
f(UP) f(DOWN) f(LEFT) f(RIGHT) f(INSERT) f(DELETE) f(HOME) f(END) f(PAGEUP) f(PAGEDOWN) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) \
f(RSHIFT) f(LCTRL) f(APPLICATION) f(LALT) \
f(SPACE) f(RALT) f(RCTRL) f(UP) f(DOWN) \
f(LEFT) f(RIGHT) f(INSERT) f(DELETE) \
f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)
#define NEMU_KEY_NAME(k) NEMU_KEY_##k, #define NEMU_KEY_NAME(k) NEMU_KEY_##k,
enum { enum { NEMU_KEY_NONE = 0, MAP(NEMU_KEYS, NEMU_KEY_NAME) };
NEMU_KEY_NONE = 0,
MAP(NEMU_KEYS, NEMU_KEY_NAME)
};
#define SDL_KEYMAP(k) keymap[SDL_SCANCODE_##k] = NEMU_KEY_##k; #define SDL_KEYMAP(k) keymap[SDL_SCANCODE_##k] = NEMU_KEY_##k;
static uint32_t keymap[256] = {}; static uint32_t keymap[256] = {};
static void init_keymap() { static void init_keymap() { MAP(NEMU_KEYS, SDL_KEYMAP) }
MAP(NEMU_KEYS, SDL_KEYMAP)
}
#define KEY_QUEUE_LEN 1024 #define KEY_QUEUE_LEN 1024
static int key_queue[KEY_QUEUE_LEN] = {}; static int key_queue[KEY_QUEUE_LEN] = {};
@ -92,9 +94,11 @@ void init_i8042() {
i8042_data_port_base = (uint32_t *)new_space(4); i8042_data_port_base = (uint32_t *)new_space(4);
i8042_data_port_base[0] = NEMU_KEY_NONE; i8042_data_port_base[0] = NEMU_KEY_NONE;
#ifdef CONFIG_HAS_PORT_IO #ifdef CONFIG_HAS_PORT_IO
add_pio_map ("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4, i8042_data_io_handler); add_pio_map("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4,
i8042_data_io_handler);
#else #else
add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4, i8042_data_io_handler); add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4,
i8042_data_io_handler);
#endif #endif
IFNDEF(CONFIG_TARGET_AM, init_keymap()); IFNDEF(CONFIG_TARGET_AM, init_keymap());
} }

View file

@ -16,6 +16,7 @@
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <device/map.h> #include <device/map.h>
#include <generated/autoconf.h>
#include <utils.h> #include <utils.h>
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */ /* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */

View file

@ -16,6 +16,7 @@
#include <assert.h> #include <assert.h>
#include <device/alarm.h> #include <device/alarm.h>
#include <device/map.h> #include <device/map.h>
#include <generated/autoconf.h>
#include <utils.h> #include <utils.h>
static uint32_t *rtc_port_base = NULL; static uint32_t *rtc_port_base = NULL;

View file

@ -0,0 +1,18 @@
#include <csr.h>
void init_csr(csr_t csr) { memset(csr, 0, sizeof(word_t)); }
void write_csr(csr_t csr, csr_addr_t csrnum, word_t value) {
switch (csrnum) {
default:
csr[csrnum] = value;
}
}
word_t read_csr(csr_t csr, csr_addr_t csrnum) {
switch (csrnum) {
// TODO: Implement csr read checks
default:
return csr[csrnum];
}
}

View file

@ -18,9 +18,13 @@
#include <common.h> #include <common.h>
#define CSR_SIZE (0x1000)
typedef word_t csr_t[CSR_SIZE];
typedef struct { typedef struct {
word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)]; word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)];
// word_t csr[MUXDEF(CONFIG_RVE, )] csr_t csr;
vaddr_t pc; vaddr_t pc;
} MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state); } MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state);

View file

@ -13,6 +13,7 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
***************************************************************************************/ ***************************************************************************************/
#include "isa.h"
#include "local-include/reg.h" #include "local-include/reg.h"
#include "macro.h" #include "macro.h"
#include "types.h" #include "types.h"
@ -20,6 +21,7 @@
#include <cpu/cpu.h> #include <cpu/cpu.h>
#include <cpu/decode.h> #include <cpu/decode.h>
#include <cpu/ifetch.h> #include <cpu/ifetch.h>
#include <csr.h>
#include <ftrace.h> #include <ftrace.h>
#include <utils.h> #include <utils.h>
@ -33,6 +35,8 @@ enum {
TYPE_S, TYPE_S,
TYPE_B, TYPE_B,
TYPE_J, TYPE_J,
TYPE_CSR,
TYPE_CSRI,
TYPE_N, // none TYPE_N, // none
}; };
@ -66,6 +70,14 @@ enum {
*imm = SEXT(BITS(i, 31, 31), 1) << 20 | BITS(i, 30, 21) << 1 | \ *imm = SEXT(BITS(i, 31, 31), 1) << 20 | BITS(i, 30, 21) << 1 | \
BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; \ BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; \
} while (0) } while (0)
#define csr() \
do { \
*src2 = BITS(i, 31, 20); \
} while (0)
#define uimm() \
do { \
*imm = BITS(i, 19, 15); \
} while (0)
static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2, static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
word_t *imm, int type) { word_t *imm, int type) {
@ -98,6 +110,14 @@ static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
src2R(); src2R();
immB(); immB();
break; break;
case TYPE_CSR:
src1R();
csr();
break;
case TYPE_CSRI:
csr();
uimm();
break;
} }
} }
@ -249,6 +269,44 @@ static int decode_exec(Decode *s) {
INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu, R, INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu, R,
R(rd) = src1 % src2); R(rd) = src1 % src2);
// "Previledge"
// -- CSR instructions
INSTPAT(
"??????? ????? ????? 001 ????? 11100 11", csrrw, CSR, do {
R(rd) = read_csr(cpu.csr, src2);
write_csr(cpu.csr, src2, src1);
} while (0););
INSTPAT(
"??????? ????? ????? 010 ????? 11100 11", csrrs, CSR, do {
R(rd) = read_csr(cpu.csr, src2);
set_csr_bits(cpu.csr, src2, src1);
} while (0););
INSTPAT(
"??????? ????? ????? 011 ????? 11100 11", csrrc, CSR, do {
R(rd) = read_csr(cpu.csr, src2);
clear_csr_bits(cpu.csr, src2, src1);
} while (0););
INSTPAT(
"??????? ????? ????? 101 ????? 11100 11", csrrwi, CSRI, do {
R(rd) = read_csr(cpu.csr, src2);
write_csr(cpu.csr, src2, imm);
} while (0););
INSTPAT(
"??????? ????? ????? 110 ????? 11100 11", csrrsi, CSRI, do {
R(rd) = read_csr(cpu.csr, src2);
set_csr_bits(cpu.csr, src2, imm);
} while (0););
INSTPAT(
"??????? ????? ????? 111 ????? 11100 11", csrrci, CSRI, do {
R(rd) = read_csr(cpu.csr, src2);
clear_csr_bits(cpu.csr, src2, imm);
} while (0););
// -- Machine level
INSTPAT("0000000 00000 00000 000 00000 11100 11", ecall, N,
s->dnpc = isa_raise_intr(CauseEnvironmentCallFromMMode, cpu.pc));
INSTPAT("0011000 00010 00000 000 00000 11100 11", mret, N,
s->dnpc = read_csr(cpu.csr, MEPC));
INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv, N, INV(s->pc)); INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv, N, INV(s->pc));
INSTPAT_END(); INSTPAT_END();

View file

@ -0,0 +1,29 @@
#ifndef __NEMU_CSR_H__
#define __NEMU_CSR_H__
#include <isa-def.h>
#include <types.h>
#define MSTATUS 0x300
#define MISA 0x301
#define MIE 0x304
#define MTVEC 0x305
#define MEPC 0x341
#define MCAUSE 0x342
enum { CauseEnvironmentCallFromMMode = 11 };
typedef uint16_t csr_addr_t;
void init_csr(csr_t csr);
/* macro for setting and clearing csr bits */
#define set_csr_bits(csr, reg, mask) \
write_csr(csr, reg, read_csr(csr, reg) | (mask))
#define clear_csr_bits(csr, reg, mask) \
write_csr(csr, reg, read_csr(csr, reg) & ~(mask))
void write_csr(csr_t csr, csr_addr_t csrnum, word_t value);
word_t read_csr(csr_t csr, csr_addr_t csrnum);
#endif // __NEMU_CSR_H__

View file

@ -14,6 +14,7 @@
***************************************************************************************/ ***************************************************************************************/
#include "local-include/reg.h" #include "local-include/reg.h"
#include "csr.h"
#include "macro.h" #include "macro.h"
#include <errno.h> #include <errno.h>
#include <gdbstub.h> #include <gdbstub.h>
@ -51,11 +52,13 @@ word_t isa_reg_str2val(const char *s, bool *success) {
} }
int isa_read_reg(void *args, int regno, size_t *reg_value) { int isa_read_reg(void *args, int regno, size_t *reg_value) {
if (regno > 32) { if (regno > 33) {
return EFAULT; return EFAULT;
} }
if (regno == 32) { if (regno == 33) {
*reg_value = cpu.csr[MTVEC];
} else if (regno == 32) {
*reg_value = cpu.pc; *reg_value = cpu.pc;
} else { } else {
*reg_value = cpu.gpr[regno]; *reg_value = cpu.gpr[regno];
@ -64,11 +67,13 @@ int isa_read_reg(void *args, int regno, size_t *reg_value) {
} }
int isa_write_reg(void *args, int regno, size_t data) { int isa_write_reg(void *args, int regno, size_t data) {
if (regno > 32) { if (regno > 33) {
return EFAULT; return EFAULT;
} }
if (regno == 32) { if (regno == 33) {
cpu.csr[MTVEC] = data;
} else if (regno == 32) {
cpu.pc = data; cpu.pc = data;
} else { } else {
cpu.gpr[regno] = data; cpu.gpr[regno] = data;
@ -76,6 +81,6 @@ int isa_write_reg(void *args, int regno, size_t data) {
return 0; return 0;
} }
__EXPORT arch_info_t isa_arch_info = {.reg_num = 32, __EXPORT arch_info_t isa_arch_info = {.reg_num = 33,
.reg_byte = MUXDEF(CONFIG_RV64, 8, 4), .reg_byte = MUXDEF(CONFIG_RV64, 8, 4),
.target_desc = TARGET_RV32}; .target_desc = TARGET_RV32};

View file

@ -13,16 +13,14 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
***************************************************************************************/ ***************************************************************************************/
#include <csr.h>
#include <isa.h> #include <isa.h>
word_t isa_raise_intr(word_t NO, vaddr_t epc) { word_t isa_raise_intr(word_t NO, vaddr_t epc) {
/* TODO: Trigger an interrupt/exception with ``NO''. write_csr(cpu.csr, MEPC, epc);
* Then return the address of the interrupt/exception vector. write_csr(cpu.csr, MCAUSE, NO);
*/
return 0; return read_csr(cpu.csr, MTVEC);
} }
word_t isa_query_intr() { word_t isa_query_intr() { return INTR_EMPTY; }
return INTR_EMPTY;
}

View file

@ -59,6 +59,11 @@ static void nemu_is_stopped(gdb_action_t *act, breakpoint_t *stopped_at) {
} }
break; break;
case NEMU_GDB_INTERRUPT:
act->reason = gdb_action_t::ACT_BREAKPOINT;
act->data = cpu.pc;
break;
default: default:
act->reason = gdb_action_t::ACT_SHUTDOWN; act->reason = gdb_action_t::ACT_SHUTDOWN;
act->data = nemu_state.halt_ret; act->data = nemu_state.halt_ret;
@ -103,7 +108,7 @@ __EXPORT bool nemu_del_bp(void *args, size_t addr, bp_type_t type) {
} }
__EXPORT void nemu_on_interrupt(void *args) { __EXPORT void nemu_on_interrupt(void *args) {
// fputs("Not implemented", stderr); nemu_state.state = NEMU_GDB_INTERRUPT;
} }
__EXPORT int nemu_read_reg(void *args, int regno, size_t *data) { __EXPORT int nemu_read_reg(void *args, int regno, size_t *data) {
@ -121,7 +126,8 @@ static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont,
.write_mem = nemu_write_mem, .write_mem = nemu_write_mem,
.set_bp = nemu_set_bp, .set_bp = nemu_set_bp,
.del_bp = nemu_del_bp, .del_bp = nemu_del_bp,
.on_interrupt = NULL}; .on_interrupt = nemu_on_interrupt,
.monitor = NULL};
static DbgState *pdbg; static DbgState *pdbg;
static gdbstub_t gdbstub_priv; static gdbstub_t gdbstub_priv;
const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock"; const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock";
@ -152,7 +158,7 @@ __EXPORT void nemu_init(void *args) {
int gdbstub_loop() { int gdbstub_loop() {
if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops, if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops,
(arch_info_t)isa_arch_info, SOCKET_ADDR)) { (arch_info_t)isa_arch_info, NULL, SOCKET_ADDR)) {
return EINVAL; return EINVAL;
} }
printf("Waiting for gdb connection at %s", SOCKET_ADDR); printf("Waiting for gdb connection at %s", SOCKET_ADDR);