提交 2270af0b 编写于 作者: Z Zihao Yu

Merge branch 'rv64-tb' into 'master'

Rv64 tb

See merge request projectn/nemu!47
......@@ -12,14 +12,14 @@ void backend_exec_code(uint64_t pc, int nr_instr) {
backend_exec(nr_instr);
}
vaddr_t rv64_exec_trans_buffer(void *buf, int nr_instr) {
vaddr_t rv64_exec_trans_buffer(void *buf, int nr_instr, int npc_type) {
// copy code to rv64 interpreter to execute it
backend_memcpy_from_frontend(RV64_EXEC_PC - riscv64_PMEM_BASE, buf, sizeof(uint32_t) * nr_instr);
// if the basic block is end with a branch instruction,
// execute until the branch instruction
// see rtl_jrelop() at rtl-basic.c
int nr_exec = (tran_next_pc == NEXT_PC_BRANCH ? nr_instr - 5 : nr_instr);
int nr_exec = (npc_type == NEXT_PC_BRANCH ? nr_instr - 5 : nr_instr);
backend_exec_code(RV64_EXEC_PC, nr_exec);
riscv64_CPU_state r;
......@@ -31,7 +31,7 @@ vaddr_t rv64_exec_trans_buffer(void *buf, int nr_instr) {
backend_getregs(&r);
}
if (tran_next_pc == NEXT_PC_BRANCH) {
if (npc_type == NEXT_PC_BRANCH) {
// execute the branch instruction and load x86.pc to x30
backend_exec(3);
backend_getregs(&r);
......
......@@ -13,9 +13,72 @@ int tran_next_pc = NEXT_PC_SEQ;
static void clear_trans_buffer() { trans_buffer_index = 0; }
void asm_print(vaddr_t ori_pc, int instr_len, bool print_flag);
vaddr_t rv64_exec_trans_buffer(void *buf, int nr_instr);
vaddr_t rv64_exec_trans_buffer(void *buf, int nr_instr, int npc_type);
void guest_getregs(CPU_state *cpu);
typedef struct TB {
vaddr_t pc;
int npc_type;
vaddr_t npc;
void *code;
uint32_t nr_instr;
uint32_t guest_nr_instr;
uint32_t hit_time;
struct TB *next;
} TB;
static TB head = { .next = NULL };
static TB* find_tb(vaddr_t pc) {
TB *tb;
for (tb = head.next; tb != NULL; tb = tb->next) {
if (tb->pc == pc) return tb;
}
return NULL;
}
static int find_top10_min(TB **top, int n) {
int i;
int min = 0;
for (i = 1; i < n; i ++) {
if (top[i]->hit_time < top[min]->hit_time) min = i;
}
return min;
}
static TB** find_top10_tb() {
static TB *top[10];
TB *p = head.next;;
int i;
for (i = 0; i < 10; i ++) {
assert(p != NULL);
top[i] = p;
p = p->next;
}
int min = find_top10_min(top, 10);
for (; p != NULL; p = p->next) {
if (p->hit_time > top[min]->hit_time) {
top[min] = p;
min = find_top10_min(top, 10);
}
}
for (i = 0; i < 10; i ++) {
int max = i;
int j;
for (j = i + 1; j < 10; j ++) {
if (top[max]->hit_time < top[j]->hit_time) max = j;
}
if (max != i) {
TB *tmp = top[i];
top[i] = top[max];
top[max] = tmp;
}
}
return top;
}
void write_ins(uint32_t ins) {
assert(trans_buffer_index < BUF_SIZE);
trans_buffer[trans_buffer_index++]=ins;
......@@ -25,44 +88,78 @@ void mainloop() {
nemu_state.state = NEMU_RUNNING;
uint64_t total_instr = 0;
while (1) {
__attribute__((unused)) vaddr_t ori_pc = cpu.pc;
__attribute__((unused)) vaddr_t seq_pc = isa_exec_once();
vaddr_t tb_start = cpu.pc;
TB *tb = find_tb(tb_start);
if (tb == NULL) {
clear_trans_buffer();
tran_next_pc = NEXT_PC_SEQ;
int guest_nr_instr = 0;
while (1) {
__attribute__((unused)) vaddr_t ori_pc = cpu.pc;
__attribute__((unused)) vaddr_t seq_pc = isa_exec_once();
guest_nr_instr ++;
if (nemu_state.state != NEMU_RUNNING) tran_next_pc = NEXT_PC_END;
if (nemu_state.state != NEMU_RUNNING) tran_next_pc = NEXT_PC_END;
#ifdef DEBUG
asm_print(ori_pc, seq_pc - ori_pc, true);
asm_print(ori_pc, seq_pc - ori_pc, true);
#endif
#ifndef DIFF_TEST
if (tran_next_pc != NEXT_PC_SEQ) {
#ifdef DIFF_TEST
if (true)
#else
if (tran_next_pc != NEXT_PC_SEQ)
#endif
vaddr_t next_pc = rv64_exec_trans_buffer(trans_buffer, trans_buffer_index);
total_instr += trans_buffer_index;
{
tb = malloc(sizeof(TB));
tb->pc = tb_start;
tb->nr_instr = trans_buffer_index;
tb->guest_nr_instr = guest_nr_instr;
tb->code = malloc(tb->nr_instr * 4);
memcpy(tb->code, trans_buffer, tb->nr_instr * 4);
tb->npc_type = tran_next_pc;
tb->npc = cpu.pc;
tb->hit_time = 0;
tb->next = head.next;
head.next = tb;
break;
}
}
}
if (tran_next_pc == NEXT_PC_END) {
// get cpu.eax and interpret `nemu_trap` again
guest_getregs(&cpu);
cpu.pc = ori_pc;
//Log("enter tb with pc = %x, nr_instr = %d", tb->pc, tb->nr_instr);
vaddr_t next_pc = rv64_exec_trans_buffer(tb->code, tb->nr_instr, tb->npc_type);
total_instr += tb->nr_instr;
tb->hit_time ++;
if (tb->npc_type == NEXT_PC_END) {
// get cpu.eax and interpret `nemu_trap` again
guest_getregs(&cpu);
cpu.pc = tb_start;
nemu_state.state = NEMU_RUNNING;
while (nemu_state.state == NEMU_RUNNING) {
isa_exec_once();
break;
}
if (tran_next_pc != NEXT_PC_SEQ) cpu.pc = next_pc;
// Log("new basic block pc = %x", cpu.pc);
clear_trans_buffer();
tran_next_pc = NEXT_PC_SEQ;
#ifndef DIFF_TEST
break;
}
#endif
if (tb->npc_type != NEXT_PC_SEQ) cpu.pc = next_pc;
else cpu.pc = tb->npc;
#ifdef DIFF_TEST
guest_getregs(&cpu);
difftest_step(ori_pc, cpu.pc);
difftest_step(tb_start, cpu.pc);
if (nemu_state.state == NEMU_ABORT) break;
#endif
}
// display the top-10 hot basic block
TB **top = find_top10_tb();
int i;
for (i = 0; i < 10; i ++) {
printf("%2d: pc = " FMT_WORD "(instr: %d -> %d), \thit time = %d\n",
i + 1, top[i]->pc, top[i]->guest_nr_instr, top[i]->nr_instr, top[i]->hit_time);
}
switch (nemu_state.state) {
case NEMU_RUNNING: nemu_state.state = NEMU_STOP; break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册