Split the CPU regulator thread to it's own file

Removed it fron the Nuklear file, as it's actually not doign anything UI
based.
Also cleanup up type names etc

Signed-off-by: Michel Pollet <buserror@gmail.com>
This commit is contained in:
Michel Pollet 2023-10-28 07:23:06 +01:00
parent 938be1724e
commit af6ff70155
3 changed files with 200 additions and 149 deletions

View File

@ -16,6 +16,7 @@
#include "mii.h" #include "mii.h"
#include "mii_bank.h" #include "mii_bank.h"
#include "mii_sw.h" #include "mii_sw.h"
#include "mii_thread.h"
#define NK_INCLUDE_FIXED_TYPES #define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO #define NK_INCLUDE_STANDARD_IO
@ -67,139 +68,6 @@ static GLuint screen_texture;
static struct nk_image screen_nk; static struct nk_image screen_nk;
#include <time.h>
typedef uint64_t mii_time_t;
enum {
MII_TIME_RES = 1,
MII_TIME_SECOND = 1000000,
MII_TIME_MS = (MII_TIME_SECOND/1000),
};
mii_time_t
mii_get_time()
{
struct timespec tim;
clock_gettime(CLOCK_MONOTONIC_RAW, &tim);
uint64_t time = ((uint64_t)tim.tv_sec) * (1000000 / MII_TIME_RES) +
tim.tv_nsec / (1000 * MII_TIME_RES);
return time;
}
#include <pthread.h>
#include "fifo_declare.h"
static pthread_t mii_thread;
static bool mii_thread_running = false;
//static mii_trace_t mii_trace = {};
float default_fps = 60;
enum {
SIGNAL_RESET,
SIGNAL_STOP,
SIGNAL_STEP,
SIGNAL_RUN,
};
typedef struct {
uint8_t cmd;
uint8_t data;
} signal_t;
DECLARE_FIFO(signal_t, signal_fifo, 16);
DEFINE_FIFO(signal_t, signal_fifo);
signal_fifo_t signal_fifo;
static void *mii_thread_func(void *arg)
{
mii_t *mii = (mii_t *) arg;
mii_thread_running = true;
__uint128_t last_cycles = mii->cycles;
uint32_t running = 1;
unsigned long target_fps_us = 1000000 / default_fps;
long sleep_time = target_fps_us;
//mii_time_t base = mii_get_time(NULL);
uint32_t last_frame = mii->video.frame_count;
mii_time_t last_frame_stamp = mii_get_time();
while (mii_thread_running) {
signal_t sig;
while (!signal_fifo_isempty(&signal_fifo)) {
sig = signal_fifo_read(&signal_fifo);
switch (sig.cmd) {
case SIGNAL_RESET:
mii_reset(mii, sig.data);
break;
case SIGNAL_STOP:
mii_dump_run_trace(mii);
mii_dump_trace_state(mii);
mii->state = MII_STOPPED;
break;
case SIGNAL_STEP:
mii->state = MII_STEP;
running = 1;
break;
case SIGNAL_RUN:
mii->state = MII_RUNNING;
last_frame_stamp = mii_get_time();
running = 1;
break;
}
}
if (mii->state != MII_STOPPED)
mii_run(mii);
switch (mii->state) {
case MII_STOPPED:
usleep(1000);
break;
case MII_STEP:
if (running) {
running--;
mii_dump_trace_state(mii);
usleep(1000);
running = 1;
if (mii->trace.step_inst)
mii->trace.step_inst--;
if (mii->trace.step_inst == 0)
mii->state = MII_STOPPED;
}
break;
case MII_RUNNING:
break;
case MII_TERMINATE:
mii_thread_running = false;
break;
}
if (mii->video.frame_count != last_frame) {
sleep_time = target_fps_us;
mii_time_t now = mii_get_time();
if (mii->state == MII_RUNNING) {
mii_time_t delta = now - last_frame_stamp;
// printf("frame time %d/%d sleep time %d\n",
// (int)delta, (int)target_fps_us,
// (int)target_fps_us - delta);
sleep_time = target_fps_us - delta;
if (sleep_time < 0)
sleep_time = 0;
last_frame = mii->video.frame_count;
while (last_frame_stamp <= now)
last_frame_stamp += target_fps_us;
// calculate the MHz
__uint128_t cycles = mii->cycles;
__uint128_t delta_cycles = cycles - last_cycles;
last_cycles = cycles;
mii->speed_current = delta_cycles / (float)target_fps_us;
}
usleep(sleep_time);
}
}
mii_dispose(mii);
return NULL;
}
extern struct nk_font *nk_main_font; extern struct nk_font *nk_main_font;
struct nk_font *nk_mono_font = NULL; struct nk_font *nk_mono_font = NULL;
@ -255,8 +123,8 @@ mii_nuklear_init(
screen_texture, MII_VRAM_WIDTH, MII_VRAM_HEIGHT, screen_texture, MII_VRAM_WIDTH, MII_VRAM_HEIGHT,
nk_rect(0, 0, MII_VIDEO_WIDTH, MII_VIDEO_HEIGHT)); nk_rect(0, 0, MII_VIDEO_WIDTH, MII_VIDEO_HEIGHT));
/* start the thread */ /* start the CPU/emulator thread */
pthread_create(&mii_thread, NULL, mii_thread_func, mii); mii_thread_start(mii);
} }
@ -271,7 +139,8 @@ mii_nuklear_handle_input(
{ {
struct nk_input *in = &ctx->input; struct nk_input *in = &ctx->input;
if (in->keyboard.text_len) { if (in->keyboard.text_len) {
// printf("INPUT %d %s\n", in->keyboard.text_len, in->keyboard.text); // printf("INPUT %d %02x %s\n",
// in->keyboard.text_len, in->keyboard.text[0], in->keyboard.text);
if (in->keyboard.text_len < 4) { if (in->keyboard.text_len < 4) {
mii_keypress(mii, in->keyboard.text[0]); mii_keypress(mii, in->keyboard.text[0]);
} else if (in->keyboard.text_len > 1) { } else if (in->keyboard.text_len > 1) {
@ -283,35 +152,35 @@ mii_nuklear_handle_input(
if (down) { if (down) {
if (key == 0xffc9) { // F12 if (key == 0xffc9) { // F12
if (nk_input_is_key_down(in, NK_KEY_CTRL)) { if (nk_input_is_key_down(in, NK_KEY_CTRL)) {
signal_t sig = { mii_th_signal_t sig = {
.cmd = SIGNAL_RESET, .cmd = SIGNAL_RESET,
.data = nk_input_is_key_down(in, NK_KEY_SHIFT) .data = nk_input_is_key_down(in, NK_KEY_SHIFT)
}; };
signal_fifo_write(&signal_fifo, sig); mii_th_fifo_write(mii_thread_get_fifo(mii), sig);
printf("RESET\n"); printf("RESET\n");
} }
} else if (key == 0xffc8) { // F11 } else if (key == 0xffc8) { // F11
if (nk_input_is_key_down(in, NK_KEY_CTRL)) { if (nk_input_is_key_down(in, NK_KEY_CTRL)) {
signal_t sig = { mii_th_signal_t sig = {
.cmd = SIGNAL_STOP, .cmd = SIGNAL_STOP,
}; };
signal_fifo_write(&signal_fifo, sig); mii_th_fifo_write(mii_thread_get_fifo(mii), sig);
printf("STOP\n"); printf("STOP\n");
} }
} else if (key == 0xffc7) { // F10 } else if (key == 0xffc7) { // F10
if (nk_input_is_key_down(in, NK_KEY_CTRL)) { if (nk_input_is_key_down(in, NK_KEY_CTRL)) {
signal_t sig = { mii_th_signal_t sig = {
.cmd = SIGNAL_STEP, .cmd = SIGNAL_STEP,
}; };
signal_fifo_write(&signal_fifo, sig); mii_th_fifo_write(mii_thread_get_fifo(mii), sig);
printf("STEP\n"); printf("STEP\n");
} }
} else if (key == 0xffc6) { // F9 } else if (key == 0xffc6) { // F9
if (nk_input_is_key_down(in, NK_KEY_CTRL)) { if (nk_input_is_key_down(in, NK_KEY_CTRL)) {
signal_t sig = { mii_th_signal_t sig = {
.cmd = SIGNAL_RUN, .cmd = SIGNAL_RUN,
}; };
signal_fifo_write(&signal_fifo, sig); mii_th_fifo_write(mii_thread_get_fifo(mii), sig);
printf("RUN\n"); printf("RUN\n");
} }
} else if (key == 0xffc2) { // F5 } else if (key == 0xffc2) { // F5
@ -336,7 +205,7 @@ mii_nuklear_handle_input(
} }
in->keyboard.text_len = 0; in->keyboard.text_len = 0;
} else { } else {
signal_t sig = {.cmd = -1 }; mii_th_signal_t sig = {.cmd = -1 };
if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) if (nk_input_is_key_pressed(in, NK_KEY_ENTER))
sig.data = 0x0d; sig.data = 0x0d;
else if (nk_input_is_key_pressed(in, NK_KEY_BACKSPACE)) else if (nk_input_is_key_pressed(in, NK_KEY_BACKSPACE))
@ -354,7 +223,7 @@ mii_nuklear_handle_input(
else if (nk_input_is_key_pressed(in, NK_KEY_ESCAPE)) else if (nk_input_is_key_pressed(in, NK_KEY_ESCAPE))
sig.data = 0x1b; sig.data = 0x1b;
if (sig.data) { if (sig.data) {
// signal_fifo_write(&signal_fifo, sig); // mii_th_fifo_write(mii_thread_get_fifo(mii), sig);
// printf("Key %d\n", sig.data); // printf("Key %d\n", sig.data);
mii_keypress(mii, sig.data); mii_keypress(mii, sig.data);
} }
@ -585,13 +454,13 @@ mii_nuklear(
nk_layout_row_static(ctx, 30, 30, 3); nk_layout_row_static(ctx, 30, 30, 3);
if (nk_button_symbol(ctx, NK_SYMBOL_RECT_SOLID)) { if (nk_button_symbol(ctx, NK_SYMBOL_RECT_SOLID)) {
signal_fifo_write(&signal_fifo, (signal_t){.cmd = SIGNAL_STOP}); mii_th_fifo_write(mii_thread_get_fifo(mii), (mii_th_signal_t){.cmd = SIGNAL_STOP});
} }
if (nk_button_symbol(ctx, NK_SYMBOL_PLUS)) { if (nk_button_symbol(ctx, NK_SYMBOL_PLUS)) {
signal_fifo_write(&signal_fifo, (signal_t){.cmd = SIGNAL_STEP}); mii_th_fifo_write(mii_thread_get_fifo(mii), (mii_th_signal_t){.cmd = SIGNAL_STEP});
} }
if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT)) { if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT)) {
signal_fifo_write(&signal_fifo, (signal_t){.cmd = SIGNAL_RUN}); mii_th_fifo_write(mii_thread_get_fifo(mii), (mii_th_signal_t){.cmd = SIGNAL_RUN});
} }
nk_layout_row_dynamic(ctx, 20, 3); nk_layout_row_dynamic(ctx, 20, 3);
{ {

146
nuklear/mii_thread.c Normal file
View File

@ -0,0 +1,146 @@
/*
* mii_thread.c
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "mii.h"
#include "mii_thread.h"
typedef uint64_t mii_time_t;
enum {
MII_TIME_RES = 1,
MII_TIME_SECOND = 1000000,
MII_TIME_MS = (MII_TIME_SECOND/1000),
};
mii_time_t
mii_get_time()
{
struct timespec tim;
clock_gettime(CLOCK_MONOTONIC_RAW, &tim);
uint64_t time = ((uint64_t)tim.tv_sec) * (1000000 / MII_TIME_RES) +
tim.tv_nsec / (1000 * MII_TIME_RES);
return time;
}
static pthread_t mii_thread;
static bool mii_thread_running = false;
static float default_fps = 60;
mii_th_fifo_t signal_fifo;
static void *
mii_thread_func(
void *arg)
{
mii_t *mii = (mii_t *) arg;
mii_thread_running = true;
__uint128_t last_cycles = mii->cycles;
uint32_t running = 1;
unsigned long target_fps_us = 1000000 / default_fps;
long sleep_time = target_fps_us;
//mii_time_t base = mii_get_time(NULL);
uint32_t last_frame = mii->video.frame_count;
mii_time_t last_frame_stamp = mii_get_time();
while (mii_thread_running) {
mii_th_signal_t sig;
while (!mii_th_fifo_isempty(&signal_fifo)) {
sig = mii_th_fifo_read(&signal_fifo);
switch (sig.cmd) {
case SIGNAL_RESET:
mii_reset(mii, sig.data);
break;
case SIGNAL_STOP:
mii_dump_run_trace(mii);
mii_dump_trace_state(mii);
mii->state = MII_STOPPED;
break;
case SIGNAL_STEP:
mii->state = MII_STEP;
running = 1;
break;
case SIGNAL_RUN:
mii->state = MII_RUNNING;
last_frame_stamp = mii_get_time();
running = 1;
break;
}
}
if (mii->state != MII_STOPPED)
mii_run(mii);
switch (mii->state) {
case MII_STOPPED:
usleep(1000);
break;
case MII_STEP:
if (running) {
running--;
mii_dump_trace_state(mii);
usleep(1000);
running = 1;
if (mii->trace.step_inst)
mii->trace.step_inst--;
if (mii->trace.step_inst == 0)
mii->state = MII_STOPPED;
}
break;
case MII_RUNNING:
break;
case MII_TERMINATE:
mii_thread_running = false;
break;
}
if (mii->video.frame_count != last_frame) {
sleep_time = target_fps_us;
mii_time_t now = mii_get_time();
if (mii->state == MII_RUNNING) {
mii_time_t delta = now - last_frame_stamp;
// printf("frame time %d/%d sleep time %d\n",
// (int)delta, (int)target_fps_us,
// (int)target_fps_us - delta);
sleep_time = target_fps_us - delta;
if (sleep_time < 0)
sleep_time = 0;
last_frame = mii->video.frame_count;
while (last_frame_stamp <= now)
last_frame_stamp += target_fps_us;
// calculate the MHz
__uint128_t cycles = mii->cycles;
__uint128_t delta_cycles = cycles - last_cycles;
last_cycles = cycles;
mii->speed_current = delta_cycles / (float)target_fps_us;
}
usleep(sleep_time);
}
}
mii_dispose(mii);
return NULL;
}
void
mii_thread_start(
mii_t *mii)
{
const mii_th_fifo_t zero = {};
signal_fifo = zero;
pthread_create(&mii_thread, NULL, mii_thread_func, mii);
}
struct mii_th_fifo_t*
mii_thread_get_fifo(
struct mii_t *mii)
{
return &signal_fifo;
}

36
nuklear/mii_thread.h Normal file
View File

@ -0,0 +1,36 @@
/*
* mii_thread.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <stdint.h>
#include "fifo_declare.h"
enum {
SIGNAL_RESET,
SIGNAL_STOP,
SIGNAL_STEP,
SIGNAL_RUN,
};
typedef struct mii_th_signal_t {
uint8_t cmd;
uint8_t data;
} mii_th_signal_t;
DECLARE_FIFO(mii_th_signal_t, mii_th_fifo, 16);
DEFINE_FIFO(mii_th_signal_t, mii_th_fifo);
struct mii_t;
void
mii_thread_start(
struct mii_t *mii);
struct mii_th_fifo_t*
mii_thread_get_fifo(
struct mii_t *mii);