diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/process.c | 253 |
1 files changed, 76 insertions, 177 deletions
diff --git a/src/process.c b/src/process.c index 4004ae1..7483aa7 100644 --- a/src/process.c +++ b/src/process.c @@ -510,13 +510,12 @@ static void toggle_ip_flag(void (*toggler)(uint32 address)) static void on_fault(uint32 pidx) { - /* Organisms get punished whenever they execute an invalid instruction - (commit a 'fault') by having the halt one simulation cycle. + /* For now, faults do nothing. */ assert(g_is_init); assert(pidx < g_capacity); assert(!sal_proc_is_free(pidx)); - g_procs[pidx].punish = 1; + (void)pidx; } static void increment_ip(uint32 pidx) @@ -995,6 +994,12 @@ static void one_reg_op(uint32 pidx, uint8 inst) case DECN: (*reg)--; break; + case SHFL: + (*reg) <<= 1; + break; + case SHFR: + (*reg) >>= 1; + break; case ZERO: (*reg) = 0; break; @@ -1266,188 +1271,82 @@ pop(uint32 pidx) increment_ip(pidx); } -static boolean eat_seek(uint32 pidx, boolean forward) -{ - /* Search (via the seeker pointer) for an identical copy of the memory - stream right in front of the calling organism's IP. This function gets - called by organisms each cycle during an EAT instruction. Only when a valid - copy is found, this function will return TRUE. */ - uint32 next_addr; - uint8 next_inst; - uint8 sp_inst; - assert(g_is_init); - assert(pidx < g_capacity); - assert(!sal_proc_is_free(pidx)); - next_addr = g_procs[pidx].ip + 1; - - if (!sal_mem_is_address_valid(next_addr)) { - on_fault(pidx); - increment_ip(pidx); - return FALSE; - } - - /* Processes may only eat code copies from memory areas that are either - deallocated or owned by them (i.e. writeable). - */ - if ( - !is_writeable_by(pidx, g_procs[pidx].sp) || - g_procs[pidx].sp == next_addr - ) { - increment_sp(pidx, forward); - return FALSE; - } - - next_inst = sal_mem_get_inst(next_addr); - sp_inst = sal_mem_get_inst(g_procs[pidx].sp); - - if (next_inst == sp_inst) { - return TRUE; - } - - increment_sp(pidx, forward); - return FALSE; -} - -static void eat(uint32 pidx) -{ - /* Salisian organisms may 'eat' information. They eat by searching for - 'copies' of the code in front of their IPs during the EAT instruction. When - a valid copy is found, an organism gets rewarded by setting their 'reward' - field to the length of the measured copy. Each cycle, organisms execute - 'reward' number of instructions plus one, thus, eating a larger stream - produces a larger advantage for an organism. - - However, whenever an organism eats, the detected copy of the source code - gets destroyed (randomized). The main idea of the EAT instruction is to - turn 'information' into a valuable resource in Salis. Organisms, - nonetheless, may only eat information which they have 'write' access to. - */ - uint32 source; - uint32 target; - assert(g_is_init); - assert(pidx < g_capacity); - assert(!sal_proc_is_free(pidx)); - source = g_procs[pidx].ip + 1; - target = g_procs[pidx].sp; - assert(sal_mem_is_address_valid(source)); - assert(sal_mem_get_inst(source) == sal_mem_get_inst(target)); - g_procs[pidx].reward = 0; - - while ( - sal_mem_is_address_valid(source) && - sal_mem_is_address_valid(target) && - sal_mem_get_inst(source) == sal_mem_get_inst(target) - ) { - g_procs[pidx].reward++; - _sal_evo_randomize_at(target); - source++; - target++; - } - - increment_ip(pidx); -} - static void proc_cycle(uint32 pidx) { - /* Cycle a process once. During each process cycle, several things may - happen. For example, if a process is being punished (for committing a - fault), it will have to wait until the next simulation cycle to be able to - execute. - - Non-punished organisms execute at least one instruction per simulation - cycle. If they are being rewarded, they execute one, plus the number on - their 'reward' field, number of instructions each cycle. + /* Cycle a process once. Organisms will always execute one instruction per + simulation cycle. */ - uint32 cycles; + uint8 inst; assert(g_is_init); assert(pidx < g_capacity); assert(!sal_proc_is_free(pidx)); - /* Organism is being punished. Clear its 'punish' field and return without - executing. - */ - if (g_procs[pidx].punish) { - g_procs[pidx].punish = 0; - return; - } + inst = sal_mem_get_inst(g_procs[pidx].ip); + g_instructions_executed++; - /* Execute one instruction per number of 'reward' points awarded to this - organism. Switch case associates each instruction to its corresponding - instruction handler. Process module keeps track of the total number of - instructions executed (by all organisms) per simulation cycle. - */ - for (cycles = 0; cycles < g_procs[pidx].reward + 1; cycles++) { - uint8 inst = sal_mem_get_inst(g_procs[pidx].ip); - g_instructions_executed++; - - switch (inst) { - case JMPB: - if (jump_seek(pidx, FALSE)) jump(pidx); - break; - case JMPF: - if (jump_seek(pidx, TRUE)) jump(pidx); - break; - case ADRB: - if (addr_seek(pidx, FALSE)) addr(pidx); - break; - case ADRF: - if (addr_seek(pidx, TRUE)) addr(pidx); - break; - case MALB: - alloc(pidx, FALSE); - break; - case MALF: - alloc(pidx, TRUE); - break; - case SWAP: - swap(pidx); - break; - case SPLT: - split(pidx); - break; - case INCN: - case DECN: - case ZERO: - case UNIT: - case NOTN: - one_reg_op(pidx, inst); - break; - case IFNZ: - if_not_zero(pidx); - break; - case SUMN: - case SUBN: - case MULN: - case DIVN: - three_reg_op(pidx, inst); - break; - case LOAD: - load(pidx); - break; - case WRTE: - write(pidx); - break; - case SEND: - send(pidx); - break; - case RECV: - receive(pidx); - break; - case PSHN: - push(pidx); - break; - case POPN: - pop(pidx); - break; - case EATB: - if (eat_seek(pidx, FALSE)) eat(pidx); - break; - case EATF: - if (eat_seek(pidx, TRUE)) eat(pidx); - break; - default: - increment_ip(pidx); - } + switch (inst) { + case JMPB: + if (jump_seek(pidx, FALSE)) jump(pidx); + break; + case JMPF: + if (jump_seek(pidx, TRUE)) jump(pidx); + break; + case ADRB: + if (addr_seek(pidx, FALSE)) addr(pidx); + break; + case ADRF: + if (addr_seek(pidx, TRUE)) addr(pidx); + break; + case MALB: + alloc(pidx, FALSE); + break; + case MALF: + alloc(pidx, TRUE); + break; + case SWAP: + swap(pidx); + break; + case SPLT: + split(pidx); + break; + case INCN: + case DECN: + case SHFL: + case SHFR: + case ZERO: + case UNIT: + case NOTN: + one_reg_op(pidx, inst); + break; + case IFNZ: + if_not_zero(pidx); + break; + case SUMN: + case SUBN: + case MULN: + case DIVN: + three_reg_op(pidx, inst); + break; + case LOAD: + load(pidx); + break; + case WRTE: + write(pidx); + break; + case SEND: + send(pidx); + break; + case RECV: + receive(pidx); + break; + case PSHN: + push(pidx); + break; + case POPN: + pop(pidx); + break; + default: + increment_ip(pidx); } } |