aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2025-11-19 04:42:58 +0100
committerPaul Oliver <contact@pauloliver.dev>2025-11-19 16:40:08 +0100
commit0075d1b10c475d303a314a3425ee472252855f32 (patch)
tree2537411ad2b9691f413eeab62d7f541724ea47c6 /src
parentd91b8a6196af711f9dface0c2a0d37794c12ac02 (diff)
Python/SQLite refactor
- Uses Python/Jinja2 to preprocess C files - Uses SQLite3 for data compression
Diffstat (limited to 'src')
-rw-r--r--src/arch/dummy.c152
-rw-r--r--src/arch/salis-v1.c875
-rw-r--r--src/bench.c49
-rw-r--r--src/graphics.c238
-rw-r--r--src/salis.c811
-rw-r--r--src/ui/curses.c965
-rw-r--r--src/ui/daemon.c63
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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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;
-}