pa2.2: add ITRACE buffer
This commit is contained in:
parent
d67fb1138a
commit
c917083554
7 changed files with 39 additions and 10 deletions
|
@ -151,6 +151,10 @@ config ITRACE_COND
|
||||||
string "Only trace instructions when the condition is true"
|
string "Only trace instructions when the condition is true"
|
||||||
default "true"
|
default "true"
|
||||||
|
|
||||||
|
config ITRACE_BUFFER
|
||||||
|
depends on ITRACE
|
||||||
|
int "Buffer size for intruction trace (unit: number of instructions)"
|
||||||
|
default 10
|
||||||
|
|
||||||
config DIFFTEST
|
config DIFFTEST
|
||||||
depends on TARGET_NATIVE_ELF
|
depends on TARGET_NATIVE_ELF
|
||||||
|
|
|
@ -23,7 +23,6 @@ typedef struct Decode {
|
||||||
vaddr_t snpc; // static next pc
|
vaddr_t snpc; // static next pc
|
||||||
vaddr_t dnpc; // dynamic next pc
|
vaddr_t dnpc; // dynamic next pc
|
||||||
ISADecodeInfo isa;
|
ISADecodeInfo isa;
|
||||||
IFDEF(CONFIG_ITRACE, char logbuf[128]);
|
|
||||||
} Decode;
|
} Decode;
|
||||||
|
|
||||||
// --- pattern matching mechanism ---
|
// --- pattern matching mechanism ---
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
MUXDEF(CONFIG_TARGET_AM, printf(ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__), \
|
MUXDEF(CONFIG_TARGET_AM, printf(ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__), \
|
||||||
(fflush(stdout), fprintf(stderr, ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__))); \
|
(fflush(stdout), fprintf(stderr, ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__))); \
|
||||||
IFNDEF(CONFIG_TARGET_AM, extern FILE* log_fp; fflush(log_fp)); \
|
IFNDEF(CONFIG_TARGET_AM, extern FILE* log_fp; fflush(log_fp)); \
|
||||||
|
IFDEF(CONFIG_ITRACE, log_itrace_print()); \
|
||||||
extern void assert_fail_msg(); \
|
extern void assert_fail_msg(); \
|
||||||
assert_fail_msg(); \
|
assert_fail_msg(); \
|
||||||
assert(cond); \
|
assert(cond); \
|
||||||
|
|
|
@ -74,4 +74,7 @@ uint64_t get_time();
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
IFDEF(CONFIG_ITRACE, void log_itrace_print());
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <cpu/decode.h>
|
#include <cpu/decode.h>
|
||||||
#include <cpu/difftest.h>
|
#include <cpu/difftest.h>
|
||||||
|
@ -29,15 +30,17 @@ CPU_state cpu = {};
|
||||||
uint64_t g_nr_guest_inst = 0;
|
uint64_t g_nr_guest_inst = 0;
|
||||||
static uint64_t g_timer = 0; // unit: us
|
static uint64_t g_timer = 0; // unit: us
|
||||||
static bool g_print_step = false;
|
static bool g_print_step = false;
|
||||||
|
IFDEF(CONFIG_ITRACE, extern char logbuf[CONFIG_ITRACE_BUFFER][128]);
|
||||||
|
IFDEF(CONFIG_ITRACE, extern int logbuf_rear);
|
||||||
|
|
||||||
void device_update();
|
void device_update();
|
||||||
bool wp_eval_all();
|
bool wp_eval_all();
|
||||||
|
|
||||||
static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
|
static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
|
||||||
#ifdef CONFIG_ITRACE_COND
|
#ifdef CONFIG_ITRACE_COND
|
||||||
if (ITRACE_COND) { log_write("%s\n", _this->logbuf); }
|
if (ITRACE_COND) { log_write("%s\n", logbuf[logbuf_rear]); }
|
||||||
#endif
|
#endif
|
||||||
if (g_print_step) { IFDEF(CONFIG_ITRACE, puts(_this->logbuf)); }
|
if (g_print_step) { IFDEF(CONFIG_ITRACE, puts(logbuf[logbuf_rear])); }
|
||||||
IFDEF(CONFIG_DIFFTEST, difftest_step(_this->pc, dnpc));
|
IFDEF(CONFIG_DIFFTEST, difftest_step(_this->pc, dnpc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +50,9 @@ static void exec_once(Decode *s, vaddr_t pc) {
|
||||||
isa_exec_once(s);
|
isa_exec_once(s);
|
||||||
cpu.pc = s->dnpc;
|
cpu.pc = s->dnpc;
|
||||||
#ifdef CONFIG_ITRACE
|
#ifdef CONFIG_ITRACE
|
||||||
char *p = s->logbuf;
|
logbuf_rear = (logbuf_rear + 1) % CONFIG_ITRACE_BUFFER;
|
||||||
p += snprintf(p, sizeof(s->logbuf), FMT_WORD ":", s->pc);
|
char *p = logbuf[logbuf_rear];
|
||||||
|
p += snprintf(p, sizeof(logbuf), FMT_WORD ":", s->pc);
|
||||||
int ilen = s->snpc - s->pc;
|
int ilen = s->snpc - s->pc;
|
||||||
int i;
|
int i;
|
||||||
uint8_t *inst = (uint8_t *)&s->isa.inst.val;
|
uint8_t *inst = (uint8_t *)&s->isa.inst.val;
|
||||||
|
@ -64,7 +68,7 @@ static void exec_once(Decode *s, vaddr_t pc) {
|
||||||
|
|
||||||
#ifndef CONFIG_ISA_loongarch32r
|
#ifndef CONFIG_ISA_loongarch32r
|
||||||
void disassemble(char *str, int size, uint64_t pc, uint8_t *code, int nbyte);
|
void disassemble(char *str, int size, uint64_t pc, uint8_t *code, int nbyte);
|
||||||
disassemble(p, s->logbuf + sizeof(s->logbuf) - p,
|
disassemble(p, logbuf[logbuf_rear] + sizeof(logbuf[logbuf_rear]) - p,
|
||||||
MUXDEF(CONFIG_ISA_x86, s->snpc, s->pc), (uint8_t *)&s->isa.inst.val, ilen);
|
MUXDEF(CONFIG_ISA_x86, s->snpc, s->pc), (uint8_t *)&s->isa.inst.val, ilen);
|
||||||
#else
|
#else
|
||||||
p[0] = '\0'; // the upstream llvm does not support loongarch32r
|
p[0] = '\0'; // the upstream llvm does not support loongarch32r
|
||||||
|
@ -79,7 +83,7 @@ static void execute(uint64_t n) {
|
||||||
g_nr_guest_inst ++;
|
g_nr_guest_inst ++;
|
||||||
trace_and_difftest(&s, cpu.pc);
|
trace_and_difftest(&s, cpu.pc);
|
||||||
if (wp_eval_all()) {
|
if (wp_eval_all()) {
|
||||||
puts(s.logbuf);
|
puts(logbuf[logbuf_rear]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nemu_state.state != NEMU_RUNNING) break;
|
if (nemu_state.state != NEMU_RUNNING) break;
|
||||||
|
@ -121,13 +125,16 @@ void cpu_exec(uint64_t n) {
|
||||||
switch (nemu_state.state) {
|
switch (nemu_state.state) {
|
||||||
case NEMU_RUNNING: nemu_state.state = NEMU_STOP; break;
|
case NEMU_RUNNING: nemu_state.state = NEMU_STOP; break;
|
||||||
|
|
||||||
case NEMU_END: case NEMU_ABORT:
|
case NEMU_END: case NEMU_ABORT: {
|
||||||
Log("nemu: %s at pc = " FMT_WORD,
|
Log("nemu: %s at pc = " FMT_WORD,
|
||||||
(nemu_state.state == NEMU_ABORT ? ANSI_FMT("ABORT", ANSI_FG_RED) :
|
(nemu_state.state == NEMU_ABORT ? ANSI_FMT("ABORT", ANSI_FG_RED) :
|
||||||
(nemu_state.halt_ret == 0 ? ANSI_FMT("HIT GOOD TRAP", ANSI_FG_GREEN) :
|
(nemu_state.halt_ret == 0 ? ANSI_FMT("HIT GOOD TRAP", ANSI_FG_GREEN) :
|
||||||
ANSI_FMT("HIT BAD TRAP", ANSI_FG_RED))),
|
ANSI_FMT("HIT BAD TRAP", ANSI_FG_RED))),
|
||||||
nemu_state.halt_pc);
|
nemu_state.halt_pc);
|
||||||
// fall through
|
if(nemu_state.halt_ret != 0) {
|
||||||
|
log_itrace_print();
|
||||||
|
}
|
||||||
|
} // fall through
|
||||||
case NEMU_QUIT: statistic();
|
case NEMU_QUIT: statistic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
|
||||||
|
|
||||||
static void do_branch(Decode *s, bool condition, word_t offset) {
|
static void do_branch(Decode *s, bool condition, word_t offset) {
|
||||||
if (condition) {
|
if (condition) {
|
||||||
puts(s->logbuf);
|
// puts(s->logbuf[s->logbuf_rear]);
|
||||||
s->dnpc = s->pc + offset;
|
s->dnpc = s->pc + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,3 +35,18 @@ bool log_enable() {
|
||||||
(g_nr_guest_inst <= CONFIG_TRACE_END), false);
|
(g_nr_guest_inst <= CONFIG_TRACE_END), false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
IFDEF(CONFIG_ITRACE, char logbuf[CONFIG_ITRACE_BUFFER][128]);
|
||||||
|
IFDEF(CONFIG_ITRACE, int logbuf_rear);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ITRACE
|
||||||
|
void log_itrace_print() {
|
||||||
|
puts("ITRACE buffer:");
|
||||||
|
for (int i = (logbuf_rear + 1) % CONFIG_ITRACE_BUFFER; i != logbuf_rear; i = (i + 1) % CONFIG_ITRACE_BUFFER) {
|
||||||
|
if (logbuf[i][0] == '\0') continue;
|
||||||
|
puts(logbuf[i]);
|
||||||
|
}
|
||||||
|
puts("Current command:");
|
||||||
|
puts(logbuf[logbuf_rear]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue