// file : ui/curses/ui.c // project : Salis-VM // author : Paul Oliver // index: // [section] includes // [section] macros/enums // [section] gfx globals // [section] tui globals // [section] gfx functions // [section] tui functions // [section] main // ---------------------------------------------------------------------------- // [section] includes // ---------------------------------------------------------------------------- #include #define NCURSES_WIDECHAR 1 #include #include #include #include #include #include #include #include #include "arch.h" #include "arch_spec.h" #include "compress.h" #include "logger.h" #include "salis.h" // ---------------------------------------------------------------------------- // [section] macros/enums // ---------------------------------------------------------------------------- #define LOG_LINE_COUNT 0x400 #define NCURSES_CTRL(x) (x & 0x1f) #define PANE_WIDTH 27 #define PANE_WIDTH_AND_MARGIN (PANE_WIDTH + 2) #define PROC_FIELD_WIDTH 21 #define PROC_PAGE_LINES 12 #define FPS_MIN 10 #define FPS_MAX 20 enum UIPage { PAGE_CORE, PAGE_PROCESS, PAGE_WORLD, PAGE_IPC, PAGE_LOG, PAGE_COUNT, }; enum UIColorPair { PAIR_NORMAL, PAIR_HEADER, PAIR_LIVE_PROC, PAIR_SELECTED_PROC, PAIR_FREE_CELL, PAIR_ALLOC_CELL, PAIR_MEM_BLOCK_START, PAIR_SELECTED_MB1, PAIR_SELECTED_MB2, PAIR_SELECTED_IP, PAIR_SELECTED_SP, PAIR_LOG_TRACE, PAIR_LOG_INFO, PAIR_LOG_ATTENTION, }; enum UILogLevel { TRACE, INFO, ATTENTION, }; // ---------------------------------------------------------------------------- // [section] gfx globals // ---------------------------------------------------------------------------- static uint64_t g_gfx_vsiz; static uint64_t *g_gfx_inst; static uint64_t *g_gfx_mall; static uint64_t *g_gfx_mbst; static uint64_t *g_gfx_mb0s; static uint64_t *g_gfx_mb1s; static uint64_t *g_gfx_ipas; static uint64_t *g_gfx_spas; static const wchar_t *g_zoomed_symbols = ( L"⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟" L"⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿" L"⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟" L"⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿" ); // ---------------------------------------------------------------------------- // [section] tui globals // ---------------------------------------------------------------------------- static bool g_exit; static bool g_running; static unsigned g_core; static unsigned g_page; static char *g_line_buff; static bool g_proc_genes; static uint64_t g_proc_scroll; static uint64_t g_proc_field_scroll; static uint64_t g_proc_gene_scroll; static uint64_t g_proc_selected; static uint64_t g_wrld_pos; static uint64_t g_wrld_zoom; static bool g_wcursor_mode; static int g_wcursor_x; static int g_wcursor_y; static uint64_t g_wcursor_pointed; static uint64_t g_log_cnt; static unsigned g_log_ptr; static unsigned g_log_scroll; static enum UILogLevel g_log_levels[LOG_LINE_COUNT]; static char g_logs[LOG_LINE_COUNT][LOG_BUFFER_SIZE]; static uint64_t g_vlin; static uint64_t g_vsiz; static uint64_t g_vlin_rng; static uint64_t g_vsiz_rng; static uint64_t g_ivpt_scroll; static uint64_t g_step_block; static float g_steps_per_sec; // ---------------------------------------------------------------------------- // [section] gfx functions // ---------------------------------------------------------------------------- static void gfx_init(uint64_t vsiz) { assert(vsiz); g_gfx_vsiz = vsiz; g_gfx_inst = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_mall = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_mbst = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_mb0s = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_mb1s = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_ipas = calloc(g_gfx_vsiz, sizeof(uint64_t)); g_gfx_spas = calloc(g_gfx_vsiz, sizeof(uint64_t)); assert(g_gfx_inst); assert(g_gfx_mall); assert(g_gfx_mbst); assert(g_gfx_mb0s); assert(g_gfx_mb1s); assert(g_gfx_ipas); assert(g_gfx_spas); } static void gfx_free(void) { if (g_gfx_vsiz == 0) { return; } assert(g_gfx_inst); assert(g_gfx_mall); assert(g_gfx_mbst); assert(g_gfx_mb0s); assert(g_gfx_mb1s); assert(g_gfx_ipas); assert(g_gfx_spas); g_gfx_vsiz = 0; free(g_gfx_inst); free(g_gfx_mall); free(g_gfx_mbst); free(g_gfx_mb0s); free(g_gfx_mb1s); free(g_gfx_ipas); free(g_gfx_spas); g_gfx_inst = NULL; g_gfx_mall = NULL; g_gfx_mbst = NULL; g_gfx_mb0s = NULL; g_gfx_mb1s = NULL; g_gfx_ipas = NULL; g_gfx_spas = NULL; } static void gfx_resize(uint64_t vsiz) { assert(vsiz); gfx_free(); gfx_init(vsiz); } static void gfx_render_inst(const struct Core *core, uint64_t pos, uint64_t zoom) { assert(core); for (uint64_t i = 0; i < g_gfx_vsiz; i++) { g_gfx_inst[i] = 0; g_gfx_mall[i] = 0; for (uint64_t j = 0; j < zoom; j++) { uint64_t addr = pos + (i * zoom) + j; g_gfx_inst[i] += mvec_get_byte(core, addr); g_gfx_mall[i] += mvec_is_alloc(core, addr) ? 1 : 0; } } } static void gfx_clear_array(uint64_t *arry) { assert(arry); memset(arry, 0, g_gfx_vsiz * sizeof(uint64_t)); } #if defined(ARCH_SPEC_MVEC_LOOP) static void gfx_accumulate_pixel(uint64_t pos, uint64_t zoom, uint64_t pixa, uint64_t *arry) { assert(arry); uint64_t beg_mod = pos % MVEC_SIZE; uint64_t end_mod = beg_mod + (g_gfx_vsiz * zoom); uint64_t pix_mod = pixa % MVEC_SIZE; #if !defined(NDEBUG) uint64_t inc_cnt = 0; #endif while (pix_mod < end_mod) { if (pix_mod >= beg_mod && pix_mod < end_mod) { uint64_t pixi = (pix_mod - beg_mod) / zoom; assert(pixi < g_gfx_vsiz); arry[pixi]++; #if !defined(NDEBUG) inc_cnt++; #endif } pix_mod += MVEC_SIZE; } #if !defined(NDEBUG) if (zoom != 1) { assert(inc_cnt <= 2); } #endif } #else static void gfx_accumulate_pixel(uint64_t pos, uint64_t zoom, uint64_t pixa, uint64_t *arry) { assert(arry); uint64_t end = pos + (g_gfx_vsiz * zoom); if (pixa < pos || pixa >= end) { return; } uint64_t pixi = (pixa - pos) / zoom; assert(pixi < g_gfx_vsiz); arry[pixi]++; } #endif static void gfx_render_mbst(const struct Core *core, uint64_t pos, uint64_t zoom) { assert(core); gfx_clear_array(g_gfx_mbst); for (uint64_t pix = core->pfst; pix <= core->plst; pix++) { uint64_t mb0a = arch_proc_get_mb0_addr(core, pix); uint64_t mb1a = arch_proc_get_mb1_addr(core, pix); gfx_accumulate_pixel(pos, zoom, mb0a, g_gfx_mbst); if (arch_proc_get_mb1_size(core, pix)) { gfx_accumulate_pixel(pos, zoom, mb1a, g_gfx_mbst); } } } static void gfx_render_mb0s(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t psel) { assert(core); gfx_clear_array(g_gfx_mb0s); if (psel < core->pfst || psel > core->plst) { return; } uint64_t mb0a = arch_proc_get_mb0_addr(core, psel); uint64_t mb0s = arch_proc_get_mb0_size(core, psel); for (uint64_t i = 0; i < mb0s; i++) { gfx_accumulate_pixel(pos, zoom, mb0a + i, g_gfx_mb0s); } } static void gfx_render_mb1s(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t psel) { assert(core); gfx_clear_array(g_gfx_mb1s); if (psel < core->pfst || psel > core->plst) { return; } uint64_t mb1a = arch_proc_get_mb1_addr(core, psel); uint64_t mb1s = arch_proc_get_mb1_size(core, psel); for (uint64_t i = 0; i < mb1s; i++) { gfx_accumulate_pixel(pos, zoom, mb1a + i, g_gfx_mb1s); } } static void gfx_render_ipas(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t psel) { assert(core); gfx_clear_array(g_gfx_ipas); if (psel < core->pfst || psel > core->plst) { return; } gfx_accumulate_pixel(pos, zoom, arch_proc_get_ip_addr(core, psel), g_gfx_ipas); } static void gfx_render_spas(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t psel) { assert(core); gfx_clear_array(g_gfx_spas); if (psel < core->pfst || psel > core->plst) { return; } gfx_accumulate_pixel(pos, zoom, arch_proc_get_sp_addr(core, psel), g_gfx_spas); } static void gfx_render(const struct Core *core, uint64_t pos, uint64_t zoom, uint64_t psel) { assert(core); gfx_render_inst(core, pos, zoom); gfx_render_mbst(core, pos, zoom); gfx_render_mb0s(core, pos, zoom, psel); gfx_render_mb1s(core, pos, zoom, psel); gfx_render_ipas(core, pos, zoom, psel); gfx_render_spas(core, pos, zoom, psel); } // ---------------------------------------------------------------------------- // [section] tui functions // ---------------------------------------------------------------------------- static void tui_line_buff_free(void) { if (g_line_buff) { free(g_line_buff); } g_line_buff = NULL; } static void tui_line_buff_resize(void) { tui_line_buff_free(); g_line_buff = calloc(COLS + 1, sizeof(char)); } static void tui_line(bool clear, int line, int color, int attr, const char *format, ...) { assert(line >= 0); assert(format); if (line >= LINES) { return; } if (clear) { move(line, 0); clrtoeol(); } va_list args; va_start(args, format); attron(COLOR_PAIR(color) | attr); vsnprintf(g_line_buff, COLS, format, args); mvprintw(line, 1, "%s", g_line_buff); attroff(COLOR_PAIR(color) | attr); va_end(args); } static void tui_clear_line(int l) { tui_line(true, l, PAIR_NORMAL, A_NORMAL, ""); } static void tui_field(int line, int col, int color, int attr, const char *format, ...) { assert(line >= 0); assert(col >= 0); assert(format); if (line >= LINES || col >= COLS) { return; } va_list args; va_start(args, format); attron(COLOR_PAIR(color) | attr); vsnprintf(g_line_buff, COLS - col, format, args); mvprintw(line, col, "%s", g_line_buff); attroff(COLOR_PAIR(color) | attr); va_end(args); } static void tui_str_field(int l, const char *label, const char *value) { assert(label); assert(strlen(label) <= 4); assert(value); tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %18s", label, value); } static void tui_ulx_field(int l, const char *label, uint64_t value) { assert(label); assert(strlen(label) <= 4); tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18lx", label, value); } static void tui_uld_field(int l, const char *label, uint64_t value) { assert(label); assert(strlen(label) <= 4); tui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18ld", label, value); } static void tui_print_core(int l) { tui_line(false, ++l, PAIR_HEADER, A_BOLD, "CORE [%d]", g_core); tui_ulx_field(++l, "cycl", g_cores[g_core].cycl); tui_ulx_field(++l, "mall", g_cores[g_core].mall); tui_ulx_field(++l, "mut0", g_cores[g_core].muta[0]); tui_ulx_field(++l, "mut1", g_cores[g_core].muta[1]); tui_ulx_field(++l, "mut2", g_cores[g_core].muta[2]); tui_ulx_field(++l, "mut3", g_cores[g_core].muta[3]); tui_ulx_field(++l, "pnum", g_cores[g_core].pnum); tui_ulx_field(++l, "pcap", g_cores[g_core].pcap); tui_ulx_field(++l, "pfst", g_cores[g_core].pfst); tui_ulx_field(++l, "plst", g_cores[g_core].plst); tui_ulx_field(++l, "pcur", g_cores[g_core].pcur); tui_ulx_field(++l, "psli", g_cores[g_core].psli); tui_ulx_field(++l, "ivpt", g_cores[g_core].ivpt); } // ---------------------------------------------------------------------------- // [section] main // ---------------------------------------------------------------------------- int main(void) { return 0; }