diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/dummy.c | 152 | ||||
| -rw-r--r-- | src/arch/salis-v1.c | 875 | ||||
| -rw-r--r-- | src/bench.c | 49 | ||||
| -rw-r--r-- | src/graphics.c | 238 | ||||
| -rw-r--r-- | src/salis.c | 811 | ||||
| -rw-r--r-- | src/ui/curses.c | 965 | ||||
| -rw-r--r-- | src/ui/daemon.c | 63 |
7 files changed, 0 insertions, 3153 deletions
diff --git a/src/arch/dummy.c b/src/arch/dummy.c deleted file mode 100644 index 7a47900..0000000 --- a/src/arch/dummy.c +++ /dev/null @@ -1,152 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * Defines a minimal viable architecture for the Salis VM. Useful for - * debugging and benchmarking. Also, this file can be used as a template when - * implementing a real architecture. - */ - -bool proc_is_live(const Core *core, u64 pix); - -#define PROC_FIELDS \ - PROC_FIELD(u64, ip) \ - PROC_FIELD(u64, sp) \ - PROC_FIELD(u64, mb0a) \ - PROC_FIELD(u64, mb0s) \ - PROC_FIELD(u64, mb1a) \ - PROC_FIELD(u64, mb1s) - -struct Proc { -#define PROC_FIELD(type, name) type name; - PROC_FIELDS -#undef PROC_FIELD -}; - -#define MNEMONIC_BUFF_SIZE (0x10) - -const wchar_t *g_arch_byte_symbols = ( - L"⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟" - L"⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿" - L"⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟" - L"⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿" -); - -u64 arch_proc_mb0_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_mb0_size(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_mb1_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_mb1_size(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_ip_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_sp_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 0; -} - -u64 arch_proc_slice(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 1; -} - -void arch_on_proc_kill(Core *core) { - assert(core); - assert(core->pnum > 1); - - (void)core; -} - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -void arch_anc_init(Core *core, u64 size) { - assert(core); - - (void)core; - (void)size; -} -#endif - -void arch_proc_step(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return; -} - -#ifndef NDEBUG -void arch_validate_proc(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - assert(true); -} -#endif - -wchar_t arch_symbol(u8 inst) { - return g_arch_byte_symbols[inst]; -} - -void arch_mnemonic(u8 inst, char *buff) { - assert(buff); - - snprintf(buff, MNEMONIC_BUFF_SIZE, "dummy %#x", inst); -} diff --git a/src/arch/salis-v1.c b/src/arch/salis-v1.c deleted file mode 100644 index 1085883..0000000 --- a/src/arch/salis-v1.c +++ /dev/null @@ -1,875 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * This is based on the original VM architecture in salis-v1: - * https://git.pauloliver.dev/salis-v1/about/ - */ - -bool mvec_is_alloc(const Core *core, u64 pix); -void mvec_alloc(Core *core, u64 addr); -void mvec_free(Core *core, u64 addr); -u8 mvec_get_inst(const Core *core, u64 addr); -void mvec_set_inst(Core *core, u64 addr, u8 inst); -bool mvec_is_proc_owner(const Core *core, u64 addr, u64 pix); -void proc_new(Core *core, const Proc *proc); -bool proc_is_live(const Core *core, u64 pix); -const Proc *proc_get(const Core *core, u64 pix); -Proc *proc_fetch(Core *core, u64 pix); - -#define INST_LIST \ - INST(noop, L' ') \ - INST(nop0, L'0') \ - INST(nop1, L'1') \ - INST(nop2, L'2') \ - INST(nop3, L'3') \ - \ - INST(jmpb, L'(') \ - INST(jmpf, L')') \ - INST(adrb, L'[') \ - INST(adrf, L']') \ - INST(ifnz, L'?') \ - \ - INST(allb, L'{') \ - INST(allf, L'}') \ - INST(bswp, L'%') \ - INST(bclr, L'|') \ - INST(splt, L'$') \ - \ - INST(addn, L'+') \ - INST(subn, L'-') \ - INST(muln, L'*') \ - INST(divn, L'/') \ - INST(incn, L'^') \ - INST(decn, L'v') \ - INST(notn, L'!') \ - INST(shfl, L'<') \ - INST(shfr, L'>') \ - INST(zero, L'z') \ - INST(unit, L'u') \ - \ - INST(pshn, L'#') \ - INST(popn, L'~') \ - \ - INST(load, L'.') \ - INST(wrte, L':') \ - INST(dupl, L'"') \ - INST(swap, L'x') \ - \ - INST(keya, L'a') \ - INST(keyb, L'b') \ - INST(keyc, L'c') \ - INST(keyd, L'd') \ - INST(keye, L'e') \ - INST(keyf, L'f') \ - INST(keyg, L'g') \ - INST(keyh, L'h') \ - INST(keyi, L'i') \ - INST(keyj, L'j') \ - INST(keyk, L'k') \ - INST(keyl, L'l') \ - INST(keym, L'm') \ - INST(keyn, L'n') \ - INST(keyo, L'o') \ - INST(keyp, L'p') \ - \ - INST(loka, L'A') \ - INST(lokb, L'B') \ - INST(lokc, L'C') \ - INST(lokd, L'D') \ - INST(loke, L'E') \ - INST(lokf, L'F') \ - INST(lokg, L'G') \ - INST(lokh, L'H') \ - INST(loki, L'I') \ - INST(lokj, L'J') \ - INST(lokk, L'K') \ - INST(lokl, L'L') \ - INST(lokm, L'M') \ - INST(lokn, L'N') \ - INST(loko, L'O') \ - INST(lokp, L'P') - -#define MNEMONIC_BUFF_SIZE (0x5) - -enum sinst { -#define INST(name, symb) name, - INST_LIST -#undef INST - INST_COUNT -}; - -#define PROC_FIELDS \ - PROC_FIELD(u64, ip) \ - PROC_FIELD(u64, sp) \ - PROC_FIELD(u64, mb0a) \ - PROC_FIELD(u64, mb0s) \ - PROC_FIELD(u64, mb1a) \ - PROC_FIELD(u64, mb1s) \ - PROC_FIELD(u64, r0x) \ - PROC_FIELD(u64, r1x) \ - PROC_FIELD(u64, r2x) \ - PROC_FIELD(u64, r3x) \ - PROC_FIELD(u64, s0) \ - PROC_FIELD(u64, s1) \ - PROC_FIELD(u64, s2) \ - PROC_FIELD(u64, s3) \ - PROC_FIELD(u64, s4) \ - PROC_FIELD(u64, s5) \ - PROC_FIELD(u64, s6) \ - PROC_FIELD(u64, s7) - -struct Proc { -#define PROC_FIELD(type, name) type name; - PROC_FIELDS -#undef PROC_FIELD -}; - -u64 arch_proc_mb0_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->mb0a; -} - -u64 arch_proc_mb0_size(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->mb0s; -} - -u64 arch_proc_mb1_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->mb1a; -} - -u64 arch_proc_mb1_size(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->mb1s; -} - -u64 arch_proc_ip_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->ip; -} - -u64 arch_proc_sp_addr(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - return proc_get(core, pix)->sp; -} - -u64 arch_proc_slice(const Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - (void)core; - (void)pix; - - return 1; -} - -void _free_memory_block(Core *core, u64 addr, u64 size) { - assert(core); - assert(size); - - for (u64 i = 0; i < size; ++i) { - mvec_free(core, addr + i); - } -} - -void arch_on_proc_kill(Core *core) { - assert(core); - assert(core->pnum > 1); - - Proc *pfst = proc_fetch(core, core->pfst); - - _free_memory_block(core, pfst->mb0a, pfst->mb0s); - - if (pfst->mb1s) { - _free_memory_block(core, pfst->mb1a, pfst->mb1s); - } - - memcpy(pfst, &g_dead_proc, sizeof(Proc)); -} - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -void arch_anc_init(Core *core, u64 size) { - assert(core); - -#if ANC_HALF == 1 - u64 addr = U64_HALF; -#else - u64 addr = 0; -#endif - - for (int i = 0; i < ANC_CLONES; ++i) { - u64 addr_clone = addr + ((MVEC_SIZE / ANC_CLONES) * i); - - Proc *panc = proc_fetch(core, i); - - panc->mb0a = addr_clone; - panc->mb0s = size; - panc->ip = addr_clone; - panc->sp = addr_clone; - } -} -#endif - -u8 _get_inst(const Core *core, u64 addr) { - assert(core); - - return mvec_get_inst(core, addr) % INST_COUNT; -} - -void _increment_ip(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - - proc->ip++; - proc->sp = proc->ip; -} - -bool _is_between(u8 inst, u8 lo, u8 hi) { - assert(inst < INST_COUNT); - assert(lo < INST_COUNT); - assert(hi < INST_COUNT); - assert(lo < hi); - - return (inst >= lo) && (inst <= hi); -} - -bool _is_key(u8 inst) { - assert(inst < INST_COUNT); - - return _is_between(inst, keya, keyp); -} - -bool _is_lock(u8 inst) { - assert(inst < INST_COUNT); - - return _is_between(inst, loka, lokp); -} - -bool _is_rmod(u8 inst) { - assert(inst < INST_COUNT); - - return _is_between(inst, nop0, nop3); -} - -bool _key_lock_match(u8 key, u8 lock) { - assert(key < INST_COUNT); - assert(lock < INST_COUNT); - assert(_is_key(key)); - - return (key - keya) == (lock - loka); -} - -bool _seek(Core *core, u64 pix, bool fwrd) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u8 next = _get_inst(core, proc->ip + 1); - - if (!_is_key(next)) { - _increment_ip(core, pix); - return false; - } - - u8 spin = _get_inst(core, proc->sp); - - if (_key_lock_match(next, spin)) { - return true; - } - - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } - - return false; -} - -void _jump(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - -#ifndef NDEBUG - u8 next = _get_inst(core, proc->ip + 1); - u8 spin = _get_inst(core, proc->sp); - assert(_is_key(next)); - assert(_is_lock(spin)); - assert(_key_lock_match(next, spin)); -#endif - - proc->ip = proc->sp; -} - -void _get_reg_addr_list(Core *core, u64 pix, u64 **rlist, int rcount, bool offset) { - assert(core); - assert(proc_is_live(core, pix)); - - assert(rlist); - assert(rcount); - assert(rcount < 4); - - Proc *proc = proc_fetch(core, pix); - u64 madr = proc->ip + (offset ? 2 : 1); - - for (int i = 0; i < rcount; ++i) { - rlist[i] = &proc->r0x; - } - - for (int i = 0; i < rcount; ++i) { - u64 mnxt = madr + i; - u8 mins = _get_inst(core, mnxt); - - if (!_is_rmod(mins)) { - break; - } - - switch (mins) { - case nop0: - rlist[i] = &proc->r0x; - break; - case nop1: - rlist[i] = &proc->r1x; - break; - case nop2: - rlist[i] = &proc->r2x; - break; - case nop3: - rlist[i] = &proc->r3x; - break; - } - } -} - -void _addr(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *reg; - -#ifndef NDEBUG - u8 next = _get_inst(core, proc->ip + 1); - u8 spin = _get_inst(core, proc->sp); - assert(_is_key(next)); - assert(_is_lock(spin)); - assert(_key_lock_match(next, spin)); -#endif - - _get_reg_addr_list(core, pix, ®, 1, true); - *reg = proc->sp; - - _increment_ip(core, pix); -} - -void _ifnz(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - u64 jmod = _is_rmod(_get_inst(core, proc->ip + 1)) ? 1 : 0; - u64 rmod = *reg ? 1 : 2; - - proc->ip += jmod + rmod; - proc->sp = proc->ip; -} - -void _free_child_memory_of(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - - assert(proc->mb1s); - - _free_memory_block(core, proc->mb1a, proc->mb1s); - - proc->mb1a = 0; - proc->mb1s = 0; -} - -void _alloc(Core *core, u64 pix, bool fwrd) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - u64 bsize = *regs[0]; - - // do nothing if block-size is zero - if (!bsize) { - _increment_ip(core, pix); - return; - } - - // do nothing if sp is not adjacent to allocated mem. block - if (proc->mb1s) { - u64 exp_addr = proc->mb1a; - - if (fwrd) { - exp_addr += proc->mb1s; - } else { - exp_addr--; - } - - if (proc->sp != exp_addr) { - _increment_ip(core, pix); - return; - } - } - - // allocation was successful, store block address on register - if (proc->mb1s == bsize) { - _increment_ip(core, pix); - *regs[1] = proc->mb1a; - return; - } - - // sp collided with another allocated block, clear and try again - if (mvec_is_alloc(core, proc->sp)) { - if (proc->mb1s) { - _free_child_memory_of(core, pix); - } - - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } - - return; - } - - // otherwise enlarge block - mvec_alloc(core, proc->sp); - - // adjust child block address and size - if (!proc->mb1s || !fwrd) { - proc->mb1a = proc->sp; - } - - proc->mb1s++; - - // move sp to new location - if (fwrd) { - proc->sp++; - } else { - proc->sp--; - } -} - -void _bswap(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - u64 tmpa = proc->mb0a; - u64 tmps = proc->mb0s; - - proc->mb0a = proc->mb1a; - proc->mb0s = proc->mb1s; - proc->mb1a = tmpa; - proc->mb1s = tmps; - } - - _increment_ip(core, pix); -} - -void _bclear(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - _free_child_memory_of(core, pix); - } - - _increment_ip(core, pix); -} - -void _split(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - - if (proc->mb1s) { - Proc child = {0}; - - child.ip = proc->mb1a; - child.sp = proc->mb1a; - child.mb0a = proc->mb1a; - child.mb0s = proc->mb1s; - - proc->mb1a = 0; - proc->mb1s = 0; - - proc_new(core, &child); - } else { - assert(!proc->mb1a); - } - - _increment_ip(core, pix); -} - -void _3rop(Core *core, u64 pix, u8 inst) { - assert(core); - assert(proc_is_live(core, pix)); - - u64 *regs[3]; - - _get_reg_addr_list(core, pix, regs, 3, false); - - switch (inst) { - case addn: - *regs[0] = *regs[1] + *regs[2]; - break; - case subn: - *regs[0] = *regs[1] - *regs[2]; - break; - case muln: - *regs[0] = *regs[1] * *regs[2]; - break; - case divn: - // do nothing on div. by zero - if (*regs[2]) { - *regs[0] = *regs[1] / *regs[2]; - } - - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void _1rop(Core *core, u64 pix, u8 inst) { - assert(core); - assert(proc_is_live(core, pix)); - - u64 *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - switch (inst) { - case incn: - (*reg)++; - break; - case decn: - (*reg)--; - break; - case notn: - *reg = !(*reg); - break; - case shfl: - *reg <<= 1; - break; - case shfr: - *reg >>= 1; - break; - case zero: - *reg = 0; - break; - case unit: - *reg = 1; - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void _push(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - proc->s7 = proc->s6; - proc->s6 = proc->s5; - proc->s5 = proc->s4; - proc->s4 = proc->s3; - proc->s3 = proc->s2; - proc->s2 = proc->s1; - proc->s1 = proc->s0; - proc->s0 = *reg; - - _increment_ip(core, pix); -} - -void _pop(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *reg; - - _get_reg_addr_list(core, pix, ®, 1, false); - - *reg = proc->s0; - proc->s0 = proc->s1; - proc->s1 = proc->s2; - proc->s2 = proc->s3; - proc->s3 = proc->s4; - proc->s4 = proc->s5; - proc->s5 = proc->s6; - proc->s6 = proc->s7; - proc->s7 = 0; - - _increment_ip(core, pix); -} - -int _sp_dir(u64 src, u64 dst) { - if (src == dst) { - return 0; - } else if (src - dst <= dst - src) { - return -1; - } else { - return 1; - } -} - -void _load(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - int sp_dir = _sp_dir(proc->sp, *regs[0]); - - if (sp_dir == 1) { - proc->sp++; - } else if (sp_dir == -1) { - proc->sp--; - } else { - *regs[1] = mvec_get_inst(core, *regs[0]); - _increment_ip(core, pix); - } -} - -bool _is_writeable_by(const Core *core, u64 addr, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - return !mvec_is_alloc(core, addr) || mvec_is_proc_owner(core, addr, pix); -} - -void _write(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u64 *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - int sp_dir = _sp_dir(proc->sp, *regs[0]); - - if (sp_dir == 1) { - proc->sp++; - } else if (sp_dir == -1) { - proc->sp--; - } else { - if (_is_writeable_by(core, *regs[0], pix)) { - mvec_set_inst(core, *regs[0], *regs[1] % INST_CAPS); - } - - _increment_ip(core, pix); - } -} - -void _2rop(Core *core, u64 pix, u8 inst) { - assert(core); - assert(proc_is_live(core, pix)); - - u64 *regs[2]; - - _get_reg_addr_list(core, pix, regs, 2, false); - - switch (inst) { - case dupl: - *regs[1] = *regs[0]; - break; - case swap: - { - u64 tmp = *regs[0]; - *regs[0] = *regs[1]; - *regs[1] = tmp; - } - - break; - default: - assert(false); - } - - _increment_ip(core, pix); -} - -void arch_proc_step(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - Proc *proc = proc_fetch(core, pix); - u8 inst = _get_inst(core, proc->ip); - - switch (inst) { - case jmpb: - if (_seek(core, pix, false)) { - _jump(core, pix); - } - - break; - case jmpf: - if (_seek(core, pix, true)) { - _jump(core, pix); - } - - break; - case adrb: - if (_seek(core, pix, false)) { - _addr(core, pix); - } - - break; - case adrf: - if (_seek(core, pix, true)) { - _addr(core, pix); - } - - break; - case ifnz: - _ifnz(core, pix); - break; - case allb: - _alloc(core, pix, false); - break; - case allf: - _alloc(core, pix, true); - break; - case bswp: - _bswap(core, pix); - break; - case bclr: - _bclear(core, pix); - break; - case splt: - _split(core, pix); - break; - case addn: - case subn: - case muln: - case divn: - _3rop(core, pix, inst); - break; - case incn: - case decn: - case notn: - case shfl: - case shfr: - case zero: - case unit: - _1rop(core, pix, inst); - break; - case pshn: - _push(core, pix); - break; - case popn: - _pop(core, pix); - break; - case load: - _load(core, pix); - break; - case wrte: - _write(core, pix); - break; - case dupl: - case swap: - _2rop(core, pix, inst); - break; - default: - _increment_ip(core, pix); - break; - } - - return; -} - -#ifndef NDEBUG -void arch_validate_proc(const Core *core, u64 pix) { - assert(core); - - const Proc *proc = proc_get(core, pix); - - assert(proc->mb0s); - - if (proc->mb1a) { - assert(proc->mb1s); - } - - for (u64 i = 0; i < proc->mb0s; ++i) { - u64 addr = proc->mb0a + i; - assert(mvec_is_alloc(core, addr)); - assert(mvec_is_proc_owner(core, addr, pix)); - } - - for (u64 i = 0; i < proc->mb1s; ++i) { - u64 addr = proc->mb1a + i; - assert(mvec_is_alloc(core, addr)); - assert(mvec_is_proc_owner(core, addr, pix)); - } -} -#endif - -wchar_t arch_symbol(u8 inst) { - switch (inst % INST_COUNT) { -#define INST(name, symb) case name: return symb; - INST_LIST -#undef INST - } - - assert(false); - return L'\0'; -} - -void arch_mnemonic(u8 inst, char *buff) { - assert(buff); - - switch (inst % INST_COUNT) { -#define INST(name, symb) case name: snprintf(buff, MNEMONIC_BUFF_SIZE, #name); return; - INST_LIST -#undef INST - } - - assert(false); -} diff --git a/src/bench.c b/src/bench.c deleted file mode 100644 index eb7e0e5..0000000 --- a/src/bench.c +++ /dev/null @@ -1,49 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * Simple benchmark test helps measure simulation speed by stepping the - * simulator N times and printing results. - */ - -#if ACTION != ACT_BENCH -#error Using bench UI with unsupported action -#endif - -int main() { - printf("Salis Benchmark Test\n\n"); - - salis_init("", SEED); - salis_step(BENCH_STEPS); - - printf("seed => %#lx\n", SEED); - printf("g_steps => %#lx\n", g_steps); - printf("g_syncs => %#lx\n", g_syncs); - - for (int i = 0; i < CORE_COUNT; ++i) { - putchar('\n'); - printf("core %d mall => %#lx\n", i, g_cores[i].mall); - printf("core %d mut0 => %#lx\n", i, g_cores[i].muta[0]); - printf("core %d mut1 => %#lx\n", i, g_cores[i].muta[1]); - printf("core %d mut2 => %#lx\n", i, g_cores[i].muta[2]); - printf("core %d mut3 => %#lx\n", i, g_cores[i].muta[3]); - printf("core %d pnum => %#lx\n", i, g_cores[i].pnum); - printf("core %d pcap => %#lx\n", i, g_cores[i].pcap); - printf("core %d pfst => %#lx\n", i, g_cores[i].pfst); - printf("core %d plst => %#lx\n", i, g_cores[i].plst); - printf("core %d pcur => %#lx\n", i, g_cores[i].pcur); - printf("core %d psli => %#lx\n", i, g_cores[i].psli); - printf("core %d ncyc => %#lx\n", i, g_cores[i].ncyc); - printf("core %d ivpt => %#lx\n", i, g_cores[i].ivpt); - putchar('\n'); - - for (int j = 0; j < 32; ++j) { - printf("%02x ", g_cores[i].mvec[j]); - } - - putchar('\n'); - } - - salis_free(); -} diff --git a/src/graphics.c b/src/graphics.c deleted file mode 100644 index 780b879..0000000 --- a/src/graphics.c +++ /dev/null @@ -1,238 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * This module renders the contents of the VM memory buffer into a 7 channel - * image. It supports zooming in and out, condensing the state of several - * bytes of memory into single pixels, when zoomed out. When zoomed in, each - * pixel represents a single byte in memory. - */ - -u64 g_gfx_vsiz; // zoom level - -u64 *g_gfx_inst; // instruction channel -u64 *g_gfx_mall; // allocated state channel -u64 *g_gfx_mbst; // memory block start channel -u64 *g_gfx_mb0s; // selected organism's memory block #1 channel -u64 *g_gfx_mb1s; // selected organism's memory block #2 channel -u64 *g_gfx_ipas; // selected organism's IP channel -u64 *g_gfx_spas; // selected organism's SP channel - -void gfx_init(u64 vsiz) { - assert(vsiz); - - g_gfx_vsiz = vsiz; - - g_gfx_inst = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_mall = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_mbst = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_mb0s = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_mb1s = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_ipas = calloc(g_gfx_vsiz, sizeof(u64)); - g_gfx_spas = calloc(g_gfx_vsiz, sizeof(u64)); - - 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); -} - -void gfx_free() { - 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; -} - -void gfx_resize(u64 vsiz) { - assert(vsiz); - - gfx_free(); - gfx_init(vsiz); -} - -void gfx_render_inst(const Core *core, u64 pos, u64 zoom) { - assert(core); - - for (u64 i = 0; i < g_gfx_vsiz; ++i) { - g_gfx_inst[i] = 0; - g_gfx_mall[i] = 0; - - for (u64 j = 0; j < zoom; ++j) { - u64 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; - } - } -} - -void gfx_clear_array(u64 *arry) { - assert(arry); - memset(arry, 0, g_gfx_vsiz * sizeof(u64)); -} - -#ifdef MVEC_LOOP -void gfx_accumulate_pixel(u64 pos, u64 zoom, u64 pixa, u64 *arry) { - assert(arry); - - u64 beg_mod = pos % MVEC_SIZE; - u64 end_mod = beg_mod + (g_gfx_vsiz * zoom); - u64 pix_mod = pixa % MVEC_SIZE; - -#ifndef NDEBUG - u64 inc_cnt = 0; -#endif - - while (pix_mod < end_mod) { - if (pix_mod >= beg_mod && pix_mod < end_mod) { - u64 pixi = (pix_mod - beg_mod) / zoom; - assert(pixi < g_gfx_vsiz); - arry[pixi]++; - -#ifndef NDEBUG - inc_cnt++; -#endif - } - - pix_mod += MVEC_SIZE; - } - - -#ifndef NDEBUG - if (zoom != 1) { - assert(inc_cnt <= 2); - } -#endif -} -#else -void gfx_accumulate_pixel(u64 pos, u64 zoom, u64 pixa, u64 *arry) { - assert(arry); - - u64 end = pos + (g_gfx_vsiz * zoom); - - if (pixa < pos || pixa >= end) { - return; - } - - u64 pixi = (pixa - pos) / zoom; - assert(pixi < g_gfx_vsiz); - arry[pixi]++; -} -#endif - -void gfx_render_mbst(const Core *core, u64 pos, u64 zoom) { - assert(core); - - gfx_clear_array(g_gfx_mbst); - - for (u64 pix = core->pfst; pix <= core->plst; ++pix) { - u64 mb0a = arch_proc_mb0_addr(core, pix); - u64 mb1a = arch_proc_mb1_addr(core, pix); - - gfx_accumulate_pixel(pos, zoom, mb0a, g_gfx_mbst); - gfx_accumulate_pixel(pos, zoom, mb1a, g_gfx_mbst); - } -} - -void gfx_render_mb0s(const Core *core, u64 pos, u64 zoom, u64 psel) { - assert(core); - - gfx_clear_array(g_gfx_mb0s); - - if (psel < core->pfst || psel > core->plst) { - return; - } - - u64 mb0a = arch_proc_mb0_addr(core, psel); - u64 mb0s = arch_proc_mb0_size(core, psel); - - for (u64 i = 0; i < mb0s; ++i) { - gfx_accumulate_pixel(pos, zoom, mb0a + i, g_gfx_mb0s); - } -} - -void gfx_render_mb1s(const Core *core, u64 pos, u64 zoom, u64 psel) { - assert(core); - - gfx_clear_array(g_gfx_mb1s); - - if (psel < core->pfst || psel > core->plst) { - return; - } - - u64 mb1a = arch_proc_mb1_addr(core, psel); - u64 mb1s = arch_proc_mb1_size(core, psel); - - for (u64 i = 0; i < mb1s; ++i) { - gfx_accumulate_pixel(pos, zoom, mb1a + i, g_gfx_mb1s); - } -} - -void gfx_render_ipas(const Core *core, u64 pos, u64 zoom, u64 psel) { - assert(core); - - gfx_clear_array(g_gfx_ipas); - - if (psel < core->pfst || psel > core->plst) { - return; - } - - u64 ipa = arch_proc_ip_addr(core, psel); - - gfx_accumulate_pixel(pos, zoom, ipa, g_gfx_ipas); -} - -void gfx_render_spas(const Core *core, u64 pos, u64 zoom, u64 psel) { - assert(core); - - gfx_clear_array(g_gfx_spas); - - if (psel < core->pfst || psel > core->plst) { - return; - } - - u64 spa = arch_proc_sp_addr(core, psel); - - gfx_accumulate_pixel(pos, zoom, spa, g_gfx_spas); -} - -void gfx_render(const Core *core, u64 pos, u64 zoom, u64 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); -} diff --git a/src/salis.c b/src/salis.c deleted file mode 100644 index 348385f..0000000 --- a/src/salis.c +++ /dev/null @@ -1,811 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * Core of the Salis simulator. Can be built against different architectures - * and UI modules. - */ - -#include <assert.h> -#include <ctype.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <threads.h> - -#ifdef COMPRESS -#include <zlib.h> -#endif - -#define ACT_BENCH (1) -#define ACT_LOAD (2) -#define ACT_NEW (3) - -#define ASM_LINE_LEN (0x100) - -#define MALL_FLAG (0x80) -#define IPCM_FLAG (0x80) -#define INST_CAPS (0x80) -#define INST_MASK (0x7f) - -#define U64_HALF (0x8000000000000000) - -typedef struct Core Core; -typedef struct Ipcm Ipcm; -typedef struct Proc Proc; -typedef thrd_t Thread; -typedef uint64_t u64; -typedef uint8_t u8; - -struct Core { - u64 mall; - u64 muta[4]; - u64 pnum; - u64 pcap; - u64 pfst; - u64 plst; - u64 pcur; - u64 psli; - u64 ncyc; - - Thread thread; - u64 tix; - - u64 ivpt; - u8 *iviv; - u64 *ivav; - - Proc *pvec; - u8 mvec[MVEC_SIZE]; - u8 tgap[TGAP_SIZE]; -}; - -Core g_cores[CORE_COUNT]; -u64 g_steps; -u64 g_syncs; -#if ACTION == ACT_LOAD || ACTION == ACT_NEW -char g_asav_pbuf[AUTO_SAVE_NAME_LEN]; -#endif -const Proc g_dead_proc; - -#include ARCH_SOURCE - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -char g_mnemo_table[0x100][MNEMONIC_BUFF_SIZE]; -#endif - -#ifdef MVEC_LOOP -u64 mvec_loop(u64 addr) { - return addr % MVEC_SIZE; -} -#endif - -bool mvec_is_alloc(const Core *core, u64 addr) { - assert(core); -#ifdef MVEC_LOOP - return core->mvec[mvec_loop(addr)] & MALL_FLAG ? true : false; -#else - if (addr < MVEC_SIZE) { - return core->mvec[addr] & MALL_FLAG ? true : false; - } else { - return true; - } -#endif -} - -void mvec_alloc(Core *core, u64 addr) { - assert(core); - assert(!mvec_is_alloc(core, addr)); -#ifdef MVEC_LOOP - core->mvec[mvec_loop(addr)] |= MALL_FLAG; -#else - assert(addr < MVEC_SIZE); - core->mvec[addr] |= MALL_FLAG; -#endif - core->mall++; -} - -void mvec_free(Core *core, u64 addr) { - assert(core); - assert(mvec_is_alloc(core, addr)); -#ifdef MVEC_LOOP - core->mvec[mvec_loop(addr)] ^= MALL_FLAG; -#else - assert(addr < MVEC_SIZE); - core->mvec[addr] ^= MALL_FLAG; -#endif - core->mall--; -} - -u8 mvec_get_byte(const Core *core, u64 addr) { - assert(core); -#ifdef MVEC_LOOP - return core->mvec[mvec_loop(addr)]; -#else - if (addr < MVEC_SIZE) { - return core->mvec[addr]; - } else { - return 0; - } -#endif -} - -u8 mvec_get_inst(const Core *core, u64 addr) { - assert(core); -#ifdef MVEC_LOOP - return core->mvec[mvec_loop(addr)] & INST_MASK; -#else - if (addr < MVEC_SIZE) { - return core->mvec[addr] & INST_MASK; - } else { - return 0; - } -#endif -} - -void mvec_set_inst(Core *core, u64 addr, u8 inst) { - assert(core); - assert(inst < INST_CAPS); -#ifdef MVEC_LOOP - core->mvec[mvec_loop(addr)] &= MALL_FLAG; - core->mvec[mvec_loop(addr)] |= inst; -#else - assert(addr < MVEC_SIZE); - core->mvec[addr] &= MALL_FLAG; - core->mvec[addr] |= inst; -#endif -} - -#if MUTA_FLIP_BIT == 1 -void mvec_flip_bit(Core *core, u64 addr, int bit) { - assert(core); - assert(bit < 8); - core->mvec[addr] ^= (1 << bit) & INST_MASK; -} -#endif - -bool mvec_is_proc_owner(const Core *core, u64 addr, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - u64 mb0a = arch_proc_mb0_addr(core, pix); - u64 mb0s = arch_proc_mb0_size(core, pix); - - if (((addr - mb0a) % MVEC_SIZE) < mb0s) { - return true; - } - - u64 mb1a = arch_proc_mb1_addr(core, pix); - u64 mb1s = arch_proc_mb1_size(core, pix); - - if (((addr - mb1a) % MVEC_SIZE) < mb1s) { - return true; - } - - return false; -} - -u64 mvec_get_owner(const Core *core, u64 addr) { - assert(core); - assert(mvec_is_alloc(core, addr)); - - for (u64 pix = core->pfst; pix <= core->plst; ++pix) { - if (mvec_is_proc_owner(core, addr, pix)) { - return pix; - } - } - - assert(false); - return -1; -} - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -u64 muta_smix(u64 *seed) { - assert(seed); - - u64 next = (*seed += 0x9e3779b97f4a7c15); - next = (next ^ (next >> 30)) * 0xbf58476d1ce4e5b9; - next = (next ^ (next >> 27)) * 0x94d049bb133111eb; - - return next ^ (next >> 31); -} -#endif - -u64 muta_ro64(u64 x, int k) { - return (x << k) | (x >> (64 - k)); -} - -u64 muta_next(Core *core) { - assert(core); - - u64 r = muta_ro64(core->muta[1] * 5, 7) * 9; - u64 t = core->muta[1] << 17; - - core->muta[2] ^= core->muta[0]; - core->muta[3] ^= core->muta[1]; - core->muta[1] ^= core->muta[2]; - core->muta[0] ^= core->muta[3]; - - core->muta[2] ^= t; - core->muta[3] = muta_ro64(core->muta[3], 45); - - return r; -} - -void muta_cosmic_ray(Core *core) { - assert(core); - - u64 a = muta_next(core) % MUTA_RANGE; - u64 b = muta_next(core); - - if (a < MVEC_SIZE) { -#if MUTA_FLIP_BIT == 1 - mvec_flip_bit(core, a, (int)(b % 8)); -#else - mvec_set_inst(core, a, b & INST_MASK); -#endif - } -} - -void proc_new(Core *core, const Proc *proc) { - assert(core); - assert(proc); - - if (core->pnum == core->pcap) { - u64 new_pcap = core->pcap * 2; - Proc *new_pvec = calloc(new_pcap, sizeof(Proc)); - - for (u64 pix = core->pfst; pix <= core->plst; ++pix) { - u64 iold = pix % core->pcap; - u64 inew = pix % new_pcap; - memcpy(&new_pvec[inew], &core->pvec[iold], sizeof(Proc)); - } - - free(core->pvec); - core->pcap = new_pcap; - core->pvec = new_pvec; - } - - core->pnum++; - core->plst++; - memcpy(&core->pvec[core->plst % core->pcap], proc, sizeof(Proc)); -} - -void proc_kill(Core *core) { - assert(core); - assert(core->pnum > 1); - - arch_on_proc_kill(core); - - core->pcur++; - core->pfst++; - core->pnum--; -} - -bool proc_is_live(const Core *core, u64 pix) { - assert(core); - - return pix >= core->pfst && pix <= core->plst; -} - -const Proc *proc_get(const Core *core, u64 pix) { - assert(core); - - if (proc_is_live(core, pix)) { - return &core->pvec[pix % core->pcap]; - } else { - return &g_dead_proc; - } -} - -Proc *proc_fetch(Core *core, u64 pix) { - assert(core); - assert(proc_is_live(core, pix)); - - return &core->pvec[pix % core->pcap]; -} - -#if ACTION == ACT_LOAD || ACTION == ACT_NEW -void core_save(FILE *f, const Core *core) { - assert(f); - assert(core); - - fwrite(&core->mall, sizeof(u64), 1, f); - fwrite( core->muta, sizeof(u64), 4, f); - fwrite(&core->pnum, sizeof(u64), 1, f); - fwrite(&core->pcap, sizeof(u64), 1, f); - fwrite(&core->pfst, sizeof(u64), 1, f); - fwrite(&core->plst, sizeof(u64), 1, f); - fwrite(&core->pcur, sizeof(u64), 1, f); - fwrite(&core->psli, sizeof(u64), 1, f); - fwrite(&core->ncyc, sizeof(u64), 1, f); - fwrite(&core->ivpt, sizeof(u64), 1, f); - - fwrite(core->iviv, sizeof(u8), SYNC_INTERVAL, f); - fwrite(core->ivav, sizeof(u64), SYNC_INTERVAL, f); - fwrite(core->pvec, sizeof(Proc), core->pcap, f); - fwrite(core->mvec, sizeof(u8), MVEC_SIZE, f); -} -#endif - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -u64 core_assemble_ancestor(int cix, const char *anc) { - assert(cix >= 0 && cix < CORE_COUNT); - assert(anc); - - if (anc[0] == '_') { - return 0; - } - - FILE *f = fopen(anc, "r"); - - assert(f); - -#if ANC_HALF == 1 - u64 addr = U64_HALF; -#else - u64 addr = 0; -#endif - - char line[ASM_LINE_LEN] = {0}; - Core *core = &g_cores[cix]; - - for (; fgets(line, ASM_LINE_LEN, f); ++addr) { -#ifndef NDEBUG - bool line_ok = false; -#endif - - line[strcspn(line, "\r\n")] = '\0'; - - for (int i = 0; i < 0x100; ++i) { - if (strcmp(line, g_mnemo_table[i]) == 0) { - for (u64 j = 0; j < ANC_CLONES; ++j) { - u64 addr_clone = addr + ((MVEC_SIZE / ANC_CLONES) * j); - - mvec_alloc(core, addr_clone); - mvec_set_inst(core, addr_clone, i); - } - -#ifndef NDEBUG - line_ok = true; -#endif - break; - } - } - - assert(line_ok); - } - - fclose(f); - - return addr; -} - -void core_init(int cix, u64 *seed, const char *anc) { - assert(cix >= 0 && cix < CORE_COUNT); - assert(seed); - assert(anc); - - Core *core = &g_cores[cix]; - - if (*seed) { - core->muta[0] = muta_smix(seed); - core->muta[1] = muta_smix(seed); - core->muta[2] = muta_smix(seed); - core->muta[3] = muta_smix(seed); - } - - core->pnum = ANC_CLONES; - core->pcap = ANC_CLONES; - core->plst = ANC_CLONES - 1; - core->iviv = calloc(SYNC_INTERVAL, sizeof(u8)); - core->ivav = calloc(SYNC_INTERVAL, sizeof(u64)); - core->pvec = calloc(core->pcap, sizeof(Proc)); - - assert(core->iviv); - assert(core->ivav); - assert(core->pvec); - - u64 anc_size = core_assemble_ancestor(cix, anc); - -#if ANC_HALF == 1 - anc_size -= U64_HALF; -#endif - - arch_anc_init(core, anc_size); -} -#endif - -#if ACTION == ACT_LOAD -void core_load(FILE *f, Core *core) { - assert(f); - assert(core); - - fread(&core->mall, sizeof(u64), 1, f); - fread( core->muta, sizeof(u64), 4, f); - fread(&core->pnum, sizeof(u64), 1, f); - fread(&core->pcap, sizeof(u64), 1, f); - fread(&core->pfst, sizeof(u64), 1, f); - fread(&core->plst, sizeof(u64), 1, f); - fread(&core->pcur, sizeof(u64), 1, f); - fread(&core->psli, sizeof(u64), 1, f); - fread(&core->ncyc, sizeof(u64), 1, f); - fread(&core->ivpt, sizeof(u64), 1, f); - - core->iviv = calloc(SYNC_INTERVAL, sizeof(u8)); - core->ivav = calloc(SYNC_INTERVAL, sizeof(u64)); - core->pvec = calloc(core->pcap, sizeof(Proc)); - - assert(core->iviv); - assert(core->ivav); - assert(core->pvec); - - fread(core->iviv, sizeof(u8), SYNC_INTERVAL, f); - fread(core->ivav, sizeof(u64), SYNC_INTERVAL, f); - fread(core->pvec, sizeof(Proc), core->pcap, f); - fread(core->mvec, sizeof(u8), MVEC_SIZE, f); -} -#endif - -void core_pull_ipcm(Core *core) { - assert(core); - assert(core->ivpt < SYNC_INTERVAL); - - u8 *iinst = &core->iviv[core->ivpt]; - u64 *iaddr = &core->ivav[core->ivpt]; - - if ((*iinst & IPCM_FLAG) != 0) { - mvec_set_inst(core, *iaddr, *iinst & INST_MASK); - - *iinst = 0; - *iaddr = 0; - } - - assert(*iinst == 0); - assert(*iaddr == 0); -} - -void core_push_ipcm(Core *core, u8 inst, u64 addr) { - assert(core); - assert(core->ivpt < SYNC_INTERVAL); - assert((inst & IPCM_FLAG) == 0); - - u8 *iinst = &core->iviv[core->ivpt]; - u64 *iaddr = &core->ivav[core->ivpt]; - - assert(*iinst == 0); - assert(*iaddr == 0); - - *iinst = inst | IPCM_FLAG; - *iaddr = addr; -} - -void core_step(Core *core) { - assert(core); - - if (core->psli != 0) { - core_pull_ipcm(core); - arch_proc_step(core, core->pcur); - - core->psli--; - core->ivpt++; - - return; - } - - if (core->pcur != core->plst) { - core->psli = arch_proc_slice(core, ++core->pcur); - core_step(core); - return; - } - - core->pcur = core->pfst; - core->psli = arch_proc_slice(core, core->pcur); - core->ncyc++; - - while (core->mall > MVEC_SIZE / 2 && core->pnum > 1) { - proc_kill(core); - } - - muta_cosmic_ray(core); - core_step(core); -} - -#if ACTION == ACT_LOAD || ACTION == ACT_NEW -void salis_save(const char *path) { -#ifdef COMPRESS - size_t size = 0; - char *in = NULL; - FILE *f = open_memstream(&in, &size); -#else - FILE *f = fopen(path, "wb"); -#endif - - assert(f); - - for (int i = 0; i < CORE_COUNT; ++i) { - core_save(f, &g_cores[i]); - } - - fwrite(&g_steps, sizeof(u64), 1, f); - fwrite(&g_syncs, sizeof(u64), 1, f); - fclose(f); - -#ifdef COMPRESS - assert(size); - - char *out = malloc(size); - assert(out); - - z_stream strm = { 0 }; - strm.zalloc = NULL, - strm.zfree = NULL, - strm.opaque = NULL, - - deflateInit(&strm, Z_DEFAULT_COMPRESSION); - - strm.avail_in = size; - strm.avail_out = size; - strm.next_in = (Bytef *)in; - strm.next_out = (Bytef *)out; - - deflate(&strm, Z_FINISH); - - FILE *fx = fopen(path, "wb"); - assert(fx); - - fwrite(&size, sizeof(size_t), 1, fx); - fwrite(out, sizeof(char), strm.total_out, fx); - fclose(fx); - - deflateEnd(&strm); - - free(in); - free(out); -#endif -} - -void salis_auto_save() { - if (g_steps % AUTO_SAVE_INTERVAL != 0) { - return; - } - -#ifndef NDEBUG - int rem = snprintf( -#else - snprintf( -#endif - g_asav_pbuf, - AUTO_SAVE_NAME_LEN, - "%s-%#018lx", - SIM_PATH, - g_steps - ); - - assert(rem >= 0); - assert(rem < AUTO_SAVE_NAME_LEN); - - salis_save(g_asav_pbuf); -} -#endif - -#if ACTION == ACT_BENCH || ACTION == ACT_NEW -void salis_init() { - for (int i = 0; i < 0x100; ++i) { - arch_mnemonic(i, g_mnemo_table[i]); - } - - u64 seed = SEED; - char anc_list[] = ANC_LIST; - - assert(anc_list); - - for (int i = 0; i < CORE_COUNT; ++i) { - core_init(i, &seed, strtok(i ? NULL : anc_list, ",")); - } - -#if ACTION == ACT_NEW - salis_auto_save(); -#endif -} -#endif - -#if ACTION == ACT_LOAD -void salis_load() { -#ifdef COMPRESS - FILE *fx = fopen(SIM_PATH, "rb"); - assert(fx); - - fseek(fx, 0, SEEK_END); - size_t x_size = ftell(fx) - sizeof(size_t); - char *in = malloc(x_size); - rewind(fx); - assert(x_size); - assert(in); - - size_t size = 0; - fread(&size, sizeof(size_t), 1, fx); - fread(in, 1, x_size, fx); - fclose(fx); - assert(size); - - char *out = malloc(size); - assert(out); - - z_stream strm = { 0 }; - strm.next_in = (Bytef *)in; - strm.avail_in = x_size; - strm.zalloc = NULL; - strm.zfree = NULL; - strm.opaque = NULL; - - inflateInit(&strm); - - strm.avail_out = size; - strm.next_out = (Bytef *)out; - -#ifdef NDEBUG - inflate(&strm, Z_FINISH); -#else - assert(inflate(&strm, Z_FINISH)); -#endif - - inflateEnd(&strm); - - FILE *f = fmemopen(out, size, "rb"); -#else - FILE *f = fopen(SIM_PATH, "rb"); -#endif - - assert(f); - - for (int i = 0; i < CORE_COUNT; ++i) { - core_load(f, &g_cores[i]); - } - - fread(&g_steps, sizeof(u64), 1, f); - fread(&g_syncs, sizeof(u64), 1, f); - fclose(f); - -#ifdef COMPRESS - free(in); - free(out); -#endif -} -#endif - -int salis_thread(Core *core) { - assert(core); - - for (u64 i = 0; i < core->tix; ++i) { - core_step(core); - } - - return 0; -} - -void salis_run_thread(u64 ns) { - for (int i = 0; i < CORE_COUNT; ++i) { - g_cores[i].tix = ns; - - thrd_create( - &g_cores[i].thread, - (thrd_start_t)salis_thread, - &g_cores[i] - ); - } - - for (int i = 0; i < CORE_COUNT; ++i) { - thrd_join(g_cores[i].thread, NULL); - } - - g_steps += ns; -} - -void salis_sync() { - u8 *iviv0 = g_cores[0].iviv; - u64 *ivav0 = g_cores[0].ivav; - - for (int i = 1; i < CORE_COUNT; ++i) { - g_cores[i - 1].iviv = g_cores[i].iviv; - g_cores[i - 1].ivav = g_cores[i].ivav; - } - - g_cores[CORE_COUNT - 1].iviv = iviv0; - g_cores[CORE_COUNT - 1].ivav = ivav0; - - for (int i = 0; i < CORE_COUNT; ++i) { - g_cores[i].ivpt = 0; - } - - g_syncs++; -} - -void salis_loop(u64 ns, u64 dt) { - assert(dt); - - if (ns < dt) { - salis_run_thread(ns); - return; - } - - salis_run_thread(dt); - salis_sync(); -#if ACTION == ACT_LOAD || ACTION == ACT_NEW - salis_auto_save(); -#endif - salis_loop(ns - dt, SYNC_INTERVAL); -} - -#ifndef NDEBUG -void salis_validate_core(const Core *core) { - assert(core->plst >= core->pfst); - assert(core->pnum == core->plst + 1 - core->pfst); - assert(core->pnum <= core->pcap); - assert(core->pcur >= core->pfst && core->pcur <= core->plst); - assert(core->ncyc <= g_steps); - - u64 mall = 0; - - for (u64 i = 0; i < MVEC_SIZE; ++i) { - mall += mvec_is_alloc(core, i) ? 1 : 0; - } - - assert(core->mall == mall); - - for (u64 i = core->pfst; i <= core->plst; ++i) { - arch_validate_proc(core, i); - } - - for (u64 i = 0; i < SYNC_INTERVAL; ++i) { - u8 iinst = core->iviv[i]; - - if ((iinst & IPCM_FLAG) == 0) { - u64 iaddr = core->ivav[i]; - - assert(iinst == 0); - assert(iaddr == 0); - } - } - - assert(core->ivpt == g_steps % SYNC_INTERVAL); -} - -void salis_validate() { - assert(g_steps / SYNC_INTERVAL == g_syncs); - - for (int i = 0; i < CORE_COUNT; ++i) { - salis_validate_core(&g_cores[i]); - } -} -#endif - -void salis_step(u64 ns) { - assert(ns); - salis_loop(ns, SYNC_INTERVAL - (g_steps % SYNC_INTERVAL)); - -#ifndef NDEBUG - salis_validate(); -#endif -} - -void salis_free() { - for (int i = 0; i < CORE_COUNT; ++i) { - assert(g_cores[i].pvec); - assert(g_cores[i].iviv); - assert(g_cores[i].ivav); - - free(g_cores[i].pvec); - free(g_cores[i].iviv); - free(g_cores[i].ivav); - - g_cores[i].pvec = NULL; - g_cores[i].iviv = NULL; - g_cores[i].ivav = NULL; - } -} - -#include UI diff --git a/src/ui/curses.c b/src/ui/curses.c deleted file mode 100644 index d1f821d..0000000 --- a/src/ui/curses.c +++ /dev/null @@ -1,965 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * Implements a TUI for the Salis simulator using the ncurses library. - */ - -// GCC_EXTRA_FLAGS -lncursesw - -#include <curses.h> -#include <locale.h> -#include <time.h> - -#define CTRL(x) ((x) & 0x1f) -#define PANE_WIDTH (27) -#define PROC_FIELD_WIDTH (21) -#define PROC_PAGE_LINES (12) - -enum { - PAGE_CORE, - PAGE_PROCESS, - PAGE_WORLD, - PAGE_IPC, - PAGE_COUNT -}; - -enum { - PAIR_NOUSE, - 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, -}; - -bool g_exit; -bool g_running; -unsigned g_core; -unsigned g_page; -bool g_proc_genes; -u64 g_proc_scroll; -u64 g_proc_field_scroll; -u64 g_proc_gene_scroll; -u64 g_proc_selected; -u64 g_wrld_pos; -u64 g_wrld_zoom; -bool g_wcursor_mode; -int g_wcursor_x; -int g_wcursor_y; -u64 g_wcursor_pointed; -u64 g_vlin; -u64 g_vsiz; -u64 g_vlin_rng; -u64 g_vsiz_rng; -u64 g_ivpt_scroll; -char *g_line_buff; -u64 g_step_block; - -const wchar_t *g_zoomed_symbols = ( - L"⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟" - L"⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿" - L"⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟" - L"⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿" -); - -#include "graphics.c" - -void ui_line_buff_free() { - if (g_line_buff) { - free(g_line_buff); - } - - g_line_buff = NULL; -} - -void ui_line_buff_resize() { - ui_line_buff_free(); - - g_line_buff = calloc(COLS + 1, sizeof(char)); -} - -void ui_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; - - attron(COLOR_PAIR(color) | attr); - va_start(args, format); - - vsnprintf(g_line_buff, COLS, format, args); - mvprintw(line, 1, g_line_buff); - - va_end(args); - attroff(COLOR_PAIR(color) | attr); -} - -void ui_clear_line(int l) { - ui_line(true, l, PAIR_NORMAL, A_NORMAL, ""); -} - -void ui_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; - - attron(COLOR_PAIR(color) | attr); - va_start(args, format); - - vsnprintf(g_line_buff, COLS - col, format, args); - mvprintw(line, col, g_line_buff); - - va_end(args); - attroff(COLOR_PAIR(color) | attr); -} - -void ui_str_field(int l, const char *label, const char *value) { - assert(label); - assert(value); - ui_line(false, l, PAIR_NORMAL, A_NORMAL, "%s : %18s", label, value); -} - -void ui_ulx_field(int l, const char *label, u64 value) { - assert(label); - ui_line(false, l, PAIR_NORMAL, A_NORMAL, "%-4s : %#18lx", label, value); -} - -void ui_print_core(int l) { - ui_line(false, ++l, PAIR_HEADER, A_BOLD, "CORE [%d]", g_core); - ui_ulx_field(++l, "mall", g_cores[g_core].mall); - ui_ulx_field(++l, "mut0", g_cores[g_core].muta[0]); - ui_ulx_field(++l, "mut1", g_cores[g_core].muta[1]); - ui_ulx_field(++l, "mut2", g_cores[g_core].muta[2]); - ui_ulx_field(++l, "mut3", g_cores[g_core].muta[3]); - ui_ulx_field(++l, "pnum", g_cores[g_core].pnum); - ui_ulx_field(++l, "pcap", g_cores[g_core].pcap); - ui_ulx_field(++l, "pfst", g_cores[g_core].pfst); - ui_ulx_field(++l, "plst", g_cores[g_core].plst); - ui_ulx_field(++l, "pcur", g_cores[g_core].pcur); - ui_ulx_field(++l, "psli", g_cores[g_core].psli); - ui_ulx_field(++l, "ncyc", g_cores[g_core].ncyc); - ui_ulx_field(++l, "ivpt", g_cores[g_core].ivpt); -} - -int ui_proc_pair(u64 pix) { - if (pix == g_proc_selected) { - return PAIR_SELECTED_PROC; - } else if (proc_is_live(&g_cores[g_core], pix)) { - return PAIR_LIVE_PROC; - } else { - return PAIR_NORMAL; - } -} - -const char *ui_proc_state(u64 pix) { - return proc_is_live(&g_cores[g_core], pix) ? "live" : "dead"; -} - -void ui_print_process_genome_header(int l) { - ui_line(false, l++, PAIR_NORMAL, A_NORMAL, "%s : %18s : %s", "stat", "pix", "genome"); -} - -void ui_print_process_gene(int l, int gcol, u64 gidx, u64 mba, u64 pix, int pair) { - assert(gcol >= PANE_WIDTH + 2); - assert(gcol < COLS); - assert(proc_is_live(&g_cores[g_core], pix)); - assert(pair == PAIR_SELECTED_MB1 || pair == PAIR_SELECTED_MB2); - - const Core *core = &g_cores[g_core]; - - u64 addr = mba + gidx; - u8 byte = mvec_get_byte(core, addr); - - wchar_t gsym[2] = { arch_symbol(byte), L'\0' }; - cchar_t cchar = { 0 }; - - int pair_cell; - - if (arch_proc_ip_addr(core, pix) == addr) { - pair_cell = PAIR_SELECTED_IP; - } else if (arch_proc_sp_addr(core, pix) == addr) { - pair_cell = PAIR_SELECTED_SP; - } else { - pair_cell = pair; - } - - setcchar(&cchar, gsym, 0, pair_cell, NULL); - mvadd_wch(l, gcol, &cchar); -} - -void ui_print_process_genes(int l, u64 pix) { - ui_line(true, l, ui_proc_pair(pix), A_NORMAL, "%s : %#18lx :", ui_proc_state(pix), pix); - - if (!proc_is_live(&g_cores[g_core], pix)) { - return; - } - - const Core *core = &g_cores[g_core]; - - int scol = PANE_WIDTH + 2; - int gcol = scol - g_proc_gene_scroll; - u64 mb0a = arch_proc_mb0_addr(core, pix); - u64 mb0s = arch_proc_mb0_size(core, pix); - u64 mb1a = arch_proc_mb1_addr(core, pix); - u64 mb1s = arch_proc_mb1_size(core, pix); - - for (u64 gidx = 0; gidx < mb0s && gcol < COLS; ++gidx, ++gcol) { - if (gcol >= scol) { - ui_print_process_gene(l, gcol, gidx, mb0a, pix, PAIR_SELECTED_MB1); - } - } - - for (u64 gidx = 0; gidx < mb1s && gcol < COLS; ++gidx, ++gcol) { - if (gcol >= scol) { - ui_print_process_gene(l, gcol, gidx, mb1a, pix, PAIR_SELECTED_MB2); - } - } - - clrtoeol(); -} - -void ui_print_process_field_header_element(int l, int fidx, const char *name) { - assert(fidx >= 0); - assert(name); - - if (fidx < (int)g_proc_field_scroll) { - return; - } - - int foff = fidx - g_proc_field_scroll; - int fcol = foff * PROC_FIELD_WIDTH + PANE_WIDTH - 1; - - ui_field(l, fcol, PAIR_NORMAL, A_NORMAL, " : %18s", name); -} - -void ui_print_process_field_header(int l) { - ui_line(true, l, PAIR_NORMAL, A_NORMAL, "%s : %18s", "stat", "pix"); - - int fidx = 0; - -#define PROC_FIELD(type, name) ui_print_process_field_header_element(l, fidx++, #name); - PROC_FIELDS -#undef PROC_FIELD -} - -void ui_print_process_field_element(int l, int fidx, int fclr, u64 field) { - assert(fidx >= 0); - - if (fidx < (int)g_proc_field_scroll) { - return; - } - - int foff = fidx - g_proc_field_scroll; - int fcol = foff * PROC_FIELD_WIDTH + PANE_WIDTH - 1; - - ui_field(l, fcol, fclr, A_NORMAL, " : %#18lx", field); -} - - -void ui_print_process_fields(int l, u64 pix) { - ui_line(true, l, ui_proc_pair(pix), A_NORMAL, "%s : %#18lx", ui_proc_state(pix), pix); - - const Proc *proc = proc_get(&g_cores[g_core], pix); - int fidx = 0; - int fclr = ui_proc_pair(pix); - -#define PROC_FIELD(type, name) ui_print_process_field_element(l, fidx++, fclr, proc->name); - PROC_FIELDS -#undef PROC_FIELD -} - -void ui_print_process(int l) { - l++; - - ui_line(true, l++, PAIR_HEADER, A_BOLD, - "PROCESS [vs:%#lx | ps:%#lx | pf:%#lx | pl:%#lx | fs:%#lx | gs:%#lx]", - g_proc_scroll, - g_proc_selected, - g_cores[g_core].pfst, - g_cores[g_core].plst, - g_proc_field_scroll, - g_proc_gene_scroll - ); - - u64 pix = g_proc_scroll; - - if (g_proc_genes) { - ui_print_process_genome_header(l++); - - while (l < LINES) { - ui_print_process_genes(l++, pix++); - } - } else { - ui_print_process_field_header(l++); - - while (l < LINES) { - ui_print_process_fields(l++, pix++); - } - } -} - -void ui_world_resize() { - assert(g_wrld_zoom); - - g_vlin = 0; - g_vsiz = 0; - g_vlin_rng = 0; - g_vsiz_rng = 0; - - if (COLS > PANE_WIDTH) { - g_vlin = COLS - PANE_WIDTH; - g_vsiz = LINES * g_vlin; - g_vlin_rng = g_vlin * g_wrld_zoom; - g_vsiz_rng = g_vsiz * g_wrld_zoom; - - gfx_resize(g_vsiz); - } -} - -void ui_print_cell(u64 i, u64 r, u64 x, u64 y, u64 a) { - wchar_t inst_nstr[2] = { L'\0', L'\0' }; - cchar_t cchar = { 0 }; - u64 inst_avrg = g_gfx_inst[i] / g_wrld_zoom; - - if (g_wrld_zoom == 1) { - inst_nstr[0] = arch_symbol((u8)inst_avrg); - } else { - inst_nstr[0] = g_zoomed_symbols[(u8)inst_avrg]; - } - - int pair_cell; - - if (a >= MVEC_SIZE) { - pair_cell = PAIR_NORMAL; - } else if (g_wcursor_mode && r == (u64)g_wcursor_x && y == (u64)g_wcursor_y) { - pair_cell = PAIR_NORMAL; - } else if (g_gfx_ipas[i] != 0) { - pair_cell = PAIR_SELECTED_IP; - } else if (g_gfx_spas[i] != 0) { - pair_cell = PAIR_SELECTED_SP; - } else if (g_gfx_mb0s[i] != 0) { - pair_cell = PAIR_SELECTED_MB1; - } else if (g_gfx_mb1s[i] != 0) { - pair_cell = PAIR_SELECTED_MB2; - } else if (g_gfx_mbst[i] != 0) { - pair_cell = PAIR_MEM_BLOCK_START; - } else if (g_gfx_mall[i] != 0) { - pair_cell = PAIR_ALLOC_CELL; - } else { - pair_cell = PAIR_FREE_CELL; - } - - setcchar(&cchar, inst_nstr, 0, pair_cell, NULL); - mvadd_wch(y, x, &cchar); -} - -void ui_print_wcursor_bar() { - ui_clear_line(LINES - 1); - - const Core *core = &g_cores[g_core]; - - char cmnem[MNEMONIC_BUFF_SIZE]; - char cownr[PROC_FIELD_WIDTH]; - - u64 cpos = g_vlin * g_wcursor_y + g_wcursor_x; - u64 caddr = cpos * g_wrld_zoom + g_wrld_pos; - u8 cbyte = mvec_get_byte(core, caddr); - - if (mvec_is_alloc(core, caddr)) { - g_wcursor_pointed = mvec_get_owner(core, caddr); - snprintf(cownr, PROC_FIELD_WIDTH, "%#lx", g_wcursor_pointed); - } else { - g_wcursor_pointed = (u64)(-1); - snprintf(cownr, PROC_FIELD_WIDTH, "-"); - } - - arch_mnemonic(cbyte, cmnem); - - mvprintw( - LINES - 1, - 1, - ( - "cursor" - " | x:%#x" - " | y:%#x" - " | addr:%#lx" - " | isum:%#lx" - " | iavr:%#lx" - " | mall:%#lx" - " | mbst:%#lx" - " | mnem:<%s>" - " | ownr:%s" - ), - g_wcursor_x, - g_wcursor_y, - caddr, - g_gfx_inst[cpos], - g_gfx_inst[cpos] / g_wrld_zoom, - g_gfx_mall[cpos], - g_gfx_mbst[cpos], - cmnem, - cownr - ); -} - -void ui_print_world(int l) { - l++; - - ui_line(false, l++, PAIR_HEADER, A_BOLD, "WORLD"); - ui_ulx_field(l++, "wrlp", g_wrld_pos); - ui_ulx_field(l++, "wrlz", g_wrld_zoom); - ui_ulx_field(l++, "psel", g_proc_selected); - ui_ulx_field(l++, "pabs", g_proc_selected % g_cores[g_core].pcap); - ui_ulx_field(l++, "vrng", g_vsiz_rng); - ui_str_field(l++, "curs", g_wcursor_mode ? "on" : "off"); - - l++; - - ui_line(false, l++, PAIR_HEADER, A_BOLD, "SELECTED"); - - const Proc *psel = proc_get(&g_cores[g_core], g_proc_selected); - -#define PROC_FIELD(type, name) ui_ulx_field(l++, #name, psel->name); - PROC_FIELDS -#undef PROC_FIELD - - if (!g_vlin) { - return; - } - - gfx_render(&g_cores[g_core], g_wrld_pos, g_wrld_zoom, g_proc_selected); - - if (g_wcursor_mode) { - int xmax = g_vlin - 1; - int ymax = LINES - 2; - - g_wcursor_x = (g_wcursor_x < xmax) ? g_wcursor_x : xmax; - g_wcursor_y = (g_wcursor_y < ymax) ? g_wcursor_y : ymax; - } - - for (u64 i = 0; i < g_vsiz; ++i) { - u64 r = i % g_vlin; - u64 x = r + PANE_WIDTH; - u64 y = i / g_vlin; - u64 a = g_wrld_pos + (i * g_wrld_zoom); - - ui_print_cell(i, r, x, y, a); - } - - if (g_wcursor_mode) { - ui_print_wcursor_bar(); - } -} - -void ui_print_ipc_field(int l, u64 i, int color) { - u8 iinst = g_cores[g_core].iviv[i]; - u64 iaddr = g_cores[g_core].ivav[i]; - - ui_field(l, PANE_WIDTH, color, A_NORMAL, "%#18x : %#18x : %#18x", i, iinst, iaddr); -} - -void ui_print_ipc_data() { - ui_field(0, PANE_WIDTH, PAIR_NORMAL, A_NORMAL, "%18s : %18s : %18s", "ipci", "inst", "addr"); - - int l = 1 - g_ivpt_scroll; - - for (u64 i = 0; i < SYNC_INTERVAL; ++i) { - if (i == g_cores[g_core].ivpt) { - if (l >= 1) { - ui_print_ipc_field(l++, i, PAIR_SELECTED_PROC); - } - - continue; - } - - u8 iinst = g_cores[g_core].iviv[i]; - - if ((iinst & IPCM_FLAG) != 0) { - if (l >= 1) { - ui_print_ipc_field(l++, i, PAIR_LIVE_PROC); - } - - continue; - } - } - - for (; l < LINES; ++l) { - if (l >= 1) { - move(l, PANE_WIDTH); - clrtoeol(); - } - } -} - -void ui_print_ipc(int l) { - l++; - - const Core *core = &g_cores[g_core]; - - ui_line(true, l++, PAIR_HEADER, A_BOLD, "IPC [%#lx]", g_ivpt_scroll); - ui_ulx_field(l++, "ivpt", core->ivpt); - ui_ulx_field(l++, "ivpi", core->iviv[core->ivpt]); - ui_ulx_field(l++, "ivpa", core->ivav[core->ivpt]); - - ui_print_ipc_data(); -} - -void ui_print() { - int l = 1; - - ui_line(false, l++, PAIR_HEADER, A_BOLD, "SALIS [%d:%d]", g_core, CORE_COUNT); - ui_str_field(l++, "name", SIM_NAME); - ui_ulx_field(l++, "seed", SEED); - ui_str_field(l++, "fbit", MUTA_FLIP_BIT ? "yes" : "no"); - ui_ulx_field(l++, "asav", AUTO_SAVE_INTERVAL); - ui_str_field(l++, "arch", ARCHITECTURE); - ui_ulx_field(l++, "size", MVEC_SIZE); - ui_ulx_field(l++, "syni", SYNC_INTERVAL); - ui_ulx_field(l++, "step", g_steps); - ui_ulx_field(l++, "sync", g_syncs); - ui_ulx_field(l++, "step", g_step_block); - - switch (g_page) { - case PAGE_CORE: - ui_print_core(l); - break; - case PAGE_PROCESS: - ui_print_process(l); - break; - case PAGE_WORLD: - ui_print_world(l); - break; - case PAGE_IPC: - ui_print_ipc(l); - break; - default: - break; - } -} - -void ev_vscroll(int ev) { - switch (g_page) { - case PAGE_PROCESS: - switch (ev) { - case 'W': - g_proc_scroll += (LINES > PROC_PAGE_LINES) ? LINES - PROC_PAGE_LINES : 0; - break; - case 'S': - g_proc_scroll -= (LINES > PROC_PAGE_LINES) ? LINES - PROC_PAGE_LINES : 0; - break; - case 'w': - g_proc_scroll += 1; - break; - case 's': - g_proc_scroll -= 1; - break; - case 'q': - g_proc_scroll = 0; - break; - default: - break; - } - - break; - case PAGE_WORLD: { - switch (ev) { - case 'W': - g_wrld_pos += g_vsiz_rng; - break; - case 'S': - g_wrld_pos -= g_vsiz_rng; - break; - case 'w': - g_wrld_pos += g_vlin_rng; - break; - case 's': -#ifdef MVEC_LOOP - g_wrld_pos -= g_vlin_rng; -#else - if (g_wrld_pos < g_vlin_rng) { - g_wrld_pos = 0; - } else { - g_wrld_pos -= g_vlin_rng; - } -#endif - break; - case 'q': - g_wrld_pos = 0; - break; - default: - break; - } - - break; - } - case PAGE_IPC: - switch (ev) { - case 'W': - g_ivpt_scroll += LINES; - break; - case 'S': - g_ivpt_scroll -= g_ivpt_scroll < (u64)LINES ? g_ivpt_scroll : (u64)LINES; - break; - case 'w': - g_ivpt_scroll += 1; - break; - case 's': - g_ivpt_scroll -= g_ivpt_scroll ? 1 : 0; - break; - case 'q': - g_ivpt_scroll = 0; - break; - } - - break; - default: - break; - } -} - -void ev_hscroll(int ev) { - switch (g_page) { - case PAGE_PROCESS: { - u64 *hs_var = g_proc_genes ? &g_proc_gene_scroll : &g_proc_field_scroll; - - switch (ev) { - case 'A': - *hs_var = 0; - break; - case 'a': - *hs_var -= *hs_var ? 1 : 0; - break; - case 'd': - (*hs_var)++; - break; - default: - break; - } - - break; - } - - case PAGE_WORLD: - switch (ev) { - case 'a': -#ifdef MVEC_LOOP - g_wrld_pos -= g_wrld_zoom; -#else - if (g_wrld_pos < g_wrld_zoom) { - g_wrld_pos = 0; - } else { - g_wrld_pos -= g_wrld_zoom; - } -#endif - break; - case 'd': - g_wrld_pos += g_wrld_zoom; - break; - default: - break; - } - - break; - default: - break; - } -} - -void ev_zoom(int ev) { - switch (g_page) { - case PAGE_WORLD: - switch (ev) { - case 'x': - g_wrld_zoom *= (g_vlin != 0 && g_vsiz_rng < MVEC_SIZE) ? 2 : 1; - ui_world_resize(); - break; - case 'z': - g_wrld_zoom /= (g_wrld_zoom != 1) ? 2 : 1; - ui_world_resize(); - break; - default: - break; - } - - break; - default: - break; - } -} - -void ev_move_wcursor(int ev) { - switch (ev) { - case KEY_UP: - g_wcursor_y -= (g_wcursor_y != 0) ? 1 : 0; - break; - case KEY_DOWN: - g_wcursor_y += (g_wcursor_y < LINES - 2) ? 1 : 0; - break; - case KEY_LEFT: - g_wcursor_x -= (g_wcursor_x != 0) ? 1 : 0; - break; - case KEY_RIGHT: - g_wcursor_x += ((u64)g_wcursor_x < g_vlin - 1) ? 1 : 0; - break; - default: - break; - } -} - -void ev_sel_proc(int ev) { - if (g_page != PAGE_PROCESS && g_page != PAGE_WORLD) { - return; - } - - switch (ev) { - case 'o': - g_proc_selected -= 1; - break; - case 'p': - g_proc_selected += 1; - break; - case 'f': - g_proc_selected = g_cores[g_core].pfst; - break; - case 'l': - g_proc_selected = g_cores[g_core].plst; - break; - default: - break; - } -} - -void ev_goto_sel_proc() { - switch (g_page) { - case PAGE_PROCESS: - g_proc_scroll = g_proc_selected; - break; - case PAGE_WORLD: - g_wrld_pos = g_cores[g_core].pvec[g_proc_selected % g_cores[g_core].pcap].mb0a; - break; - default: - break; - } -} - -void ev_handle() { - int ev = getch(); - - if (g_page == PAGE_WORLD && g_wcursor_mode) { - switch (ev) { - case KEY_UP: - case KEY_DOWN: - case KEY_LEFT: - case KEY_RIGHT: - ev_move_wcursor(ev); - return; - case '\n': - if (g_wcursor_pointed != (u64)(-1)) { - g_proc_selected = g_wcursor_pointed; - } - - break; - default: - break; - } - } - - switch (ev) { - case CTRL('c'): - g_exit = true; - break; - case KEY_SLEFT: - clear(); - g_core = (g_core - 1) % CORE_COUNT; - break; - case KEY_SRIGHT: - clear(); - g_core = (g_core + 1) % CORE_COUNT; - break; - case KEY_LEFT: - clear(); - g_page = (g_page - 1) % PAGE_COUNT; - break; - case KEY_RIGHT: - clear(); - g_page = (g_page + 1) % PAGE_COUNT; - break; - case KEY_RESIZE: - clear(); - ui_line_buff_resize(); - ui_world_resize(); - - if (g_vlin) { - while (g_vsiz_rng >= MVEC_SIZE * 2 && g_wrld_zoom != 1) { - g_wrld_zoom /= 2; - ui_world_resize(); - } - } - - g_wcursor_mode = false; - break; - case 'W': - case 'S': - case 'w': - case 's': - case 'q': - ev_vscroll(ev); - break; - case 'A': - case 'a': - case 'd': - ev_hscroll(ev); - break; - case 'z': - case 'x': - ev_zoom(ev); - break; - case 'o': - case 'p': - case 'f': - case 'l': - ev_sel_proc(ev); - break; - case 'k': - ev_goto_sel_proc(); - break; - case 'g': - if (g_page == PAGE_PROCESS) { - clear(); - g_proc_genes = !g_proc_genes; - } - - break; - case 'c': - if (g_page == PAGE_WORLD) { - clear(); - - if (g_vlin == 0) { - g_wcursor_mode = false; - } else { - g_wcursor_mode = !g_wcursor_mode; - } - } - - break; - case ' ': - g_running = !g_running; - nodelay(stdscr, g_running); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '0': - if (!g_running) { - u64 cycles = 1 << (((ev - '0') ? (ev - '0') : 10) - 1); - salis_step(cycles); - } - - break; - default: - break; - } -} - -void init() { - setlocale(LC_ALL, ""); - - initscr(); - raw(); - noecho(); - curs_set(0); - keypad(stdscr, TRUE); - - start_color(); - init_color(COLOR_BLACK, 0, 0, 0); - - init_pair(PAIR_NORMAL, COLOR_WHITE, COLOR_BLACK ); - init_pair(PAIR_HEADER, COLOR_BLUE, COLOR_BLACK ); - init_pair(PAIR_LIVE_PROC, COLOR_BLUE, COLOR_BLACK ); - init_pair(PAIR_SELECTED_PROC, COLOR_YELLOW, COLOR_BLACK ); - init_pair(PAIR_FREE_CELL, COLOR_BLACK, COLOR_BLUE ); - init_pair(PAIR_ALLOC_CELL, COLOR_BLACK, COLOR_CYAN ); - init_pair(PAIR_MEM_BLOCK_START, COLOR_BLACK, COLOR_WHITE ); - init_pair(PAIR_SELECTED_MB1, COLOR_BLACK, COLOR_YELLOW ); - init_pair(PAIR_SELECTED_MB2, COLOR_BLACK, COLOR_GREEN ); - init_pair(PAIR_SELECTED_IP, COLOR_BLACK, COLOR_RED ); - init_pair(PAIR_SELECTED_SP, COLOR_BLACK, COLOR_MAGENTA); - -#if ACTION == ACT_NEW - salis_init(); -#elif ACTION == ACT_LOAD - salis_load(); -#endif - - g_wrld_zoom = 1; - g_step_block = 1; - - ui_line_buff_resize(); - ui_world_resize(); -} - -void exec() { - while (!g_exit) { - if (g_running) { - clock_t beg = clock(); - salis_step(g_step_block - (g_steps % g_step_block)); - clock_t end = clock(); - - if ((end - beg) < (CLOCKS_PER_SEC / 30)) { - g_step_block <<= 1; - } - - if ((end - beg) >= (CLOCKS_PER_SEC / 60) && g_step_block != 1) { - g_step_block >>= 1; - } - } - - ui_print(); - ev_handle(); - } -} - -void quit() { - gfx_free(); - ui_line_buff_free(); - salis_save(SIM_PATH); - salis_free(); - endwin(); -} - -int main() { - init(); - exec(); - quit(); - - return 0; -} diff --git a/src/ui/daemon.c b/src/ui/daemon.c deleted file mode 100644 index f74713d..0000000 --- a/src/ui/daemon.c +++ /dev/null @@ -1,63 +0,0 @@ -// Project: Salis -// Author: Paul Oliver -// Email: contact@pauloliver.dev - -/* - * Implements a minimal UI for the Salis simulator with minimal output and - * interruptible via OS signals. Ideal for running Salis in the background. - */ - -#include <signal.h> -#include <unistd.h> - -volatile bool g_running; -u64 g_step_block; - -void sig_handler(int signo) { - switch (signo) { - case SIGINT: - case SIGTERM: - printf("signal received, stopping simulator...\n"); - g_running = false; - break; - } -} - -void step_block() { - clock_t beg = clock(); - salis_step(g_step_block - (g_steps % g_step_block)); - clock_t end = clock(); - - if ((end - beg) < (CLOCKS_PER_SEC * 4)) { - g_step_block <<= 1; - } - - if ((end - beg) >= (CLOCKS_PER_SEC * 2) && g_step_block != 1) { - g_step_block >>= 1; - } - - printf("simulator running on step '%#lx'\n", g_steps); -} - -int main() { -#if ACTION == ACT_NEW - salis_init(); -#elif ACTION == ACT_LOAD - salis_load(); -#endif - - g_running = true; - g_step_block = 1; - - signal(SIGINT, sig_handler); - signal(SIGTERM, sig_handler); - - while (g_running) { - step_block(); - } - - salis_save(SIM_PATH); - salis_free(); - - return 0; -} |
