aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2024-02-29 01:50:44 +0100
committerPaul Oliver <contact@pauloliver.dev>2024-02-29 01:50:44 +0100
commitcf9b3de8fcb590eed85112e3427b6223f643c90c (patch)
treed900e53ac2b2fddb12d6f56789701ee826edfac6
parent2aaaca4299306b7a5bf62390c6028bc0a2c1ac73 (diff)
Faults replace instructions randomly.
-rw-r--r--README.md5
-rw-r--r--include/evolver.h1
-rw-r--r--include/instset.h10
-rw-r--r--src/evolver.c8
-rw-r--r--src/instset.c12
-rw-r--r--src/process.c46
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
@@ -113,6 +113,14 @@ generateRandomNumber(void)
}
void
+se_randomizeAt(sword addr)
+{
+ assert(g_isInit);
+ assert(sm_isValidAt(addr));
+ sm_setInstAt(addr, (sbyte)(generateRandomNumber() % SINST_COUNT));
+}
+
+void
se_cycle(void)
{
assert(g_isInit);
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);