refactor: drop internal difftest support
This commit is contained in:
parent
f852ee8689
commit
422ff9e006
21 changed files with 192 additions and 433 deletions
0
nemu/.result.tmp
Normal file
0
nemu/.result.tmp
Normal file
|
@ -1,9 +1,9 @@
|
||||||
{ pkgs,
|
{ pkgs,
|
||||||
lib,
|
lib,
|
||||||
stdenv,
|
stdenv,
|
||||||
am-kernels,
|
|
||||||
dtc,
|
dtc,
|
||||||
mini-gdbstub,
|
mini-gdbstub,
|
||||||
|
am-kernels ? null,
|
||||||
defconfig ? "alldefconfig",
|
defconfig ? "alldefconfig",
|
||||||
}:
|
}:
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ stdenv.mkDerivation rec {
|
||||||
make
|
make
|
||||||
'';
|
'';
|
||||||
|
|
||||||
doCheck = (defconfig == "alldefconfig");
|
doCheck = (am-kernels != null);
|
||||||
checkPhase = if doCheck then ''
|
checkPhase = if doCheck then ''
|
||||||
export NEMU_IMAGES_PATH=${am-kernels}/share/am-kernels
|
export NEMU_IMAGES_PATH=${am-kernels}/share/am-kernels
|
||||||
make test
|
make test
|
||||||
|
|
9
nemu/include/config.h
Normal file
9
nemu/include/config.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __NEMU_CONFIG_H__
|
||||||
|
#define __NEMU_CONFIG_H__
|
||||||
|
|
||||||
|
extern char *log_file = NULL;
|
||||||
|
extern char *elf_file = NULL;
|
||||||
|
extern char *img_file = NULL;
|
||||||
|
extern bool enable_gdbstub = false;
|
||||||
|
|
||||||
|
#endif // __NEMU_CONFIG_H__
|
|
@ -1,53 +0,0 @@
|
||||||
/***************************************************************************************
|
|
||||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
||||||
*
|
|
||||||
* NEMU is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
***************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __CPU_DIFFTEST_H__
|
|
||||||
#define __CPU_DIFFTEST_H__
|
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <difftest-def.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_DIFFTEST
|
|
||||||
void difftest_skip_ref();
|
|
||||||
void difftest_skip_dut(int nr_ref, int nr_dut);
|
|
||||||
void difftest_set_patch(void (*fn)(void *arg), void *arg);
|
|
||||||
void difftest_step(vaddr_t pc, vaddr_t npc);
|
|
||||||
void difftest_detach();
|
|
||||||
void difftest_attach();
|
|
||||||
#else
|
|
||||||
static inline void difftest_skip_ref() {}
|
|
||||||
static inline void difftest_skip_dut(int nr_ref, int nr_dut) {}
|
|
||||||
static inline void difftest_set_patch(void (*fn)(void *arg), void *arg) {}
|
|
||||||
static inline void difftest_step(vaddr_t pc, vaddr_t npc) {}
|
|
||||||
static inline void difftest_detach() {}
|
|
||||||
static inline void difftest_attach() {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction);
|
|
||||||
extern void (*ref_difftest_regcpy)(void *dut, bool direction);
|
|
||||||
extern void (*ref_difftest_exec)(uint64_t n);
|
|
||||||
extern void (*ref_difftest_raise_intr)(uint64_t NO);
|
|
||||||
|
|
||||||
static inline bool difftest_check_reg(const char *name, vaddr_t pc, word_t ref, word_t dut) {
|
|
||||||
if (ref != dut) {
|
|
||||||
Log("%s is different after executing instruction at pc = " FMT_WORD
|
|
||||||
", right = " FMT_WORD ", wrong = " FMT_WORD ", diff = " FMT_WORD,
|
|
||||||
name, pc, ref, dut, ref ^ dut);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -16,10 +16,12 @@
|
||||||
#ifndef __DEVICE_MAP_H__
|
#ifndef __DEVICE_MAP_H__
|
||||||
#define __DEVICE_MAP_H__
|
#define __DEVICE_MAP_H__
|
||||||
|
|
||||||
#include <cpu/difftest.h>
|
#include <difftest.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
typedef void(*io_callback_t)(uint32_t, int, bool);
|
typedef void (*io_callback_t)(uint32_t, int, bool);
|
||||||
uint8_t* new_space(int size);
|
uint8_t *new_space(int size);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -36,19 +38,19 @@ static inline bool map_inside(IOMap *map, paddr_t addr) {
|
||||||
|
|
||||||
static inline int find_mapid_by_addr(IOMap *maps, int size, paddr_t addr) {
|
static inline int find_mapid_by_addr(IOMap *maps, int size, paddr_t addr) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < size; i ++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (map_inside(maps + i, addr)) {
|
if (map_inside(maps + i, addr)) {
|
||||||
difftest_skip_ref();
|
nemu_do_difftest = false;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_pio_map(const char *name, ioaddr_t addr,
|
void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len,
|
||||||
void *space, uint32_t len, io_callback_t callback);
|
io_callback_t callback);
|
||||||
void add_mmio_map(const char *name, paddr_t addr,
|
void add_mmio_map(const char *name, paddr_t addr, void *space, uint32_t len,
|
||||||
void *space, uint32_t len, io_callback_t callback);
|
io_callback_t callback);
|
||||||
|
|
||||||
word_t map_read(paddr_t addr, int len, IOMap *map);
|
word_t map_read(paddr_t addr, int len, IOMap *map);
|
||||||
void map_write(paddr_t addr, int len, word_t data, IOMap *map);
|
void map_write(paddr_t addr, int len, word_t data, IOMap *map);
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
/***************************************************************************************
|
|
||||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
||||||
*
|
|
||||||
* NEMU is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
***************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __DIFFTEST_DEF_H__
|
|
||||||
#define __DIFFTEST_DEF_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <macro.h>
|
|
||||||
#include <generated/autoconf.h>
|
|
||||||
|
|
||||||
#define __EXPORT __attribute__((visibility("default")))
|
|
||||||
enum { DIFFTEST_TO_DUT, DIFFTEST_TO_REF };
|
|
||||||
|
|
||||||
#if defined(CONFIG_ISA_x86)
|
|
||||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GPRs + pc
|
|
||||||
#elif defined(CONFIG_ISA_mips32)
|
|
||||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 38) // GPRs + status + lo + hi + badvaddr + cause + pc
|
|
||||||
#elif defined(CONFIG_ISA_riscv)
|
|
||||||
#define RISCV_GPR_TYPE MUXDEF(CONFIG_RV64, uint64_t, uint32_t)
|
|
||||||
#define RISCV_GPR_NUM MUXDEF(CONFIG_RVE , 16, 32)
|
|
||||||
#define DIFFTEST_REG_SIZE (sizeof(RISCV_GPR_TYPE) * (RISCV_GPR_NUM + 1)) // GPRs + pc
|
|
||||||
#elif defined(CONFIG_ISA_loongarch32r)
|
|
||||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 33) // GPRs + pc
|
|
||||||
#else
|
|
||||||
# error Unsupport ISA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
8
nemu/include/difftest.h
Normal file
8
nemu/include/difftest.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __NEMU_DIFFTEST_H__
|
||||||
|
#define __NEMU_DIFFTEST_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern bool nemu_do_difftest;
|
||||||
|
|
||||||
|
#endif // __NEMU_DIFFTEST_H__
|
|
@ -29,7 +29,7 @@
|
||||||
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
// macro concatenation
|
// macro concatenation
|
||||||
#define concat_temp(x, y) x ## y
|
#define concat_temp(x, y) x##y
|
||||||
#define concat(x, y) concat_temp(x, y)
|
#define concat(x, y) concat_temp(x, y)
|
||||||
#define concat3(x, y, z) concat(concat(x, y), z)
|
#define concat3(x, y, z) concat(concat(x, y), z)
|
||||||
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
|
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
|
||||||
|
@ -39,7 +39,8 @@
|
||||||
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
|
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
|
||||||
#define CHOOSE2nd(a, b, ...) b
|
#define CHOOSE2nd(a, b, ...) b
|
||||||
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
|
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
|
||||||
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
|
#define MUX_MACRO_PROPERTY(p, macro, a, b) \
|
||||||
|
MUX_WITH_COMMA(concat(p, macro), a, b)
|
||||||
// define placeholders for some property
|
// define placeholders for some property
|
||||||
#define __P_DEF_0 X,
|
#define __P_DEF_0 X,
|
||||||
#define __P_DEF_1 X,
|
#define __P_DEF_1 X,
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
|
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
|
||||||
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
|
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
|
||||||
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
|
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
|
||||||
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y)
|
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_, macro, X, Y)
|
||||||
|
|
||||||
// test if a boolean macro is defined
|
// test if a boolean macro is defined
|
||||||
#define ISDEF(macro) MUXDEF(macro, 1, 0)
|
#define ISDEF(macro) MUXDEF(macro, 1, 0)
|
||||||
|
@ -84,29 +85,46 @@
|
||||||
#define MAP(c, f) c(f)
|
#define MAP(c, f) c(f)
|
||||||
|
|
||||||
#define BITMASK(bits) ((1ull << (bits)) - 1)
|
#define BITMASK(bits) ((1ull << (bits)) - 1)
|
||||||
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
|
#define BITS(x, hi, lo) \
|
||||||
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (uint64_t)__x.n; })
|
(((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
|
||||||
|
#define SEXT(x, len) \
|
||||||
|
({ \
|
||||||
|
struct { \
|
||||||
|
int64_t n : len; \
|
||||||
|
} __x = {.n = x}; \
|
||||||
|
(uint64_t) __x.n; \
|
||||||
|
})
|
||||||
|
|
||||||
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
|
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz)-1) & ~((sz)-1))
|
||||||
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1))
|
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz)-1))
|
||||||
|
|
||||||
#define PG_ALIGN __attribute((aligned(4096)))
|
#define PG_ALIGN __attribute((aligned(4096)))
|
||||||
|
|
||||||
#define FAILED_GOTO(tag, exp) do {if((exp)) goto tag;} while(0)
|
#define FAILED_GOTO(tag, exp) \
|
||||||
|
do { \
|
||||||
|
if ((exp)) \
|
||||||
|
goto tag; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#if !defined(likely)
|
#if !defined(likely)
|
||||||
#define likely(cond) __builtin_expect(cond, 1)
|
#define likely(cond) __builtin_expect(cond, 1)
|
||||||
#define unlikely(cond) __builtin_expect(cond, 0)
|
#define unlikely(cond) __builtin_expect(cond, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define __EXPORT __attribute__((visibility("default")))
|
||||||
|
|
||||||
// for AM IOE
|
// for AM IOE
|
||||||
#define io_read(reg) \
|
#define io_read(reg) \
|
||||||
({ reg##_T __io_param; \
|
({ \
|
||||||
|
reg##_T __io_param; \
|
||||||
ioe_read(reg, &__io_param); \
|
ioe_read(reg, &__io_param); \
|
||||||
__io_param; })
|
__io_param; \
|
||||||
|
})
|
||||||
|
|
||||||
#define io_write(reg, ...) \
|
#define io_write(reg, ...) \
|
||||||
({ reg##_T __io_param = (reg##_T) { __VA_ARGS__ }; \
|
({ \
|
||||||
ioe_write(reg, &__io_param); })
|
reg##_T __io_param = (reg##_T){__VA_ARGS__}; \
|
||||||
|
ioe_write(reg, &__io_param); \
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
28
nemu/include/nemu.h
Normal file
28
nemu/include/nemu.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef __NEMU_HEADER__
|
||||||
|
#define __NEMU_HEADER__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <gdbstub.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int nemu_read_mem(void *args, size_t addr, size_t len, void *val);
|
||||||
|
int nemu_write_mem(void *args, size_t addr, size_t len, void *val);
|
||||||
|
void nemu_cont(void *args, gdb_action_t *res);
|
||||||
|
void nemu_stepi(void *args, gdb_action_t *res);
|
||||||
|
bool nemu_set_bp(void *args, size_t addr, bp_type_t type);
|
||||||
|
bool nemu_del_bp(void *args, size_t addr, bp_type_t type);
|
||||||
|
void nemu_on_interrupt(void *args);
|
||||||
|
int nemu_read_reg(void *args, int regno, size_t *data);
|
||||||
|
int nemu_write_reg(void *args, int regno, size_t data);
|
||||||
|
void nemu_init(void *args);
|
||||||
|
|
||||||
|
extern arch_info_t nemu_isa_arch_info;
|
||||||
|
extern bool nemu_do_difftest;
|
||||||
|
extern bool nemu_dbg_state_size;
|
||||||
|
|
||||||
|
#endif // __NEMU_HEADER__
|
|
@ -16,7 +16,6 @@
|
||||||
#include "gdbstub.h"
|
#include "gdbstub.h"
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <cpu/decode.h>
|
#include <cpu/decode.h>
|
||||||
#include <cpu/difftest.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
/***************************************************************************************
|
|
||||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
||||||
*
|
|
||||||
* NEMU is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
***************************************************************************************/
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include <isa.h>
|
|
||||||
#include <cpu/cpu.h>
|
|
||||||
#include <memory/paddr.h>
|
|
||||||
#include <utils.h>
|
|
||||||
#include <difftest-def.h>
|
|
||||||
|
|
||||||
void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction) = NULL;
|
|
||||||
void (*ref_difftest_regcpy)(void *dut, bool direction) = NULL;
|
|
||||||
void (*ref_difftest_exec)(uint64_t n) = NULL;
|
|
||||||
void (*ref_difftest_raise_intr)(uint64_t NO) = NULL;
|
|
||||||
|
|
||||||
#ifdef CONFIG_DIFFTEST
|
|
||||||
|
|
||||||
static bool is_skip_ref = false;
|
|
||||||
static int skip_dut_nr_inst = 0;
|
|
||||||
|
|
||||||
// this is used to let ref skip instructions which
|
|
||||||
// can not produce consistent behavior with NEMU
|
|
||||||
void difftest_skip_ref() {
|
|
||||||
is_skip_ref = true;
|
|
||||||
// If such an instruction is one of the instruction packing in QEMU
|
|
||||||
// (see below), we end the process of catching up with QEMU's pc to
|
|
||||||
// keep the consistent behavior in our best.
|
|
||||||
// Note that this is still not perfect: if the packed instructions
|
|
||||||
// already write some memory, and the incoming instruction in NEMU
|
|
||||||
// will load that memory, we will encounter false negative. But such
|
|
||||||
// situation is infrequent.
|
|
||||||
skip_dut_nr_inst = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is used to deal with instruction packing in QEMU.
|
|
||||||
// Sometimes letting QEMU step once will execute multiple instructions.
|
|
||||||
// We should skip checking until NEMU's pc catches up with QEMU's pc.
|
|
||||||
// The semantic is
|
|
||||||
// Let REF run `nr_ref` instructions first.
|
|
||||||
// We expect that DUT will catch up with REF within `nr_dut` instructions.
|
|
||||||
void difftest_skip_dut(int nr_ref, int nr_dut) {
|
|
||||||
skip_dut_nr_inst += nr_dut;
|
|
||||||
|
|
||||||
while (nr_ref -- > 0) {
|
|
||||||
ref_difftest_exec(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_difftest(char *ref_so_file, long img_size, int port) {
|
|
||||||
assert(ref_so_file != NULL);
|
|
||||||
|
|
||||||
void *handle;
|
|
||||||
handle = dlopen(ref_so_file, RTLD_LAZY);
|
|
||||||
assert(handle);
|
|
||||||
|
|
||||||
ref_difftest_memcpy = dlsym(handle, "difftest_memcpy");
|
|
||||||
assert(ref_difftest_memcpy);
|
|
||||||
|
|
||||||
ref_difftest_regcpy = dlsym(handle, "difftest_regcpy");
|
|
||||||
assert(ref_difftest_regcpy);
|
|
||||||
|
|
||||||
ref_difftest_exec = dlsym(handle, "difftest_exec");
|
|
||||||
assert(ref_difftest_exec);
|
|
||||||
|
|
||||||
ref_difftest_raise_intr = dlsym(handle, "difftest_raise_intr");
|
|
||||||
assert(ref_difftest_raise_intr);
|
|
||||||
|
|
||||||
void (*ref_difftest_init)(int) = dlsym(handle, "difftest_init");
|
|
||||||
assert(ref_difftest_init);
|
|
||||||
|
|
||||||
Log("Differential testing: %s", ANSI_FMT("ON", ANSI_FG_GREEN));
|
|
||||||
Log("The result of every instruction will be compared with %s. "
|
|
||||||
"This will help you a lot for debugging, but also significantly reduce the performance. "
|
|
||||||
"If it is not necessary, you can turn it off in menuconfig.", ref_so_file);
|
|
||||||
|
|
||||||
ref_difftest_init(port);
|
|
||||||
ref_difftest_memcpy(RESET_VECTOR, guest_to_host(RESET_VECTOR), img_size, DIFFTEST_TO_REF);
|
|
||||||
ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void checkregs(CPU_state *ref, vaddr_t pc) {
|
|
||||||
if (!isa_difftest_checkregs(ref, pc)) {
|
|
||||||
nemu_state.state = NEMU_ABORT;
|
|
||||||
nemu_state.halt_pc = pc;
|
|
||||||
isa_reg_display();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void difftest_step(vaddr_t pc, vaddr_t npc) {
|
|
||||||
CPU_state ref_r;
|
|
||||||
|
|
||||||
if (skip_dut_nr_inst > 0) {
|
|
||||||
ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT);
|
|
||||||
if (ref_r.pc == npc) {
|
|
||||||
skip_dut_nr_inst = 0;
|
|
||||||
checkregs(&ref_r, npc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
skip_dut_nr_inst --;
|
|
||||||
if (skip_dut_nr_inst == 0)
|
|
||||||
panic("can not catch up with ref.pc = " FMT_WORD " at pc = " FMT_WORD, ref_r.pc, pc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_skip_ref) {
|
|
||||||
// to skip the checking of an instruction, just copy the reg state to reference design
|
|
||||||
ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF);
|
|
||||||
is_skip_ref = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref_difftest_exec(1);
|
|
||||||
ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT);
|
|
||||||
|
|
||||||
checkregs(&ref_r, pc);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void init_difftest(char *ref_so_file, long img_size, int port) { }
|
|
||||||
#endif
|
|
|
@ -1,51 +0,0 @@
|
||||||
/***************************************************************************************
|
|
||||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
||||||
*
|
|
||||||
* NEMU is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
***************************************************************************************/
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
#include <cpu/cpu.h>
|
|
||||||
#include <cpu/decode.h>
|
|
||||||
#include <difftest-def.h>
|
|
||||||
#include <isa.h>
|
|
||||||
#include <memory/paddr.h>
|
|
||||||
|
|
||||||
__EXPORT void difftest_memcpy(paddr_t addr, void *buf, size_t n,
|
|
||||||
bool direction) {
|
|
||||||
if (direction == DIFFTEST_TO_REF) {
|
|
||||||
memcpy(guest_to_host(addr), buf, n);
|
|
||||||
} else {
|
|
||||||
memcpy(buf, guest_to_host(addr), n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__EXPORT void difftest_regcpy(void *dut, bool direction) {
|
|
||||||
// assert(0);
|
|
||||||
if (direction == DIFFTEST_TO_DUT)
|
|
||||||
memcpy(dut, &cpu, sizeof(CPU_state));
|
|
||||||
else
|
|
||||||
memcpy(&cpu, dut, sizeof(CPU_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
__EXPORT void difftest_exec(uint64_t n) { cpu_exec(n); }
|
|
||||||
|
|
||||||
__EXPORT void difftest_raise_intr(word_t NO) {
|
|
||||||
// assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
__EXPORT void difftest_init(int port) {
|
|
||||||
void init_mem();
|
|
||||||
init_mem();
|
|
||||||
/* Perform ISA dependent initialization. */
|
|
||||||
init_isa();
|
|
||||||
}
|
|
|
@ -13,6 +13,8 @@
|
||||||
* 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>
|
||||||
|
|
||||||
#define PORT_IO_SPACE_MAX 65535
|
#define PORT_IO_SPACE_MAX 65535
|
||||||
|
@ -22,15 +24,19 @@ static IOMap maps[NR_MAP] = {};
|
||||||
static int nr_map = 0;
|
static int nr_map = 0;
|
||||||
|
|
||||||
/* device interface */
|
/* device interface */
|
||||||
void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len, io_callback_t callback) {
|
void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len,
|
||||||
|
io_callback_t callback) {
|
||||||
assert(nr_map < NR_MAP);
|
assert(nr_map < NR_MAP);
|
||||||
assert(addr + len <= PORT_IO_SPACE_MAX);
|
assert(addr + len <= PORT_IO_SPACE_MAX);
|
||||||
maps[nr_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
|
maps[nr_map] = (IOMap){.name = name,
|
||||||
.space = space, .callback = callback };
|
.low = addr,
|
||||||
|
.high = addr + len - 1,
|
||||||
|
.space = space,
|
||||||
|
.callback = callback};
|
||||||
Log("Add port-io map '%s' at [" FMT_PADDR ", " FMT_PADDR "]",
|
Log("Add port-io map '%s' at [" FMT_PADDR ", " FMT_PADDR "]",
|
||||||
maps[nr_map].name, maps[nr_map].low, maps[nr_map].high);
|
maps[nr_map].name, maps[nr_map].low, maps[nr_map].high);
|
||||||
|
|
||||||
nr_map ++;
|
nr_map++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CPU interface */
|
/* CPU interface */
|
||||||
|
|
|
@ -13,8 +13,10 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
#include <utils.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
#include <device/map.h>
|
#include <device/map.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
||||||
// NOTE: this is compatible to 16550
|
// NOTE: this is compatible to 16550
|
||||||
|
@ -23,7 +25,6 @@
|
||||||
|
|
||||||
static uint8_t *serial_base = NULL;
|
static uint8_t *serial_base = NULL;
|
||||||
|
|
||||||
|
|
||||||
static void serial_putc(char ch) {
|
static void serial_putc(char ch) {
|
||||||
MUXDEF(CONFIG_TARGET_AM, putch(ch), putc(ch, stderr));
|
MUXDEF(CONFIG_TARGET_AM, putch(ch), putc(ch, stderr));
|
||||||
}
|
}
|
||||||
|
@ -33,19 +34,21 @@ static void serial_io_handler(uint32_t offset, int len, bool is_write) {
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
/* We bind the serial port with the host stderr in NEMU. */
|
/* We bind the serial port with the host stderr in NEMU. */
|
||||||
case CH_OFFSET:
|
case CH_OFFSET:
|
||||||
if (is_write) serial_putc(serial_base[0]);
|
if (is_write)
|
||||||
else panic("do not support read");
|
serial_putc(serial_base[0]);
|
||||||
|
else
|
||||||
|
panic("do not support read");
|
||||||
break;
|
break;
|
||||||
default: panic("do not support offset = %d", offset);
|
default:
|
||||||
|
panic("do not support offset = %d", offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_serial() {
|
void init_serial() {
|
||||||
serial_base = new_space(8);
|
serial_base = new_space(8);
|
||||||
#ifdef CONFIG_HAS_PORT_IO
|
#ifdef CONFIG_HAS_PORT_IO
|
||||||
add_pio_map ("serial", CONFIG_SERIAL_PORT, serial_base, 8, serial_io_handler);
|
add_pio_map("serial", CONFIG_SERIAL_PORT, serial_base, 8, serial_io_handler);
|
||||||
#else
|
#else
|
||||||
add_mmio_map("serial", CONFIG_SERIAL_MMIO, serial_base, 8, serial_io_handler);
|
add_mmio_map("serial", CONFIG_SERIAL_MMIO, serial_base, 8, serial_io_handler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
#include <device/map.h>
|
#include <assert.h>
|
||||||
#include <device/alarm.h>
|
#include <device/alarm.h>
|
||||||
|
#include <device/map.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
static uint32_t *rtc_port_base = NULL;
|
static uint32_t *rtc_port_base = NULL;
|
||||||
|
@ -40,7 +41,7 @@ static void timer_intr() {
|
||||||
void init_timer() {
|
void init_timer() {
|
||||||
rtc_port_base = (uint32_t *)new_space(8);
|
rtc_port_base = (uint32_t *)new_space(8);
|
||||||
#ifdef CONFIG_HAS_PORT_IO
|
#ifdef CONFIG_HAS_PORT_IO
|
||||||
add_pio_map ("rtc", CONFIG_RTC_PORT, rtc_port_base, 8, rtc_io_handler);
|
add_pio_map("rtc", CONFIG_RTC_PORT, rtc_port_base, 8, rtc_io_handler);
|
||||||
#else
|
#else
|
||||||
add_mmio_map("rtc", CONFIG_RTC_MMIO, rtc_port_base, 8, rtc_io_handler);
|
add_mmio_map("rtc", CONFIG_RTC_MMIO, rtc_port_base, 8, rtc_io_handler);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,20 +13,19 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
#include <utils.h>
|
|
||||||
#include <cpu/ifetch.h>
|
#include <cpu/ifetch.h>
|
||||||
|
#include <difftest.h>
|
||||||
#include <isa.h>
|
#include <isa.h>
|
||||||
#include <cpu/difftest.h>
|
#include <utils.h>
|
||||||
|
|
||||||
void set_nemu_state(int state, vaddr_t pc, int halt_ret) {
|
void set_nemu_state(int state, vaddr_t pc, int halt_ret) {
|
||||||
difftest_skip_ref();
|
nemu_do_difftest = false;
|
||||||
nemu_state.state = state;
|
nemu_state.state = state;
|
||||||
nemu_state.halt_pc = pc;
|
nemu_state.halt_pc = pc;
|
||||||
nemu_state.halt_ret = halt_ret;
|
nemu_state.halt_ret = halt_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noinline))
|
__attribute__((noinline)) void invalid_inst(vaddr_t thispc) {
|
||||||
void invalid_inst(vaddr_t thispc) {
|
|
||||||
uint32_t temp[2];
|
uint32_t temp[2];
|
||||||
vaddr_t pc = thispc;
|
vaddr_t pc = thispc;
|
||||||
temp[0] = inst_fetch(&pc, 4);
|
temp[0] = inst_fetch(&pc, 4);
|
||||||
|
@ -36,16 +35,22 @@ void invalid_inst(vaddr_t thispc) {
|
||||||
printf("invalid opcode(PC = " FMT_WORD "):\n"
|
printf("invalid opcode(PC = " FMT_WORD "):\n"
|
||||||
"\t%02x %02x %02x %02x %02x %02x %02x %02x ...\n"
|
"\t%02x %02x %02x %02x %02x %02x %02x %02x ...\n"
|
||||||
"\t%08x %08x...\n",
|
"\t%08x %08x...\n",
|
||||||
thispc, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], temp[0], temp[1]);
|
thispc, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], temp[0],
|
||||||
|
temp[1]);
|
||||||
|
|
||||||
printf("There are two cases which will trigger this unexpected exception:\n"
|
printf("There are two cases which will trigger this unexpected exception:\n"
|
||||||
"1. The instruction at PC = " FMT_WORD " is not implemented.\n"
|
"1. The instruction at PC = " FMT_WORD " is not implemented.\n"
|
||||||
"2. Something is implemented incorrectly.\n", thispc);
|
"2. Something is implemented incorrectly.\n",
|
||||||
printf("Find this PC(" FMT_WORD ") in the disassembling result to distinguish which case it is.\n\n", thispc);
|
thispc);
|
||||||
|
printf("Find this PC(" FMT_WORD
|
||||||
|
") in the disassembling result to distinguish which case it is.\n\n",
|
||||||
|
thispc);
|
||||||
printf(ANSI_FMT("If it is the first case, see\n%s\nfor more details.\n\n"
|
printf(ANSI_FMT("If it is the first case, see\n%s\nfor more details.\n\n"
|
||||||
"If it is the second case, remember:\n"
|
"If it is the second case, remember:\n"
|
||||||
"* The machine is always right!\n"
|
"* The machine is always right!\n"
|
||||||
"* Every line of untested code is always wrong!\n\n", ANSI_FG_RED), isa_logo);
|
"* Every line of untested code is always wrong!\n\n",
|
||||||
|
ANSI_FG_RED),
|
||||||
|
isa_logo);
|
||||||
|
|
||||||
set_nemu_state(NEMU_ABORT, thispc, -1);
|
set_nemu_state(NEMU_ABORT, thispc, -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,22 @@
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
|
|
||||||
void sdb_mainloop();
|
int gdbstub_loop();
|
||||||
|
extern bool enable_gdbstub;
|
||||||
|
|
||||||
void engine_start() {
|
void engine_start() {
|
||||||
#ifdef CONFIG_TARGET_AM
|
#ifdef CONFIG_TARGET_AM
|
||||||
cpu_exec(-1);
|
cpu_exec(-1);
|
||||||
#else
|
#else
|
||||||
/* Receive commands from user. */
|
/* Receive commands from user. */
|
||||||
int nemu_gdbstub_run();
|
int ret = 0;
|
||||||
if (nemu_gdbstub_run()) {
|
if (enable_gdbstub) {
|
||||||
|
if ((ret = gdbstub_loop())) {
|
||||||
Error("gdbstub exited abnormally");
|
Error("gdbstub exited abnormally");
|
||||||
exit(1);
|
exit(ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cpu_exec(-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/***************************************************************************************
|
|
||||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
||||||
*
|
|
||||||
* NEMU is licensed under Mulan PSL v2.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
||||||
* You may obtain a copy of Mulan PSL v2 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL2
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
||||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
* See the Mulan PSL v2 for more details.
|
|
||||||
***************************************************************************************/
|
|
||||||
|
|
||||||
#include <isa.h>
|
|
||||||
#include <cpu/difftest.h>
|
|
||||||
#include "../local-include/reg.h"
|
|
||||||
|
|
||||||
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
|
|
||||||
for(int i = 0; i < MUXDEF(CONFIG_RVE, 16, 32); i++) {
|
|
||||||
if(!difftest_check_reg(reg_name(i), pc, ref_r->gpr[i], gpr(i))) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void isa_difftest_attach() {
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
#include "local-include/reg.h"
|
#include "local-include/reg.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include <difftest-def.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
#include <isa.h>
|
#include <isa.h>
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <difftest-def.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
#include <isa.h>
|
#include <isa.h>
|
||||||
|
@ -17,6 +16,10 @@ typedef struct {
|
||||||
bool halt;
|
bool halt;
|
||||||
} DbgState;
|
} DbgState;
|
||||||
|
|
||||||
|
__EXPORT size_t nemu_dbg_state_size = sizeof(DbgState);
|
||||||
|
__EXPORT bool nemu_do_difftest = true;
|
||||||
|
__EXPORT arch_info_t nemu_isa_arch_info;
|
||||||
|
|
||||||
__EXPORT int nemu_read_mem(void *args, size_t addr, size_t len, void *val) {
|
__EXPORT int nemu_read_mem(void *args, size_t addr, size_t len, void *val) {
|
||||||
if (!in_pmem(addr))
|
if (!in_pmem(addr))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -109,7 +112,6 @@ __EXPORT int nemu_read_reg(void *args, int regno, size_t *data) {
|
||||||
__EXPORT int nemu_write_reg(void *args, int regno, size_t data) {
|
__EXPORT int nemu_write_reg(void *args, int regno, size_t data) {
|
||||||
return isa_write_reg(args, regno, data);
|
return isa_write_reg(args, regno, data);
|
||||||
}
|
}
|
||||||
__EXPORT size_t argsize = sizeof(DbgState);
|
|
||||||
|
|
||||||
static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont,
|
static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont,
|
||||||
.stepi = nemu_stepi,
|
.stepi = nemu_stepi,
|
||||||
|
@ -120,35 +122,41 @@ static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont,
|
||||||
.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 = NULL};
|
||||||
static DbgState dbg;
|
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";
|
||||||
|
|
||||||
__EXPORT void nemu_init(void *args) {
|
static void init_remote_gdbstub(void *args) {
|
||||||
DbgState *dbg_state = (DbgState *)args;
|
DbgState *dbg_state = (DbgState *)args;
|
||||||
|
pdbg = (DbgState *)args;
|
||||||
dbg_state->bp = new std::vector<breakpoint_t>();
|
dbg_state->bp = new std::vector<breakpoint_t>();
|
||||||
dbg_state->halt = 0;
|
dbg_state->halt = 0;
|
||||||
Assert(dbg_state->bp != NULL, "Failed to allocate breakpoint");
|
Assert(dbg_state->bp != NULL, "Failed to allocate breakpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
__EXPORT void nemu_init(void *args) {
|
||||||
|
init_remote_gdbstub(args);
|
||||||
|
|
||||||
|
void init_rand();
|
||||||
void init_mem();
|
void init_mem();
|
||||||
|
|
||||||
|
IFDEF(CONFIG_DEVICE, void init_device());
|
||||||
|
|
||||||
|
init_rand();
|
||||||
init_mem();
|
init_mem();
|
||||||
|
IFDEF(CONFIG_DEVICE, init_device());
|
||||||
|
|
||||||
/* Perform ISA dependent initialization. */
|
/* Perform ISA dependent initialization. */
|
||||||
init_isa();
|
init_isa();
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT int nemu_gdbstub_init() {
|
int gdbstub_loop() {
|
||||||
dbg.bp = new std::vector<breakpoint_t>();
|
|
||||||
assert(dbg.bp);
|
|
||||||
if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops,
|
if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops,
|
||||||
(arch_info_t)isa_arch_info, strdup(SOCKET_ADDR))) {
|
(arch_info_t)isa_arch_info, SOCKET_ADDR)) {
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__EXPORT int nemu_gdbstub_run() {
|
|
||||||
printf("Waiting for gdb connection at %s", SOCKET_ADDR);
|
printf("Waiting for gdb connection at %s", SOCKET_ADDR);
|
||||||
bool success = gdbstub_run(&gdbstub_priv, &dbg);
|
bool success = gdbstub_run(&gdbstub_priv, pdbg);
|
||||||
// gdbstub_close(&gdbstub_priv);
|
// gdbstub_close(&gdbstub_priv);
|
||||||
return !success;
|
return !success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#include <cpu/cpu.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <isa.h>
|
#include <isa.h>
|
||||||
#include <memory/paddr.h>
|
#include <memory/paddr.h>
|
||||||
|
#include <nemu.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
|
@ -25,7 +27,11 @@ void init_mem();
|
||||||
void init_difftest(char *ref_so_file, long img_size, int port);
|
void init_difftest(char *ref_so_file, long img_size, int port);
|
||||||
void init_device();
|
void init_device();
|
||||||
void init_disasm(const char *triple);
|
void init_disasm(const char *triple);
|
||||||
void nemu_init();
|
|
||||||
|
char *log_file = NULL;
|
||||||
|
char *elf_file = NULL;
|
||||||
|
char *img_file = NULL;
|
||||||
|
bool enable_gdbstub = false;
|
||||||
|
|
||||||
static void welcome() {
|
static void welcome() {
|
||||||
Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN),
|
Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN),
|
||||||
|
@ -43,12 +49,6 @@ static void welcome() {
|
||||||
#ifndef CONFIG_TARGET_AM
|
#ifndef CONFIG_TARGET_AM
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
static char *log_file = NULL;
|
|
||||||
static char *elf_file = NULL;
|
|
||||||
static char *diff_so_file = NULL;
|
|
||||||
static char *img_file = NULL;
|
|
||||||
static int difftest_port = 1234;
|
|
||||||
|
|
||||||
static long load_img() {
|
static long load_img() {
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
size_t img_filename_len = strlen(img_file);
|
size_t img_filename_len = strlen(img_file);
|
||||||
|
@ -113,38 +113,30 @@ static long load_img() {
|
||||||
|
|
||||||
static int parse_args(int argc, char *argv[]) {
|
static int parse_args(int argc, char *argv[]) {
|
||||||
const struct option table[] = {
|
const struct option table[] = {
|
||||||
{"batch", no_argument, NULL, 'b'},
|
{"batch", no_argument, NULL, 'b'}, {"log", required_argument, NULL, 'l'},
|
||||||
{"log", required_argument, NULL, 'l'},
|
{"debug", no_argument, NULL, 'g'}, {"elf", required_argument, NULL, 'f'},
|
||||||
{"diff", required_argument, NULL, 'd'},
|
{"help", no_argument, NULL, 'h'}, {0, 0, NULL, 0},
|
||||||
{"port", required_argument, NULL, 'p'},
|
|
||||||
{"elf", required_argument, NULL, 'f'},
|
|
||||||
{"help", no_argument, NULL, 'h'},
|
|
||||||
{0, 0, NULL, 0},
|
|
||||||
};
|
};
|
||||||
int o;
|
int o;
|
||||||
while ((o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) {
|
while ((o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'p':
|
|
||||||
sscanf(optarg, "%d", &difftest_port);
|
|
||||||
break;
|
|
||||||
case 'l':
|
case 'l':
|
||||||
log_file = optarg;
|
log_file = optarg;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
|
||||||
diff_so_file = optarg;
|
|
||||||
break;
|
|
||||||
case 'f':
|
case 'f':
|
||||||
elf_file = optarg;
|
elf_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'g':
|
||||||
|
enable_gdbstub = true;
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
img_file = optarg;
|
img_file = optarg;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]);
|
printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]);
|
||||||
printf("\t-b,--batch run with batch mode\n");
|
printf("\t-b,--batch run with batch mode\n");
|
||||||
|
printf("\t-g,--debug enable gdb remote server\n");
|
||||||
printf("\t-l,--log=FILE output log to FILE\n");
|
printf("\t-l,--log=FILE output log to FILE\n");
|
||||||
printf("\t-d,--diff=REF_SO run DiffTest with reference REF_SO\n");
|
|
||||||
printf("\t-p,--port=PORT run DiffTest with port PORT\n");
|
|
||||||
printf("\t-f,--elf=FILE elf file with debug info\n");
|
printf("\t-f,--elf=FILE elf file with debug info\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -154,38 +146,18 @@ static int parse_args(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_monitor(int argc, char *argv[]) {
|
void init_monitor(int argc, char *argv[]) {
|
||||||
/* Perform some global initialization. */
|
|
||||||
|
|
||||||
/* Parse arguments. */
|
/* Parse arguments. */
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
|
|
||||||
/* Set random seed. */
|
void init_log(const char *log_file);
|
||||||
init_rand();
|
|
||||||
|
|
||||||
/* Open the log file. */
|
/* Open the log file. */
|
||||||
init_log(log_file);
|
init_log(log_file);
|
||||||
|
|
||||||
/* Initialize memory. */
|
/* Perform some global initialization. */
|
||||||
init_mem();
|
nemu_init(malloc(nemu_dbg_state_size));
|
||||||
|
|
||||||
/* Initialize devices. */
|
|
||||||
IFDEF(CONFIG_DEVICE, init_device());
|
|
||||||
|
|
||||||
/* Perform ISA dependent initialization. */
|
|
||||||
init_isa();
|
|
||||||
|
|
||||||
/* Load the image to memory. This will overwrite the built-in image. */
|
/* Load the image to memory. This will overwrite the built-in image. */
|
||||||
long img_size = load_img();
|
load_img();
|
||||||
|
|
||||||
/* Initialize differential testing. */
|
|
||||||
init_difftest(diff_so_file, img_size, difftest_port);
|
|
||||||
|
|
||||||
/* Initialize debugger */
|
|
||||||
// if (nemu_init()) {
|
|
||||||
// Error("Failed to init");
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
nemu_init();
|
|
||||||
|
|
||||||
// printf("elf_file: %s\n", elf_file);
|
// printf("elf_file: %s\n", elf_file);
|
||||||
if (elf_file != NULL) {
|
if (elf_file != NULL) {
|
||||||
|
|
Loading…
Reference in a new issue