From cf9b3de8fcb590eed85112e3427b6223f643c90c Mon Sep 17 00:00:00 2001 From: Paul Oliver Date: Thu, 29 Feb 2024 01:50:44 +0100 Subject: Faults replace instructions randomly. --- README.md | 5 ++--- include/evolver.h | 1 + include/instset.h | 10 +++++----- src/evolver.c | 8 ++++++++ src/instset.c | 12 ++++++------ src/process.c | 46 +++++++++++++++++++++++++++++++++++++--------- 6 files changed, 59 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index eefb982..9e7dff9 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,10 @@ address is selected and a random instruction is written into it. *SALIS*' organisms read a simple language similar to ASM. This language consists of 64 instructions, each with an associated name and symbol. Whenever an organism performs an invalid instruction it's considered a *fault*. -To preserve robustness, faulty instructions are simply ignored by the -organisms and their IPs are incremented to the next address. +When a *fault* is commited by any organism, the faulty instruction gets +randomly replaced at that address and the organism's IP gets incremented. #### Faults -- IP or SP reaching ends of memory - Perform a search or attempt a jump without a following key - Writing to an allocated (but not owned) or invalid address - Reading (loading) from an invalid address diff --git a/include/evolver.h b/include/evolver.h index 15a4f64..ea26c58 100644 --- a/include/evolver.h +++ b/include/evolver.h @@ -12,6 +12,7 @@ sbyte se_getLastInst (void); sword se_getState (sword eidx); void se_setState (sword eidx, sword state); +void se_randomizeAt (sword addr); void se_cycle (void); #endif diff --git a/include/instset.h b/include/instset.h index e819ff3..f333c76 100644 --- a/include/instset.h +++ b/include/instset.h @@ -84,10 +84,10 @@ enum sinst { #undef SILST }; -sbool si_isInst (sbyte inst); -sbool si_isMod (sbyte inst); -sbool si_isKey (sbyte inst); -sbool si_isLock (sbyte inst); -sbool si_keyLockMatch (sbyte key, sbyte lock); +sbool si_isInst (sword inst); +sbool si_isMod (sword inst); +sbool si_isKey (sword inst); +sbool si_isLock (sword inst); +sbool si_keyLockMatch (sword key, sword lock); #endif diff --git a/src/evolver.c b/src/evolver.c index ba043a3..6635097 100644 --- a/src/evolver.c +++ b/src/evolver.c @@ -112,6 +112,14 @@ generateRandomNumber(void) return t; } +void +se_randomizeAt(sword addr) +{ + assert(g_isInit); + assert(sm_isValidAt(addr)); + sm_setInstAt(addr, (sbyte)(generateRandomNumber() % SINST_COUNT)); +} + void se_cycle(void) { diff --git a/src/instset.c b/src/instset.c index 1333ffb..e0556b0 100644 --- a/src/instset.c +++ b/src/instset.c @@ -3,13 +3,13 @@ #include "instset.h" sbool -si_isInst(sbyte inst) +si_isInst(sword inst) { return inst < SINST_COUNT; } static sbool -isBetween(sbyte inst, sbyte lo, sbyte hi) +isBetween(sword inst, sword lo, sword hi) { assert(si_isInst(inst)); assert(lo < SINST_COUNT); @@ -27,28 +27,28 @@ isBetween(sbyte inst, sbyte lo, sbyte hi) } sbool -si_isMod(sbyte inst) +si_isMod(sword inst) { assert(si_isInst(inst)); return isBetween(inst, SNOP0, SNOP3); } sbool -si_isKey(sbyte inst) +si_isKey(sword inst) { assert(si_isInst(inst)); return isBetween(inst, SKEYA, SKEYP); } sbool -si_isLock(sbyte inst) +si_isLock(sword inst) { assert(si_isInst(inst)); return isBetween(inst, SLOKA, SLOKP); } sbool -si_keyLockMatch(sbyte key, sbyte lock) +si_keyLockMatch(sword key, sword lock) { assert(si_isKey(key)); assert(si_isInst(lock)); diff --git a/src/process.c b/src/process.c index e3d3c18..faee0df 100644 --- a/src/process.c +++ b/src/process.c @@ -6,6 +6,7 @@ #include "instset.h" #include "memory.h" #include "process.h" +#include "evolver.h" static sbool g_isInit; static sword g_count; @@ -57,14 +58,14 @@ sp_load(FILE *file) void sp_save(FILE *file) { -assert(g_isInit); -assert(file); -fwrite(&g_isInit, sizeof(sbool), 1, file); -fwrite(&g_count, sizeof(sword), 1, file); -fwrite(&g_cap, sizeof(sword), 1, file); -fwrite(&g_first, sizeof(sword), 1, file); -fwrite(&g_last, sizeof(sword), 1, file); -fwrite(g_procs, sizeof(SProc), g_cap, file); + assert(g_isInit); + assert(file); + fwrite(&g_isInit, sizeof(sbool), 1, file); + fwrite(&g_count, sizeof(sword), 1, file); + fwrite(&g_cap, sizeof(sword), 1, file); + fwrite(&g_first, sizeof(sword), 1, file); + fwrite(&g_last, sizeof(sword), 1, file); + fwrite(g_procs, sizeof(SProc), g_cap, file); } sbool @@ -307,6 +308,18 @@ incrementIP(sword pidx) g_procs[pidx].sp = g_procs[pidx].ip; } +static void +onFault(sword pidx) +{ + sword ip; + assert(g_isInit); + assert(pidx < g_cap); + assert(!sp_isFree(pidx)); + ip = sp_getProc(pidx).ip; + assert(sm_isValidAt(ip)); + se_randomizeAt(ip); +} + static sbool seek(sword pidx, sbool forward) { @@ -319,6 +332,7 @@ seek(sword pidx, sbool forward) nextAddr = g_procs[pidx].ip + 1; if (!sm_isValidAt(nextAddr)) { + onFault(pidx); incrementIP(pidx); return SFALSE; } @@ -326,6 +340,7 @@ seek(sword pidx, sbool forward) nextInst = sm_getInstAt(nextAddr); if (!si_isKey(nextInst)) { + onFault(pidx); incrementIP(pidx); return SFALSE; } @@ -520,6 +535,7 @@ alloc(sword pidx, sbool forward) } if (g_procs[pidx].sp != correctAddr) { + onFault(pidx); incrementIP(pidx); return; } @@ -588,6 +604,8 @@ bswap(sword pidx) g_procs[pidx].mb1s = g_procs[pidx].mb2s; g_procs[pidx].mb2a = addrTmp; g_procs[pidx].mb2s = sizeTmp; + } else { + onFault(pidx); } incrementIP(pidx); @@ -602,6 +620,8 @@ bclear(sword pidx) if (g_procs[pidx].mb2s) { freeMemBlock2Of(pidx); + } else { + onFault(pidx); } incrementIP(pidx); @@ -618,6 +638,8 @@ split(sword pidx) create(g_procs[pidx].mb2a, g_procs[pidx].mb2s, pidx, SFALSE); g_procs[pidx].mb2a = 0; g_procs[pidx].mb2s = 0; + } else { + onFault(pidx); } incrementIP(pidx); @@ -632,8 +654,9 @@ r3op(sword pidx, sbyte inst) assert(!sp_isFree(pidx)); getRegAddrList(pidx, regs, 3, SFALSE); - /* ignore when dividing by zero */ + /* fault when dividing by zero */ if ((inst == SDIVN) && (*regs[2] == 0)) { + onFault(pidx); incrementIP(pidx); return; } @@ -755,6 +778,7 @@ load(sword pidx) getRegAddrList(pidx, regs, 2, SFALSE); if (!sm_isValidAt(*regs[0])) { + onFault(pidx); incrementIP(pidx); return; } @@ -801,11 +825,13 @@ write(sword pidx) getRegAddrList(pidx, regs, 2, SFALSE); if (!sm_isValidAt(*regs[0])) { + onFault(pidx); incrementIP(pidx); return; } if (!si_isInst(*regs[1])) { + onFault(pidx); incrementIP(pidx); return; } @@ -817,6 +843,8 @@ write(sword pidx) } else { if (isWriteableBy(pidx, *regs[0])) { sm_setInstAt(*regs[0], *regs[1]); + } else { + onFault(pidx); } incrementIP(pidx); -- cgit v1.2.1