Event handling (stop/interrupt) clean-up

This commit is contained in:
folkert van heusden 2022-06-10 20:59:36 +02:00
parent f6824ececf
commit 8d8af7153b
12 changed files with 47 additions and 51 deletions

View file

@ -10,9 +10,8 @@
#include "utils.h" #include "utils.h"
console::console(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b) : console::console(std::atomic_uint32_t *const stop_event, bus *const b) :
terminate(terminate), stop_event(stop_event),
interrupt_emulation(interrupt_emulation),
b(b) b(b)
{ {
memset(screen_buffer, ' ', sizeof screen_buffer); memset(screen_buffer, ' ', sizeof screen_buffer);
@ -105,7 +104,7 @@ std::string console::read_line(const std::string & prompt)
for(;;) { for(;;) {
char c = wait_char(500); char c = wait_char(500);
if (*terminate || stop_thread_flag) if (*stop_event == EVENT_TERMINATE)
return ""; return "";
if (c == -1) if (c == -1)
@ -208,9 +207,9 @@ void console::operator()()
{ {
D(fprintf(stderr, "Console thread started\n");) D(fprintf(stderr, "Console thread started\n");)
set_thread_name("kek:console"); set_thread_name("kek::console");
while(!*terminate && !stop_thread_flag) { while(*stop_event != EVENT_TERMINATE && !stop_thread_flag) {
int c = wait_for_char_ll(100); int c = wait_for_char_ll(100);
if (c == -1) if (c == -1)
@ -221,9 +220,9 @@ void console::operator()()
// printf("%d %d\n", running_flag, c); // printf("%d %d\n", running_flag, c);
if (running_flag == false && c == 3) // ^c if (running_flag == false && c == 3) // ^c
*interrupt_emulation = *terminate = true; *stop_event = EVENT_TERMINATE;
else if (running_flag == true && c == 5) // ^e else if (running_flag == true && c == 5) // ^e
*interrupt_emulation = true; *stop_event = EVENT_INTERRUPT;
else if (running_flag == false && c == 12) // ^l else if (running_flag == false && c == 12) // ^l
refresh_virtual_terminal(); refresh_virtual_terminal();
else { else {

View file

@ -19,8 +19,7 @@ private:
std::mutex input_lock; std::mutex input_lock;
protected: protected:
std::atomic_bool *const terminate { nullptr }; std::atomic_uint32_t *const stop_event { nullptr };
std::atomic_bool *const interrupt_emulation { nullptr };
bus *const b { nullptr }; bus *const b { nullptr };
std::thread *th { nullptr }; std::thread *th { nullptr };
@ -41,7 +40,7 @@ protected:
virtual void put_char_ll(const char c) = 0; virtual void put_char_ll(const char c) = 0;
public: public:
console(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b); console(std::atomic_uint32_t *const stop_event, bus *const b);
virtual ~console(); virtual ~console();
void start_thread(); void start_thread();

View file

@ -6,11 +6,12 @@
#include "console_ncurses.h" #include "console_ncurses.h"
#include "cpu.h" #include "cpu.h"
#include "error.h" #include "error.h"
#include "gen.h"
#include "utils.h" #include "utils.h"
console_ncurses::console_ncurses(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b) : console_ncurses::console_ncurses(std::atomic_uint32_t *const stop_event, bus *const b) :
console(terminate, interrupt_emulation, b) console(stop_event, b)
{ {
init_ncurses(true); init_ncurses(true);
@ -130,7 +131,7 @@ void console_ncurses::panel_update_thread()
constexpr int refresh_rate = 50; constexpr int refresh_rate = 50;
while(!*terminate) { while(*stop_event != EVENT_TERMINATE) {
myusleep(1000000 / refresh_rate); myusleep(1000000 / refresh_rate);
// note that these are approximately as there's no mutex on the emulation // note that these are approximately as there's no mutex on the emulation

View file

@ -26,7 +26,7 @@ protected:
void put_char_ll(const char c) override; void put_char_ll(const char c) override;
public: public:
console_ncurses(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b); console_ncurses(std::atomic_uint32_t *const stop_event, bus *const b);
virtual ~console_ncurses(); virtual ~console_ncurses();
void put_string_lf(const std::string & what) override; void put_string_lf(const std::string & what) override;

View file

@ -7,8 +7,8 @@
#include "error.h" #include "error.h"
console_posix::console_posix(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b) : console_posix::console_posix(std::atomic_uint32_t *const stop_event, bus *const b) :
console(terminate, interrupt_emulation, b) console(stop_event, b)
{ {
if (tcgetattr(STDIN_FILENO, &org_tty_opts) == -1) if (tcgetattr(STDIN_FILENO, &org_tty_opts) == -1)
error_exit(true, "console_posix: tcgetattr failed"); error_exit(true, "console_posix: tcgetattr failed");

View file

@ -14,7 +14,7 @@ protected:
void put_char_ll(const char c) override; void put_char_ll(const char c) override;
public: public:
console_posix(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b); console_posix(std::atomic_uint32_t *const stop_event, bus *const b);
virtual ~console_posix(); virtual ~console_posix();
void resize_terminal() override; void resize_terminal() override;

View file

@ -13,7 +13,7 @@
#define IS_0(x, wm) ((wm) ? ((x) & 0xff) == 0 : (x) == 0) #define IS_0(x, wm) ((wm) ? ((x) & 0xff) == 0 : (x) == 0)
cpu::cpu(bus *const b, uint32_t *const event) : b(b), event(event) cpu::cpu(bus *const b, std::atomic_uint32_t *const event) : b(b), event(event)
{ {
reset(); reset();
} }
@ -1528,7 +1528,7 @@ bool cpu::misc_operations(const uint16_t instr)
{ {
switch(instr) { switch(instr) {
case 0b0000000000000000: // HALT case 0b0000000000000000: // HALT
*event = 1; *event = EVENT_HALT;
return true; return true;
case 0b0000000000000001: // WAIT case 0b0000000000000001: // WAIT

4
cpu.h
View file

@ -34,7 +34,7 @@ private:
bus *const b { nullptr }; bus *const b { nullptr };
uint32_t *const event { nullptr }; std::atomic_uint32_t *const event { nullptr };
bool check_queued_interrupts(); bool check_queued_interrupts();
@ -65,7 +65,7 @@ private:
operand_parameters addressing_to_string(const uint8_t mode_register, const uint16_t pc, const bool word_mode) const; operand_parameters addressing_to_string(const uint8_t mode_register, const uint16_t pc, const bool word_mode) const;
public: public:
explicit cpu(bus *const b, uint32_t *const event); explicit cpu(bus *const b, std::atomic_uint32_t *const event);
~cpu(); ~cpu();
bool check_breakpoint(); bool check_breakpoint();

View file

@ -1,6 +1,7 @@
#include "bus.h" #include "bus.h"
#include "console.h" #include "console.h"
#include "cpu.h" #include "cpu.h"
#include "gen.h"
#include "utils.h" #include "utils.h"
@ -8,9 +9,6 @@
void setBootLoader(bus *const b); void setBootLoader(bus *const b);
#endif #endif
extern uint32_t event;
extern std::atomic_bool terminate;
// returns size of instruction (in bytes) // returns size of instruction (in bytes)
int disassemble(cpu *const c, console *const cnsl, const int pc, const bool instruction_only) int disassemble(cpu *const c, console *const cnsl, const int pc, const bool instruction_only)
{ {
@ -72,7 +70,7 @@ std::map<std::string, std::string> split(const std::vector<std::string> & kv_arr
return out; return out;
} }
void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interrupt_emulation, const bool tracing_in) void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const stop_event, const bool tracing_in)
{ {
int32_t trace_start_addr = -1; int32_t trace_start_addr = -1;
bool tracing = tracing_in; bool tracing = tracing_in;
@ -83,9 +81,8 @@ void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interru
bool single_step = false; bool single_step = false;
while(!terminate) { while(*stop_event != EVENT_TERMINATE) {
bool temp = terminate; std::string cmd = cnsl->read_line(format("%d", stop_event->load()));
std::string cmd = cnsl->read_line(format("%d%d", event, temp));
auto parts = split(cmd, " "); auto parts = split(cmd, " ");
auto kv = split(parts, "="); auto kv = split(parts, "=");
@ -184,9 +181,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interru
#if defined(ESP32) #if defined(ESP32)
ESP.restart(); ESP.restart();
#else #else
terminate = false; *stop_event = EVENT_NONE;
event = 0;
c->reset(); c->reset();
#endif #endif
@ -222,7 +217,7 @@ void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interru
*cnsl->get_running_flag() = true; *cnsl->get_running_flag() = true;
while(!event && !*interrupt_emulation) { while(*stop_event == EVENT_NONE) {
c->step_a(); c->step_a();
if (trace_start_addr != -1 && c->getPC() == trace_start_addr) if (trace_start_addr != -1 && c->getPC() == trace_start_addr)
@ -249,12 +244,10 @@ void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interru
cnsl->debug("MIPS: %.2f, relative speed: %.2f%%", speed.first, speed.second); cnsl->debug("MIPS: %.2f, relative speed: %.2f%%", speed.first, speed.second);
} }
if (*interrupt_emulation) { if (*stop_event == EVENT_INTERRUPT) {
single_step = true; single_step = true;
event = 0; *stop_event = EVENT_NONE;
*interrupt_emulation = false;
} }
} }
} }

View file

@ -1,4 +1,4 @@
#include "bus.h" #include "bus.h"
#include "console.h" #include "console.h"
void debugger(console *const cnsl, bus *const b, std::atomic_bool *const interrupt_emulation, const bool tracing); void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const stop_event, const bool tracing);

2
gen.h
View file

@ -4,6 +4,8 @@
extern bool trace_output; extern bool trace_output;
typedef enum { EVENT_NONE = 0, EVENT_HALT, EVENT_INTERRUPT, EVENT_TERMINATE } stop_event_t;
#if defined(ESP32) #if defined(ESP32)
#define D(...) do { } while(0); #define D(...) do { } while(0);
#else #else

View file

@ -24,8 +24,7 @@
typedef enum { BL_NONE, BL_RK05, BL_RL02 } bootloader_t; typedef enum { BL_NONE, BL_RK05, BL_RL02 } bootloader_t;
bool withUI { false }; bool withUI { false };
uint32_t event { 0 }; std::atomic_uint32_t event { 0 };
std::atomic_bool terminate { false };
std::atomic_bool *running { nullptr }; std::atomic_bool *running { nullptr };
bool trace_output { false }; bool trace_output { false };
@ -231,7 +230,7 @@ void sw_handler(int s)
else { else {
fprintf(stderr, "Terminating...\n"); fprintf(stderr, "Terminating...\n");
terminate = true; event = EVENT_TERMINATE;
} }
} }
@ -342,13 +341,13 @@ int main(int argc, char *argv[])
std::atomic_bool interrupt_emulation { false }; std::atomic_bool interrupt_emulation { false };
if (withUI) if (withUI)
cnsl = new console_ncurses(&terminate, &interrupt_emulation, b); cnsl = new console_ncurses(&event, b);
else { else {
fprintf(stderr, "This PDP-11 emulator is called \"kek\" (reason for that is forgotten) and was written by Folkert van Heusden.\n"); fprintf(stderr, "This PDP-11 emulator is called \"kek\" (reason for that is forgotten) and was written by Folkert van Heusden.\n");
fprintf(stderr, "Built on: " __DATE__ " " __TIME__ "\n"); fprintf(stderr, "Built on: " __DATE__ " " __TIME__ "\n");
cnsl = new console_posix(&terminate, &interrupt_emulation, b); cnsl = new console_posix(&event, b);
} }
if (rk05_files.empty() == false) if (rk05_files.empty() == false)
@ -390,21 +389,24 @@ int main(int argc, char *argv[])
cnsl->start_thread(); cnsl->start_thread();
if (run_debugger) if (run_debugger)
debugger(cnsl, b, &interrupt_emulation, tracing); debugger(cnsl, b, &event, tracing);
else { else {
c->emulation_start(); // for statistics c->emulation_start(); // for statistics
*running = true; *running = true;
// TODO combine event, interrupt_emulation and terminate into one thing for(;;) {
while(!event) { while(!event) {
if (interrupt_emulation)
break;
c->step_a(); c->step_a();
c->step_b(); c->step_b();
} }
uint32_t stop_event = event.exchange(EVENT_NONE);
if (stop_event == EVENT_HALT || stop_event == EVENT_INTERRUPT || stop_event == EVENT_TERMINATE)
break;
}
auto stats = c->get_mips_rel_speed(); auto stats = c->get_mips_rel_speed();
printf("MIPS: %.2f, running speed: %.2f%%\n", stats.first, stats.second); printf("MIPS: %.2f, running speed: %.2f%%\n", stats.first, stats.second);
@ -412,7 +414,7 @@ int main(int argc, char *argv[])
*running = false; *running = false;
} }
terminate = true; event = EVENT_TERMINATE;
delete cnsl; delete cnsl;