correct ebreak implementation, gdbstub watcher

everything in gdb should work now :)
master
vhaudiquet 1 year ago
parent 89da4e56bb
commit 980070b204
  1. 10
      src/cpu/rv32cpu.c
  2. 38
      src/gdbstub/gdbstub.c

@ -512,7 +512,10 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
fprintf(stderr, "ECALL: a7(sbi ext id) = %d, a6(sbi funct id) = %d\n", cpu->regs.a7, cpu->regs.a6); fprintf(stderr, "ECALL: a7(sbi ext id) = %d, a6(sbi funct id) = %d\n", cpu->regs.a7, cpu->regs.a6);
break; break;
case IMM_EBREAK: case IMM_EBREAK:
fprintf(stderr, "EBREAK\n"); // EBREAK : on debug, give back hand to debugger ; without debug, end simulation
// In any way, we set back simulation ticks to 0
cpu->sim_ticks_left = 1;
cpu->pc -= 4;
break; break;
default: default:
fprintf(stderr, "FATAL: Unknown IMM for ECALL/EBREAK instruction while executing (IMM=0x%x)\n", instruction->immediate); fprintf(stderr, "FATAL: Unknown IMM for ECALL/EBREAK instruction while executing (IMM=0x%x)\n", instruction->immediate);
@ -650,6 +653,11 @@ void cpu_loop(rv32_cpu_t* cpu)
{ {
// Aquire CPU and memory mutex // Aquire CPU and memory mutex
pthread_mutex_lock(&cpu0_mutex); pthread_mutex_lock(&cpu0_mutex);
// No simulation ticks left : wakeup people waiting on sim end
if(!cpu->sim_ticks_left)
pthread_cond_signal(&cpu0->sim_condition);
// Then, wait for simulation state to change until we get more ticks to simulate
while(!cpu->sim_ticks_left) while(!cpu->sim_ticks_left)
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex); pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);

@ -25,10 +25,13 @@ typedef struct sockaddr sockaddr_t;
socket_t gdbstub_server_socket; socket_t gdbstub_server_socket;
socket_t gdb_socket; socket_t gdb_socket;
pthread_t gdbstub_thread; pthread_t gdbstub_thread;
pthread_t gdbstub_watcher_thread;
void gdbstub_thread_gdb(); void gdbstub_thread_gdb();
void gdbstub_cpu_watcher_thread();
static void gdbstub_handle_ctrlc(); static void gdbstub_handle_ctrlc();
/* /*
* Receive a packet from client gdb * Receive a packet from client gdb
* Ignores the ACK on the way, and only returns the packet (not initial '$' symbol) * Ignores the ACK on the way, and only returns the packet (not initial '$' symbol)
@ -161,6 +164,7 @@ void gdbstub_wait_for_connection()
gdb_socket = c_socket; gdb_socket = c_socket;
pthread_create(&gdbstub_thread, 0, (void*) gdbstub_thread_gdb, 0); pthread_create(&gdbstub_thread, 0, (void*) gdbstub_thread_gdb, 0);
pthread_create(&gdbstub_watcher_thread, 0, (void*) gdbstub_cpu_watcher_thread, 0);
} }
void gdbstub_thread_gdb() void gdbstub_thread_gdb()
@ -286,12 +290,14 @@ void gdbstub_thread_gdb()
{ {
// s : single-step // s : single-step
// TODO : Implement that correctly // Send an ACK
send(gdb_socket, "+", 1, 0);
// Send back halt reason // Continue simulation, for 1 tick
// Halt Reason : Signal 05 (SIGTRAP) pthread_mutex_lock(&cpu0_mutex);
char* resp = "S05"; cpu0->sim_ticks_left = 1;
gdbstub_send_packet(resp, 3); pthread_mutex_unlock(&cpu0_mutex);
pthread_cond_signal(&cpu0->sim_condition);
} }
else if(packet[0] == 'c') else if(packet[0] == 'c')
{ {
@ -310,6 +316,23 @@ void gdbstub_thread_gdb()
} }
} }
void gdbstub_cpu_watcher_thread()
{
while(1)
{
pthread_mutex_lock(&cpu0_mutex);
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
if(!cpu0->sim_ticks_left && cpu0->sim_ticks_done > 0)
{
// Send back halt reason
// Halt Reason : Signal 05 (SIGTRAP)
char* resp = "S05";
gdbstub_send_packet(resp, 3);
}
pthread_mutex_unlock(&cpu0_mutex);
}
}
/* /*
* Handles the GDB CTRL+C (^C) command, that * Handles the GDB CTRL+C (^C) command, that
* should interrupt the simulation * should interrupt the simulation
@ -320,9 +343,4 @@ static void gdbstub_handle_ctrlc()
pthread_mutex_lock(&cpu0_mutex); pthread_mutex_lock(&cpu0_mutex);
cpu0->sim_ticks_left = 0; cpu0->sim_ticks_left = 0;
pthread_mutex_unlock(&cpu0_mutex); pthread_mutex_unlock(&cpu0_mutex);
// Send back halt signal to gdb
// Halt Reason : Signal 05 (SIGTRAP)
char* resp = "S05";
gdbstub_send_packet(resp, 3);
} }

Loading…
Cancel
Save