diff options
-rw-r--r-- | bin/modules/handler.py | 2 | ||||
-rw-r--r-- | bin/modules/printer.py | 3 | ||||
-rwxr-xr-x | bin/salis.py | 5 | ||||
-rw-r--r-- | include/common.h | 17 | ||||
-rw-r--r-- | include/evolver.h | 23 | ||||
-rw-r--r-- | include/instset.h | 12 | ||||
-rw-r--r-- | include/memory.h | 52 | ||||
-rw-r--r-- | include/process.h | 44 | ||||
-rw-r--r-- | include/render.h | 8 | ||||
-rw-r--r-- | include/salis.h | 24 | ||||
-rw-r--r-- | src/common.c | 22 | ||||
-rw-r--r-- | src/evolver.c | 44 | ||||
-rw-r--r-- | src/instset.c | 18 | ||||
-rw-r--r-- | src/memory.c | 80 | ||||
-rw-r--r-- | src/process.c | 479 | ||||
-rw-r--r-- | src/render.c | 53 | ||||
-rw-r--r-- | src/salis.c | 42 |
17 files changed, 564 insertions, 364 deletions
diff --git a/bin/modules/handler.py b/bin/modules/handler.py index ba2b249..ad62c5c 100644 --- a/bin/modules/handler.py +++ b/bin/modules/handler.py @@ -1,6 +1,6 @@ """ SALIS: Viewer/controller for the SALIS simulator. -file: handler.py +File: handler.py Author: Paul Oliver Email: paul.t.oliver.design@gmail.com diff --git a/bin/modules/printer.py b/bin/modules/printer.py index cfbca84..bf664d2 100644 --- a/bin/modules/printer.py +++ b/bin/modules/printer.py @@ -12,9 +12,10 @@ format. It makes use of the curses library for terminal handling. import curses import curses.textpad import os - from collections import OrderedDict + from ctypes import c_uint32, cast, POINTER + from modules.world import World diff --git a/bin/salis.py b/bin/salis.py index f51484c..e40e72d 100755 --- a/bin/salis.py +++ b/bin/salis.py @@ -20,13 +20,14 @@ import os import re import sys import time - from argparse import ArgumentParser, HelpFormatter +from subprocess import check_call + from ctypes import CDLL, c_bool, c_uint8, c_uint32, c_char_p, POINTER + from modules.common import Common from modules.handler import Handler from modules.printer import Printer -from subprocess import check_call __version__ = "2.0" diff --git a/include/common.h b/include/common.h index 50ac563..2db1258 100644 --- a/include/common.h +++ b/include/common.h @@ -12,24 +12,33 @@ #ifndef SALIS_COMMON_H #define SALIS_COMMON_H -/* Typedef sender functor type for easy python parsing. +/** +* Typedef sender functor type for easy python parsing. */ typedef void (*Sender)(uint8 inst); -/* Typedef receiver functor type for easy python parsing. +/** +* Typedef receiver functor type for easy python parsing. */ typedef uint8 (*Receiver)(void); -/* Set sender functor. When unset, SEND instruction does nothing. +/** +* Set sender functor. When unset, SEND instruction does nothing. * @param sender Sender functor */ SALIS_API void sal_comm_set_sender(Sender sender); -/* Set receiver functor. When unset, RCVE instruction does nothing. +/** +* Set receiver functor. When unset, RCVE instruction does nothing. * @param receiver Receiver functor */ SALIS_API void sal_comm_set_receiver(Receiver receiver); + +/******************************* +* PRIVATES * +*******************************/ + void _sal_comm_send(uint8 inst); uint8 _sal_comm_receive(void); diff --git a/include/evolver.h b/include/evolver.h index 457cd9a..26c7d6a 100644 --- a/include/evolver.h +++ b/include/evolver.h @@ -10,27 +10,34 @@ #ifndef SALIS_EVOLVER_H #define SALIS_EVOLVER_H -void _sal_evo_init(void); -void _sal_evo_quit(void); -void _sal_evo_load_from(FILE *file); -void _sal_evo_save_into(FILE *file); - -/** Get address where the last cosmic ray landed. +/** +* Get address where the last cosmic ray landed. * @return Last address changed by a cosmic ray */ SALIS_API uint32 sal_evo_get_last_changed_address(void); -/** Get amount of random numbers generated during the last simulation cycle. +/** +* Get amount of random numbers generated during the last simulation cycle. * @return Number of calls to the random number generator during the last cycle */ SALIS_API uint32 sal_evo_get_calls_on_last_cycle(void); -/** Access the internal state of the XOR-Shift random number generator. +/** +* Access the internal state of the XOR-Shift random number generator. * @param state_index Index of one of the 32 bit state-blocks [0-4] * @return State of the 32 bit block */ SALIS_API uint32 sal_evo_get_state(uint8 state_index); + +/******************************* +* PRIVATES * +*******************************/ + +void _sal_evo_init(void); +void _sal_evo_quit(void); +void _sal_evo_load_from(FILE *file); +void _sal_evo_save_into(FILE *file); void _sal_evo_randomize_at(uint32 address); void _sal_evo_cycle(void); diff --git a/include/instset.h b/include/instset.h index a7f4773..cde1498 100644 --- a/include/instset.h +++ b/include/instset.h @@ -12,7 +12,8 @@ #define INST_COUNT 32 -/** Salis instruction set. The 'SALIS_INST' macro and inline doc-comments help +/** +* Salis instruction set. The 'SALIS_INST' macro and inline doc-comments help * python parse this file. Don't edit these unless you know what you're doing! */ enum { @@ -50,19 +51,22 @@ enum { SALIS_INST POPN /**< ~ Pop value from stack */ }; -/** Determine if an unsigned integer contains a valid instruction. +/** +* Determine if an unsigned integer contains a valid instruction. * @param byte Any unsigned integer up to 32 bits * @return Whether or nor integer contains a valid instruction */ SALIS_API boolean sal_is_inst(uint32 word); -/** Determine if instruction is a template constructor [NOP0-NOP1]. +/** +* Determine if instruction is a template constructor [NOP0-NOP1]. * @param inst Must contain a valid instruction * @return Whether or not instruction is a template constructor */ SALIS_API boolean sal_is_template(uint32 inst); -/** Determine if instruction a register modifier [MOD0-MOD3]. +/** +* Determine if instruction a register modifier [MOD0-MOD3]. * @param inst Must contain a valid instruction * @return Whether or not instruction is a register modifier */ diff --git a/include/memory.h b/include/memory.h index 6376d7c..e144228 100644 --- a/include/memory.h +++ b/include/memory.h @@ -13,75 +13,89 @@ #define ALLOCATED_FLAG 0x20 #define INSTRUCTION_MASK 0x1f -void _sal_mem_init(uint32 order); -void _sal_mem_quit(void); -void _sal_mem_load_from(FILE *file); -void _sal_mem_save_into(FILE *file); - -/** Get memory order. +/** +* Get memory order. * @return Order of memory (memory_size == 1 << order) */ SALIS_API uint32 sal_mem_get_order(void); -/** Get memory size. +/** +* Get memory size. * @return Size of memory (memory_size == 1 << order) */ SALIS_API uint32 sal_mem_get_size(void); -/** Get amount of addresses with the allocated flag set on them. +/** +* Get amount of addresses with the allocated flag set on them. * @return Amount of addresses with the allocated flag set */ SALIS_API uint32 sal_mem_get_allocated(void); -/** Get memory capacity. +/** +* Get memory capacity. * @return Memory capacity (capacity == size / 2) */ SALIS_API uint32 sal_mem_get_capacity(void); -/** Get amount of addresses with a given instruction written on them. +/** +* Get amount of addresses with a given instruction written on them. * @param inst Instruction whose amount we want to count * @return Amount of addresses with given instruction */ SALIS_API uint32 sal_mem_get_inst_count(uint8 inst); -/** Determine if memory is above its capacity. +/** +* Determine if memory is above its capacity. * @return Memory is above capacity */ SALIS_API boolean sal_mem_is_over_capacity(void); -/** Check validity of address. +/** +* Check validity of address. * @param address Address being queried * @return Validity of address (validity == address < size) */ SALIS_API boolean sal_mem_is_address_valid(uint32 address); -/** Check if given address has the allocated flag set. +/** +* Check if given address has the allocated flag set. * @param address Address being queried * @return Allocated flag is set on this address */ SALIS_API boolean sal_mem_is_allocated(uint32 address); -void _sal_mem_set_allocated(uint32 address); -void _sal_mem_unset_allocated(uint32 address); - -/** Get current instruction at address. +/** +* Get current instruction at address. * @param address Address being queried * @return Instruction currently written at address */ SALIS_API uint8 sal_mem_get_inst(uint32 address); -/** Write instruction into address. +/** +* Write instruction into address. * @param address Address being set * @param inst Instruction to write at given address */ SALIS_API void sal_mem_set_inst(uint32 address, uint8 inst); -/** Get current byte at address. +/** +* Get current byte at address. * @param address Address being queried * @return Byte currently written at address (includes alloc-flag & instruction) */ SALIS_API uint8 sal_mem_get_byte(uint32 address); + +/******************************* +* PRIVATES * +*******************************/ + +void _sal_mem_init(uint32 order); +void _sal_mem_quit(void); +void _sal_mem_load_from(FILE *file); +void _sal_mem_save_into(FILE *file); +void _sal_mem_set_allocated(uint32 address); +void _sal_mem_unset_allocated(uint32 address); void _sal_mem_cycle(void); #endif diff --git a/include/process.h b/include/process.h index 26772c3..aa017c6 100644 --- a/include/process.h +++ b/include/process.h @@ -11,7 +11,8 @@ #ifndef SALIS_PROCESS_H #define SALIS_PROCESS_H -/** The Process data-structure. The 'SALIS_PROC_ELEMENT' macro helps python +/** +* The Process data-structure. The 'SALIS_PROC_ELEMENT' macro helps python * parse the struct, so don't change it! */ struct Process @@ -31,59 +32,72 @@ struct Process typedef struct Process Process; -void _sal_proc_init(void); -void _sal_proc_quit(void); -void _sal_proc_load_from(FILE *file); -void _sal_proc_save_into(FILE *file); - -/** Get process count. +/** +* Get process count. * @return Amount of running (living) processes */ SALIS_API uint32 sal_proc_get_count(void); -/** Get reaper queue capacity. +/** +* Get reaper queue capacity. * @return Currently allocated size of reaper queue */ SALIS_API uint32 sal_proc_get_capacity(void); -/** Get first process. +/** +* Get first process. * @return Process currently on top of reaper queue */ SALIS_API uint32 sal_proc_get_first(void); -/** Get last process. +/** +* Get last process. * @return Process currently on bottom of reaper queue (closest to death) */ SALIS_API uint32 sal_proc_get_last(void); -/** Check if process is currently free. +/** +* Check if process is currently free. * @param proc_id ID of process whose status we want to check * @return Status (either free or running) of the process with the given ID */ SALIS_API boolean sal_proc_is_free(uint32 proc_id); -/** Get process. +/** +* Get process. * @param proc_id ID of Process being queried * @return A copy of the process with the given ID */ SALIS_API Process sal_proc_get_proc(uint32 proc_id); -/** Get process data. +/** +* Get process data. * @param proc_id ID of Process being queried * @param buffer Pre-allocated buffer to store data on [ > sizeof(Process)] */ SALIS_API void sal_proc_get_proc_data(uint32 proc_id, uint32_p buffer); -/** Create new process. +/** +* Create new process. * @param address Address we want to allocate our process into * @param mb1_size Size of the memory block we want to allocate for our process */ SALIS_API void sal_proc_create(uint32 address, uint32 mb1_size); -/** Kill process on bottom of reaper queue. +/** +* Kill process on bottom of reaper queue. */ SALIS_API void sal_proc_kill(void); + +/******************************* +* PRIVATES * +*******************************/ + +void _sal_proc_init(void); +void _sal_proc_quit(void); +void _sal_proc_load_from(FILE *file); +void _sal_proc_save_into(FILE *file); void _sal_proc_cycle(void); #endif diff --git a/include/render.h b/include/render.h index b48fb8f..9a659c4 100644 --- a/include/render.h +++ b/include/render.h @@ -10,7 +10,8 @@ #ifndef SALIS_RENDER_H #define SALIS_RENDER_H -/** Render a 1D image of a given block of memory. This is useful, as rendering +/** +* Render a 1D image of a given block of memory. This is useful, as rendering * directly in python would be too slow. We use openmp for multi-threaded image * generation. * @@ -19,7 +20,8 @@ * @param buff_size Amount of pixels (cells) to be generated * @param buffer Pre-allocated buffer to store the rendered pixels into */ -SALIS_API void sal_ren_get_image(uint32 origin, uint32 cell_size, - uint32 buff_size, uint8_p buffer); +SALIS_API void sal_ren_get_image( + uint32 origin, uint32 cell_size, uint32 buff_size, uint8_p buffer +); #endif diff --git a/include/salis.h b/include/salis.h index 75ef9dd..4394cdb 100644 --- a/include/salis.h +++ b/include/salis.h @@ -20,41 +20,49 @@ #include <common.h> #include <process.h> -/** Initialize Salis simulation. +/** +* Initialize Salis simulation. * @param order Order of memory (memory_size == 1 << order) */ SALIS_API void sal_main_init(uint32 order); -/** Free resources and quit Salis. +/** +* Free resources and quit Salis. */ SALIS_API void sal_main_quit(void); -/** Load existing Salis simulation from saved file. +/** +* Load existing Salis simulation from saved file. * @param file_name Path of the save file to be loaded */ SALIS_API void sal_main_load(string file_name); -/** Save Salis simulation to a file. +/** +* Save Salis simulation to a file. * @param file_name Path of the save file to be created */ SALIS_API void sal_main_save(string file_name); -/** Check if Salis simulation has been correctly initialized. +/** +* Check if Salis simulation has been correctly initialized. * @return Salis has been correctly initialized */ SALIS_API boolean sal_main_is_init(void); -/** Get current simulation cycle. +/** +* Get current simulation cycle. * @return Current simulation cycle */ SALIS_API uint32 sal_main_get_cycle(void); -/** Get current simulation epoch. +/** +* Get current simulation epoch. * @return Current simulation epoch (1 epoch == 2^32 cycles) */ SALIS_API uint32 sal_main_get_epoch(void); -/** Update simulation once. This will cycle all Salis modules and processes. +/** +* Update simulation once. This will cycle all Salis modules and processes. */ SALIS_API void sal_main_cycle(void); diff --git a/src/common.c b/src/common.c index 402320e..a2fc559 100644 --- a/src/common.c +++ b/src/common.c @@ -8,8 +8,9 @@ static Receiver g_receiver; void sal_comm_set_sender(Sender sender) { - /* Set sender functor. Whenever an organism calls the SEND instruction, - this function will get called. When unset, SEND instruction is ignored. + /* + * Set sender functor. Whenever an organism calls the SEND instruction, + * this function will get called. When unset, SEND instruction is ignored. */ assert(sender); g_sender = sender; @@ -17,8 +18,9 @@ void sal_comm_set_sender(Sender sender) void sal_comm_set_receiver(Receiver receiver) { - /* Set receiver functor. Whenever an organism calls the RCVE instruction, - this function will get called. When unset, RCVE instruction is ignored. + /* + * Set receiver functor. Whenever an organism calls the RCVE instruction, + * this function will get called. When unset, RCVE instruction is ignored. */ assert(receiver); g_receiver = receiver; @@ -26,8 +28,9 @@ void sal_comm_set_receiver(Receiver receiver) void _sal_comm_send(uint8 inst) { - /* Send a single byte (instruction) to the sender. This function is called - by processes that execute the SEND instruction. + /* + * Send a single byte (instruction) to the sender. This function is called + * by processes that execute the SEND instruction. */ assert(sal_is_inst(inst)); @@ -38,9 +41,10 @@ void _sal_comm_send(uint8 inst) uint8 _sal_comm_receive(void) { - /* Receive a single byte (instruction) from the receiver. This function is - called by processes that execute the RCVE instruction. It returns NOP0 is - receiver is unset. + /* + * Receive a single byte (instruction) from the receiver. This function is + * called by processes that execute the RCVE instruction. It returns NOP0 is + * receiver is unset. */ if (g_receiver) { uint8 inst = g_receiver(); diff --git a/src/evolver.c b/src/evolver.c index e3b6ef7..dfba958 100644 --- a/src/evolver.c +++ b/src/evolver.c @@ -16,8 +16,9 @@ static uint32 g_state[4]; void _sal_evo_init(void) { - /* Start up the evolver module. We simply set the 128 bits into a random - state by calling 'rand()'. + /* + * Start up the evolver module. We simply set the 128 bits into a random + * state by calling 'rand()'. */ assert(!g_is_init); srand((uint32)time(NULL)); @@ -30,7 +31,8 @@ void _sal_evo_init(void) void _sal_evo_quit(void) { - /* Quit the evolver module. Reset everything back to zero. + /* + * Quit the evolver module. Reset everything back to zero. */ assert(g_is_init); g_is_init = FALSE; @@ -41,7 +43,8 @@ void _sal_evo_quit(void) void _sal_evo_load_from(FILE *file) { - /* Load evolver state from a binary file. + /* + * Load evolver state from a binary file. */ assert(!g_is_init); assert(file); @@ -53,7 +56,8 @@ void _sal_evo_load_from(FILE *file) void _sal_evo_save_into(FILE *file) { - /* Save evolver state into a binary file. + /* + * Save evolver state into a binary file. */ assert(g_is_init); assert(file); @@ -63,15 +67,17 @@ void _sal_evo_save_into(FILE *file) fwrite(&g_state, sizeof(uint32), 4, file); } -/* Getter methods for the evolver module. +/* +* Getter methods for the evolver module. */ UINT32_GETTER(evo, last_changed_address) UINT32_GETTER(evo, calls_on_last_cycle) uint32 sal_evo_get_state(uint8 state_index) { - /* Get part of the evolver's internal state (32 bits of 128 total bits) as - an unsigned int. + /* + * Get part of the evolver's internal state (32 bits of 128 total bits) as + * an unsigned int. */ assert(g_is_init); assert(state_index < 4); @@ -80,10 +86,11 @@ uint32 sal_evo_get_state(uint8 state_index) static uint32 generate_random_number(void) { - /* Generate a single 32 bit random number. This module makes use of the - XOR-Shift pseudo-rng. We use XOR-Shift because it's extremely lightweight - and fast, while providing quite good results. Find more info about it here: - >>> https://en.wikipedia.org/wiki/Xorshift + /* + * Generate a single 32 bit random number. This module makes use of the + * XOR-Shift pseudo-rng. We use XOR-Shift because it's extremely lightweight + * and fast, while providing quite good results. Find more info about it at: + * https://en.wikipedia.org/wiki/Xorshift */ uint32 tmp1; uint32 tmp2; @@ -103,7 +110,8 @@ static uint32 generate_random_number(void) void _sal_evo_randomize_at(uint32 address) { - /* Place a random instruction into a given address. + /* + * Place a random instruction into a given address. */ uint8 inst; assert(g_is_init); @@ -115,11 +123,11 @@ void _sal_evo_randomize_at(uint32 address) void _sal_evo_cycle(void) { - /* During each simulation cycle, a random 32 bit integer is generated. If - this integer represents a 'valid' address in memory - (i.e. new_rand < memory_size), this address becomes hit by a cosmic ray - (randomized). This simple mutation scheme is enough to drive evolution in - Salis. + /* + * During each simulation cycle, a random 32 bit integer is generated. If + * this integer represents a 'valid' address in memory (new_rand < mem_size), + * this address becomes hit by a cosmic ray (randomized). This simple + * mutation scheme is enough to drive evolution in Salis. */ uint32 address; assert(g_is_init); diff --git a/src/instset.c b/src/instset.c index 2ab127a..94c3df7 100644 --- a/src/instset.c +++ b/src/instset.c @@ -4,15 +4,17 @@ boolean sal_is_inst(uint32 word) { - /* Test if a given 32 bit integer contains a valid Salis instruction. + /* + * Test if a given 32 bit integer contains a valid Salis instruction. */ return word < INST_COUNT; } static boolean is_in_between(uint32 inst, uint32 low, uint32 hi) { - /* Test whether a Salis instruction lies within a given range. This is - useful for identifying template instructions and/or register modifiers. + /* + * Test whether a Salis instruction lies within a given range. This is + * useful for identifying template instructions and/or register modifiers. */ assert(sal_is_inst(inst)); assert(sal_is_inst(low)); @@ -22,8 +24,9 @@ static boolean is_in_between(uint32 inst, uint32 low, uint32 hi) boolean sal_is_template(uint32 inst) { - /* Test whether a given instruction is a template element - (i.e. NOP0 or NOP1). + /* + * Test whether a given instruction is a template element (i.e. NOP0 or + * NOP1). */ assert(sal_is_inst(inst)); return is_in_between(inst, NOP0, NOP1); @@ -31,8 +34,9 @@ boolean sal_is_template(uint32 inst) boolean sal_is_mod(uint32 inst) { - /* Test whether a given instruction is a register modifier - (i.e. MODA, MODB, MODC or MODD). + /* + * Test whether a given instruction is a register modifier (i.e. MODA, MODB, + * MODC or MODD). */ assert(sal_is_inst(inst)); return is_in_between(inst, MODA, MODD); diff --git a/src/memory.c b/src/memory.c index b02a5b9..7f51df4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -17,9 +17,10 @@ static uint8_p g_memory; void _sal_mem_init(uint32 order) { - /* Set memory module to its initial state. We calculate memory size based - on its order (size = 1 << order) and allocate an array of such size. We - also initialize the array completely to zero. + /* + * Set memory module to its initial state. We calculate memory size based + * on its order (size = 1 << order) and allocate an array of such size. We + * also initialize the array completely to zero. */ assert(!g_is_init); assert(order < 32); @@ -34,8 +35,9 @@ void _sal_mem_init(uint32 order) void _sal_mem_quit(void) { - /* Reset memory module entirely back to zero. That way, we can load several - simulations without restarting the application entirely. + /* + * Reset memory module entirely back to zero. That way, we can load several + * simulations without restarting the application entirely. */ assert(g_is_init); free(g_memory); @@ -50,7 +52,8 @@ void _sal_mem_quit(void) void _sal_mem_load_from(FILE *file) { - /* Load memory state from a binary file. + /* + * Load memory state from a binary file. */ assert(!g_is_init); assert(file); @@ -67,7 +70,8 @@ void _sal_mem_load_from(FILE *file) void _sal_mem_save_into(FILE *file) { - /* Save memory state to a binary file. + /* + * Save memory state to a binary file. */ assert(g_is_init); assert(file); @@ -80,7 +84,8 @@ void _sal_mem_save_into(FILE *file) fwrite(g_memory, sizeof(uint8), g_size, file); } -/* Getter methods for the memory module. +/* +* Getter methods for the memory module. */ UINT32_GETTER(mem, order) UINT32_GETTER(mem, size) @@ -89,8 +94,9 @@ UINT32_GETTER(mem, capacity) uint32 sal_mem_get_inst_count(uint8 inst) { - /* Return number of times a certain instruction appears in memory. The - instruction counter gets updated dynamically during each cycle. + /* + * Return number of times a certain instruction appears in memory. The + * instruction counter gets updated dynamically during each cycle. */ assert(g_is_init); assert(sal_is_inst(inst)); @@ -99,8 +105,9 @@ uint32 sal_mem_get_inst_count(uint8 inst) boolean sal_mem_is_over_capacity(void) { - /* Check if memory is filled above 50%. If so, old organisms will be popped - out of the reaper queue! + /* + * Check if memory is filled above 50%. If so, old organisms will be popped + * out of the reaper queue! */ assert(g_is_init); return g_allocated > g_capacity; @@ -108,7 +115,8 @@ boolean sal_mem_is_over_capacity(void) boolean sal_mem_is_address_valid(uint32 address) { - /* Check if given address is valid. + /* + * Check if given address is valid. */ assert(g_is_init); return address < g_size; @@ -116,7 +124,8 @@ boolean sal_mem_is_address_valid(uint32 address) boolean sal_mem_is_allocated(uint32 address) { - /* Check if given address is allocated. + /* + * Check if given address is allocated. */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -125,7 +134,8 @@ boolean sal_mem_is_allocated(uint32 address) void _sal_mem_set_allocated(uint32 address) { - /* Set allocated flag on a given address. + /* + * Set allocated flag on a given address. */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -138,7 +148,8 @@ void _sal_mem_set_allocated(uint32 address) void _sal_mem_unset_allocated(uint32 address) { - /* Unset allocated flag on a given address. + /* + * Unset allocated flag on a given address. */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -151,8 +162,9 @@ void _sal_mem_unset_allocated(uint32 address) uint8 sal_mem_get_inst(uint32 address) { - /* Get instruction currently set on a specified address, with the allocated - bit flag turned off. + /* + * Get instruction currently set on a specified address, with the allocated + * bit flag turned off. */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -161,8 +173,9 @@ uint8 sal_mem_get_inst(uint32 address) void sal_mem_set_inst(uint32 address, uint8 inst) { - /* Set instruction at given address. This is useful when performing manual - memory manipulations (like compiling organism genomes). + /* + * Set instruction at given address. This is useful when performing manual + * memory manipulations (like compiling organism genomes). */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -175,8 +188,9 @@ void sal_mem_set_inst(uint32 address, uint8 inst) uint8 sal_mem_get_byte(uint32 address) { - /* Get unadulterated byte at given address. This could be used, for - example, to render nice images of the memory state. + /* + * Get unadulterated byte at given address. This could be used, for example, + * to render nice images of the memory state. */ assert(g_is_init); assert(sal_mem_is_address_valid(address)); @@ -185,8 +199,9 @@ uint8 sal_mem_get_byte(uint32 address) static boolean inst_count_is_correct(void) { - /* Check that the instruction counter is in a valid state - (i.e. SUM inst_counter[0..(INST_COUNT - 1)] == memory_size). + /* + * Check that the instruction counter is in a valid state (i.e. + * SUM inst_counter[0..(INST_COUNT - 1)] == memory_size). */ uint32 i; uint32 sum = 0; @@ -202,9 +217,10 @@ static boolean inst_count_is_correct(void) static boolean module_is_valid(void) { - /* Check for validity of memory module. This function only gets called when - Salis is running in debug mode. It makes Salis **very** slow in comparison - to when running optimized, but it is also **very** useful for debugging! + /* + * Check for validity of memory module. This function only gets called when + * Salis is running in debug mode. It makes Salis **very** slow in comparison + * to when running optimized, but it is also **very** useful for debugging! */ uint32 bidx; uint32 allocated = 0; @@ -212,8 +228,9 @@ static boolean module_is_valid(void) assert(g_capacity <= g_size / 2); assert(inst_count_is_correct()); - /* Iterate through all memory, counting the flags set on each address. We - then compare the sum to the flag counters to assert module validity. + /* + * Iterate through all memory, counting the flags set on each address. We + * then compare the sum to the flag counters to assert module validity. */ for (bidx = 0; bidx < g_size; bidx++) { if (sal_mem_is_allocated(bidx)) { @@ -227,8 +244,9 @@ static boolean module_is_valid(void) void _sal_mem_cycle(void) { - /* Cycle memory module. Simply assert validity when running in debug mode. - When running optimized, this function does nothing. + /* + * Cycle memory module. Simply assert validity when running in debug mode. + * When running optimized, this function does nothing. */ assert(g_is_init); assert(module_is_valid()); diff --git a/src/process.c b/src/process.c index eb89a8d..3a674c1 100644 --- a/src/process.c +++ b/src/process.c @@ -19,10 +19,11 @@ static Process *g_procs; void _sal_proc_init(void) { - /* Initialize process module to its initial state. We initialize the reaper - queue with a capacity of 1. 'First' and 'last' organism pointers are - initialized to (uint32)-1 (to indicate they point to no organism, as no - organism exists yet). + /* + * Initialize process module to its initial state. We initialize the reaper + * queue with a capacity of 1. 'First' and 'last' organism pointers are + * initialized to (uint32)-1 (to indicate they point to no organism, as no + * organism exists yet). */ assert(!g_is_init); g_is_init = TRUE; @@ -35,7 +36,8 @@ void _sal_proc_init(void) void _sal_proc_quit(void) { - /* Reset process module back to zero; free up the process queue. + /* + * Reset process module back to zero; free up the process queue. */ assert(g_is_init); free(g_procs); @@ -49,7 +51,8 @@ void _sal_proc_quit(void) void _sal_proc_load_from(FILE *file) { - /* Load process module state from a binary file. + /* + * Load process module state from a binary file. */ assert(!g_is_init); assert(file); @@ -65,7 +68,8 @@ void _sal_proc_load_from(FILE *file) void _sal_proc_save_into(FILE *file) { - /* Save process module state to a binary file. + /* + * Save process module state to a binary file. */ assert(g_is_init); assert(file); @@ -77,7 +81,8 @@ void _sal_proc_save_into(FILE *file) fwrite(g_procs, sizeof(Process), g_capacity, file); } -/* Getter methods for the process module. +/* +* Getter methods for the process module. */ UINT32_GETTER(proc, count) UINT32_GETTER(proc, capacity) @@ -86,18 +91,20 @@ UINT32_GETTER(proc, last) boolean sal_proc_is_free(uint32 proc_id) { - /* In Salis, the reaper queue is implemented as a circular queue. Thus, at - any given time, a process ID (which actually denotes a process 'address' - or, more correctly, a process 'container address') might contain a living - process or be empty. This function checks for the 'living' state of a given - process ID. + /* + * In Salis, the reaper queue is implemented as a circular queue. Thus, at + * any given time, a process ID (which actually denotes a process 'address' + * or, more correctly, a process 'container address') might contain a living + * process or be empty. This function checks for the 'living' state of a + * given process ID. */ assert(g_is_init); assert(proc_id < g_capacity); if (!g_procs[proc_id].mb1s) { - /* When running in debug mode, we make sure that non-living processes - are completely set to zero, as this is the expected state. + /* + * When running in debug mode, we make sure that non-living processes + * are completely set to zero, as this is the expected state. */ #ifndef NDEBUG Process dummy_proc; @@ -113,8 +120,9 @@ boolean sal_proc_is_free(uint32 proc_id) Process sal_proc_get_proc(uint32 proc_id) { - /* Get a **copy** (not a reference) of the process with the given ID. Note, - this might be a non-living process. + /* + * Get a **copy** (not a reference) of the process with the given ID. Note, + * this might be a non-living process. */ assert(g_is_init); assert(proc_id < g_capacity); @@ -123,11 +131,12 @@ Process sal_proc_get_proc(uint32 proc_id) void sal_proc_get_proc_data(uint32 proc_id, uint32_p buffer) { - /* Get a **copy** (not a reference) of the process with the given ID - (represented as a string of 32 bit integers) written into the given buffer. - The buffer must be pre-allocated to a large enough size - (i.e. malloc(sizeof(Process))). Note, copied process might be in a - non-living state. + /* + * Get a **copy** (not a reference) of the process with the given ID + * (represented as a string of 32 bit integers) written into the given + * buffer. The buffer must be pre-allocated to a large enough size (i.e. + * malloc(sizeof(Process))). Note, copied process might be in a non-living + * state. */ assert(g_is_init); assert(proc_id < g_capacity); @@ -137,8 +146,9 @@ void sal_proc_get_proc_data(uint32 proc_id, uint32_p buffer) static boolean block_is_free_and_valid(uint32 address, uint32 size) { - /* Iterate all addresses in the given memory block and check that they lie - within memory bounds and have the ALLOCATED flag unset. + /* + * Iterate all addresses in the given memory block and check that they lie + * within memory bounds and have the ALLOCATED flag unset. */ uint32 offset; @@ -153,13 +163,14 @@ static boolean block_is_free_and_valid(uint32 address, uint32 size) static void realloc_queue(uint32 queue_lock) { - /* Reallocate reaper queue into a new circular queue with double the - capacity. This function gets called whenever the reaper queue fills up - with new organisms. - - A queue_lock parameter may be provided, which 'centers' the reallocation on - a given process ID. This means that, after reallocating the queue, the - process with that ID will keep still have the same ID on the new queue. + /* + * Reallocate reaper queue into a new circular queue with double the + * capacity. This function gets called whenever the reaper queue fills up + * with new organisms. + * + * A queue_lock parameter may be provided, which 'centers' the reallocation + * on a given process ID. This means that, after reallocating the queue, the + * process with that ID will keep still have the same ID on the new queue. */ uint32 new_capacity; Process *new_queue; @@ -174,7 +185,8 @@ static void realloc_queue(uint32 queue_lock) fwrd_idx = queue_lock; back_idx = (queue_lock - 1) % new_capacity; - /* Copy all organisms that lie forward from queue lock. + /* + * Copy all organisms that lie forward from queue lock. */ while (TRUE) { uint32 old_idx = fwrd_idx % g_capacity; @@ -188,9 +200,10 @@ static void realloc_queue(uint32 queue_lock) } } - /* Copy all organisms that lie backwards from queue lock, making sure to - loop around the queue (with modulo '%') whenever the process index goes - below zero. + /* + * Copy all organisms that lie backwards from queue lock, making sure to + * loop around the queue (with modulo '%') whenever the process index goes + * below zero. */ if (queue_lock != g_first) { while (TRUE) { @@ -207,7 +220,8 @@ static void realloc_queue(uint32 queue_lock) } } - /* Free old reaper queue and re-link global pointer to new queue. + /* + * Free old reaper queue and re-link global pointer to new queue. */ free(g_procs); g_capacity = new_capacity; @@ -216,12 +230,14 @@ static void realloc_queue(uint32 queue_lock) static uint32 get_new_proc_from_queue(uint32 queue_lock) { - /* Retrieve an unoccupied process ID from the reaper queue. This function - gets called whenever a new organism is generated (born). + /* + * Retrieve an unoccupied process ID from the reaper queue. This function + * gets called whenever a new organism is generated (born). */ assert(g_is_init); - /* If reaper queue is full, reallocate to double its current size. + /* + * If reaper queue is full, reallocate to double its current size. */ if (g_count == g_capacity) { realloc_queue(queue_lock); @@ -243,18 +259,20 @@ static uint32 get_new_proc_from_queue(uint32 queue_lock) static void proc_create(uint32 address, uint32 size, uint32 queue_lock, boolean allocate) { - /* Give birth to a new process! We must specify the address and size of the - new organism. + /* + * Give birth to a new process! We must specify the address and size of the + * new organism. */ uint32 pidx; assert(g_is_init); assert(sal_mem_is_address_valid(address)); assert(sal_mem_is_address_valid(address + size - 1)); - /* When organisms are generated manually (by an user), we must explicitly - allocate its entire memory block. When organisms replicate by themselves, - we assume they have already allocated the child's memory, so we don't need - to do it here. + /* + * When organisms are generated manually (by an user), we must explicitly + * allocate its entire memory block. When organisms replicate by themselves, + * we assume they have already allocated the child's memory, so we don't + * need to do it here. */ if (allocate) { uint32 offset; @@ -266,8 +284,9 @@ static void proc_create(uint32 address, uint32 size, uint32 queue_lock, } } - /* Get a new process ID for the child process. Also, set initial state of - the child process data structure. + /* + * Get a new process ID for the child process. Also, set initial state of + * the child process data structure. */ pidx = get_new_proc_from_queue(queue_lock); g_procs[pidx].mb1a = address; @@ -278,8 +297,9 @@ static void proc_create(uint32 address, uint32 size, uint32 queue_lock, void sal_proc_create(uint32 address, uint32 mb1s) { - /* API function to create a new process. Memory address and size of new - process must be provided. + /* + * API function to create a new process. Memory address and size of new + * process must be provided. */ assert(g_is_init); assert(block_is_free_and_valid(address, mb1s)); @@ -288,7 +308,8 @@ void sal_proc_create(uint32 address, uint32 mb1s) static void free_memory_block(uint32 address, uint32 size) { - /* Deallocate a memory block. + /* + * Deallocate a memory block. */ uint32 offset; assert(sal_mem_is_address_valid(address)); @@ -306,7 +327,8 @@ static void free_memory_block(uint32 address, uint32 size) static void free_memory_owned_by(uint32 pidx) { - /* Free memory specifically owned by the process with the given ID. + /* + * Free memory specifically owned by the process with the given ID. */ assert(g_is_init); assert(pidx < g_capacity); @@ -314,7 +336,8 @@ static void free_memory_owned_by(uint32 pidx) free_memory_block(g_procs[pidx].mb1a, g_procs[pidx].mb1s); if (g_procs[pidx].mb2s) { - /* If process owns a child memory block, free it as well. + /* + * If process owns a child memory block, free it as well. */ free_memory_block(g_procs[pidx].mb2a, g_procs[pidx].mb2s); } @@ -322,7 +345,8 @@ static void free_memory_owned_by(uint32 pidx) static void proc_kill(void) { - /* Kill process on bottom of reaper queue (the oldest process). + /* + * Kill process on bottom of reaper queue (the oldest process). */ assert(g_is_init); assert(g_count); @@ -330,7 +354,8 @@ static void proc_kill(void) assert(g_last != UINT32_MAX); assert(!sal_proc_is_free(g_first)); - /* Free up owned memory and reset process data structure back to zero. + /* + * Free up owned memory and reset process data structure back to zero. */ free_memory_owned_by(g_first); memset(&g_procs[g_first], 0, sizeof(Process)); @@ -347,8 +372,9 @@ static void proc_kill(void) void sal_proc_kill(void) { - /* API function to kill a process. Make sure that at least one process is - alive, or 'assert()' will fail. + /* + * API function to kill a process. Make sure that at least one process is + * alive, or 'assert()' will fail. */ assert(g_is_init); assert(g_count); @@ -360,7 +386,8 @@ void sal_proc_kill(void) static boolean block_is_allocated(uint32 address, uint32 size) { - /* Assert that a given memory block is fully allocated. + /* + * Assert that a given memory block is fully allocated. */ uint32 offset; assert(g_is_init); @@ -376,9 +403,11 @@ static boolean block_is_allocated(uint32 address, uint32 size) static boolean proc_is_valid(uint32 pidx) { - /* Assert that the process with the given ID is in a valid state. This - means that all of its owned memory must be allocated and that the allocated - flags are set in place. IP and SP must be located in valid addresses. + /* + * Assert that the process with the given ID is in a valid state. This + * means that all of its owned memory must be allocated and that the + * allocated flags are set in place. IP and SP must be located in valid + * addresses. */ assert(g_is_init); assert(pidx < g_capacity); @@ -398,26 +427,29 @@ static boolean proc_is_valid(uint32 pidx) static boolean module_is_valid(void) { - /* Check for validity of process module. This function only gets called - when Salis is running in debug mode. It makes Salis **very** slow in - comparison to when running optimized, but it is also **very** useful for - debugging! + /* + * Check for validity of process module. This function only gets called when + * Salis is running in debug mode. It makes Salis **very** slow in + * comparison to when running optimized, but it is also **very** useful for + * debugging! */ uint32 pidx; uint32 alloc_count = 0; assert(g_is_init); - /* Check that each individual process is in a valid state. We can do this - in a multi-threaded way. + /* + * Check that each individual process is in a valid state. We can do this + * in a multi-threaded way. */ #pragma omp parallel for for (pidx = 0; pidx < g_capacity; pidx++) { assert(proc_is_valid(pidx)); } - /* Iterate all processes, counting their memory blocks and adding up their - memory block sizes. At the end, we compare the sums to the flag counters of - the memory module. + /* + * Iterate all processes, counting their memory blocks and adding up their + * memory block sizes. At the end, we compare the sums to the flag counters of + * the memory module. */ for (pidx = 0; pidx < g_capacity; pidx++) { if (!sal_proc_is_free(pidx)) { @@ -436,7 +468,8 @@ static boolean module_is_valid(void) static void on_fault(uint32 pidx) { - /* For now, faults do nothing. + /* + * For now, faults do nothing. */ assert(g_is_init); assert(pidx < g_capacity); @@ -446,8 +479,9 @@ static void on_fault(uint32 pidx) static void increment_ip(uint32 pidx) { - /* After executing each instruction, increment the given organism's IP to - the next valid address. + /* + * After executing each instruction, increment the given organism's IP to + * the next valid address. */ assert(g_is_init); assert(pidx < g_capacity); @@ -457,42 +491,49 @@ static void increment_ip(uint32 pidx) g_procs[pidx].ip++; } - /* Wherever IP goes, SP follows. :P + /* + * Wherever IP goes, SP follows. :P */ g_procs[pidx].sp = g_procs[pidx].ip; } static boolean are_templates_complements(uint32 source, uint32 complement) { - /* Check whether 2 templates are complements. Templates are introduced in - Salis-2.0 and they function in the same way as templates in the original - Tierra. They consist of string of NOP0 and NOP1 instructions. - - We say that templates are complements whenever one is a 'negation' of - another (i.e. they are reverse copies of each other). So, on the following - example, the top template would be the complement of the bottom template. - - >>> NOP0 - NOP1 - NOP1 - >>> NOP1 - NOP0 - NOP0 - - This function looks into 2 given addresses in memory and checks whether - there are complementing templates on those addresses. + /* + * Check whether 2 templates are complements. Templates are introduced in + * Salis-2.0 and they function in the same way as templates in the original + * Tierra. They consist of string of NOP0 and NOP1 instructions. + * + * We say that templates are complements whenever one is a 'negation' of + * another (i.e. they are reverse copies of each other). So, on the + * following example, the top template would be the complement of the bottom + * template. + * + * >>> NOP0 - NOP1 - NOP1 + * >>> NOP1 - NOP0 - NOP0 + * + * This function looks into 2 given addresses in memory and checks whether + * there are complementing templates on those addresses. */ assert(g_is_init); assert(sal_mem_is_address_valid(source)); assert(sal_mem_is_address_valid(complement)); assert(sal_is_template(sal_mem_get_inst(source))); - while (sal_mem_is_address_valid(source) && - sal_is_template(sal_mem_get_inst(source))) { - /* Iterate address by address, checking complementarity on each - consecutive byte pair. + while ( + sal_mem_is_address_valid(source) && + sal_is_template(sal_mem_get_inst(source)) + ) { + /* + * Iterate address by address, checking complementarity on each + * consecutive byte pair. */ uint8 inst_src; uint8 inst_comp; - /* If complement head moves to an invalid address, complementarity - fails. + /* + * If complement head moves to an invalid address, complementarity + * fails. */ if (!sal_mem_is_address_valid(complement)) { return FALSE; @@ -514,18 +555,20 @@ static boolean are_templates_complements(uint32 source, uint32 complement) complement++; } - /* If we get to the end of a template in the source head, and target has - been complementary all the way through, we consider these blocks of memory - 'complements'. + /* + * If we get to the end of a template in the source head, and target has + * been complementary all the way through, we consider these blocks of + * memory 'complements'. */ return TRUE; } static void increment_sp(uint32 pidx, boolean forward) { - /* Increment or decrement SP to the next valid address. This function gets - called by organisms during jumps, searches, etc. (i.e. whenever the seeker - pointer gets sent on a 'mission'). + /* + * Increment or decrement SP to the next valid address. This function gets + * called by organisms during jumps, searches, etc. (i.e. whenever the + * seeker pointer gets sent on a 'mission'). */ assert(g_is_init); assert(pidx < g_capacity); @@ -542,11 +585,12 @@ static void increment_sp(uint32 pidx, boolean forward) static boolean jump_seek(uint32 pidx, boolean forward) { - /* Search (via the seeker pointer) for template to jump into. This gets - called by organisms each cycle during a JMP instruction. Only when a valid - template is found, will this function return TRUE. Otherwise it will return - FALSE, signaling the calling process that a template has not yet been - found. + /* + * Search (via the seeker pointer) for template to jump into. This gets + * called by organisms each cycle during a JMP instruction. Only when a + * valid template is found, will this function return TRUE. Otherwise it + * will return FALSE, signaling the calling process that a template has not + * yet been found. */ uint32 next_addr; uint8 next_inst; @@ -555,8 +599,9 @@ static boolean jump_seek(uint32 pidx, boolean forward) assert(!sal_proc_is_free(pidx)); next_addr = g_procs[pidx].ip + 1; - /* This function causes a 'fault' when there is no template right in front - of the caller organism's instruction pointer. + /* + * This function causes a 'fault' when there is no template right in front + * of the caller organism's instruction pointer. */ if (!sal_mem_is_address_valid(next_addr)) { on_fault(pidx); @@ -572,8 +617,9 @@ static boolean jump_seek(uint32 pidx, boolean forward) return FALSE; } - /* Check for complementarity. Increment seeker pointer if template has not - been found yet. + /* + * Check for complementarity. Increment seeker pointer if template has not + * been found yet. */ if (are_templates_complements(next_addr, g_procs[pidx].sp)) { return TRUE; @@ -585,9 +631,10 @@ static boolean jump_seek(uint32 pidx, boolean forward) static void jump(uint32 pidx) { - /* This gets called when an organism has finally found a template to jump - into (see function above). Only when in debug mode, we make sure that the - entire jump operation has been performed in a valid way. + /* + * This gets called when an organism has finally found a template to jump + * into (see function above). Only when in debug mode, we make sure that the + * entire jump operation has been performed in a valid way. */ #ifndef NDEBUG uint32 next_addr; @@ -610,11 +657,13 @@ static void jump(uint32 pidx) static boolean addr_seek(uint32 pidx, boolean forward) { - /* Search (via the seeker pointer) for template address in memory. This - gets called by organisms each cycle during a ADR instruction. Only when a - valid template is found, will this function return TRUE. Otherwise it will - return FALSE, signaling the calling process that a template has not yet - been found. */ + /* + * Search (via the seeker pointer) for template address in memory. This + * gets called by organisms each cycle during a ADR instruction. Only when a + * valid template is found, will this function return TRUE. Otherwise it + * will return FALSE, signaling the calling process that a template has not + * yet been found. + */ uint32 next1_addr; uint32 next2_addr; uint8 next1_inst; @@ -625,12 +674,15 @@ static boolean addr_seek(uint32 pidx, boolean forward) next1_addr = g_procs[pidx].ip + 1; next2_addr = g_procs[pidx].ip + 2; - /* This function causes a 'fault' when there is no register modifier right - in front of the caller organism's instruction pointer, and a template just - after that. + /* + * This function causes a 'fault' when there is no register modifier right + * in front of the caller organism's instruction pointer, and a template + * just after that. */ - if (!sal_mem_is_address_valid(next1_addr) || - !sal_mem_is_address_valid(next2_addr)) { + if ( + !sal_mem_is_address_valid(next1_addr) || + !sal_mem_is_address_valid(next2_addr) + ) { on_fault(pidx); increment_ip(pidx); return FALSE; @@ -645,8 +697,9 @@ static boolean addr_seek(uint32 pidx, boolean forward) return FALSE; } - /* Check for complementarity. Increment seeker pointer if template has not - been found yet. + /* + * Check for complementarity. Increment seeker pointer if template has not + * been found yet. */ if (are_templates_complements(next2_addr, g_procs[pidx].sp)) { return TRUE; @@ -656,12 +709,13 @@ static boolean addr_seek(uint32 pidx, boolean forward) return FALSE; } -static boolean get_register_pointers(uint32 pidx, uint32_p *regs, - uint32 reg_count) -{ - /* This function is used to get pointers to a calling organism registers. - Specifically, registers returned are those that will be used when executing - the caller organism's current instruction. +static boolean get_register_pointers( + uint32 pidx, uint32_p *regs, uint32 reg_count +) { + /* + * This function is used to get pointers to a calling organism registers. + * Specifically, registers returned are those that will be used when + * executing the caller organism's current instruction. */ uint32 ridx; assert(g_is_init); @@ -671,15 +725,18 @@ static boolean get_register_pointers(uint32 pidx, uint32_p *regs, assert(reg_count); assert(reg_count < 4); - /* Iterate 'reg_count' number of instructions forward from the IP, noting - down all found register modifiers. If less than 'reg_count' modifiers are - found, this function returns FALSE (triggering a 'fault'). + /* + * Iterate 'reg_count' number of instructions forward from the IP, noting + * down all found register modifiers. If less than 'reg_count' modifiers are + * found, this function returns FALSE (triggering a 'fault'). */ for (ridx = 0; ridx < reg_count; ridx++) { uint32 mod_addr = g_procs[pidx].ip + 1 + ridx; - if (!sal_mem_is_address_valid(mod_addr) || - !sal_is_mod(sal_mem_get_inst(mod_addr))) { + if ( + !sal_mem_is_address_valid(mod_addr) || + !sal_is_mod(sal_mem_get_inst(mod_addr)) + ) { return FALSE; } @@ -704,9 +761,10 @@ static boolean get_register_pointers(uint32 pidx, uint32_p *regs, static void addr(uint32 pidx) { - /* This gets called when an organism has finally found a template and is - ready to store its address. Only when in debug mode, we make sure that the - entire search operation has been performed in a valid way. + /* + * This gets called when an organism has finally found a template and is + * ready to store its address. Only when in debug mode, we make sure that + * the entire search operation has been performed in a valid way. */ uint32_p reg; @@ -726,7 +784,8 @@ static void addr(uint32 pidx) assert(are_templates_complements(next2_addr, g_procs[pidx].sp)); #endif - /* Store address of complement into the given register. + /* + * Store address of complement into the given register. */ if (!get_register_pointers(pidx, ®, 1)) { on_fault(pidx); @@ -740,7 +799,8 @@ static void addr(uint32 pidx) static void free_child_block_of(uint32 pidx) { - /* Free only the 'child' memory block (mb2) of the caller organism. + /* + * Free only the 'child' memory block (mb2) of the caller organism. */ assert(g_is_init); assert(pidx < g_capacity); @@ -753,11 +813,12 @@ static void free_child_block_of(uint32 pidx) static void alloc(uint32 pidx, boolean forward) { - /* Allocate a 'child' memory block of size stored in the first given - register, and save its address into the second given register. This - function is the basis of Salisian reproduction. It's a fairly complicated - function (as the seeker pointer must function in a procedural way), so it's - divided into a series of steps, documented below. + /* + * Allocate a 'child' memory block of size stored in the first given + * register, and save its address into the second given register. This + * function is the basis of Salisian reproduction. It's a fairly complicated + * function (as the seeker pointer must function in a procedural way), so + * it's divided into a series of steps, documented below. */ uint32_p regs[2]; uint32 block_size; @@ -765,9 +826,10 @@ static void alloc(uint32 pidx, boolean forward) assert(pidx < g_capacity); assert(!sal_proc_is_free(pidx)); - /* For this function to work, we need at least two register modifiers. - Then, we check for all possible error conditions. If any error conditions - are found, the instruction faults and returns. + /* + * For this function to work, we need at least two register modifiers. + * Then, we check for all possible error conditions. If any error conditions + * are found, the instruction faults and returns. */ if (!get_register_pointers(pidx, regs, 2)) { on_fault(pidx); @@ -777,7 +839,8 @@ static void alloc(uint32 pidx, boolean forward) block_size = *regs[0]; - /* ERROR 1: requested child block is of size zero. + /* + * ERROR 1: requested child block is of size zero. */ if (!block_size) { on_fault(pidx); @@ -785,7 +848,8 @@ static void alloc(uint32 pidx, boolean forward) return; } - /* ERROR 2: seeker pointer not adjacent to existing child block. + /* + * ERROR 2: seeker pointer not adjacent to existing child block. */ if (g_procs[pidx].mb2s) { uint32 exp_addr; @@ -803,7 +867,8 @@ static void alloc(uint32 pidx, boolean forward) } } - /* No errors were detected. We thus handle all correct conditions. + /* + * No errors were detected. We thus handle all correct conditions. * CONDITION 1: allocation was successful. */ if (g_procs[pidx].mb2s == block_size) { @@ -812,8 +877,9 @@ static void alloc(uint32 pidx, boolean forward) return; } - /* CONDITION 2: seeker pointer has collided with allocated space. We free - child memory block and just continue searching. + /* + * CONDITION 2: seeker pointer has collided with allocated space. We free + * child memory block and just continue searching. */ if (sal_mem_is_allocated(g_procs[pidx].sp)) { if (g_procs[pidx].mb2s) { @@ -824,8 +890,9 @@ static void alloc(uint32 pidx, boolean forward) return; } - /* CONDITION 3: no collision detected; enlarge child memory block and - increment seeker pointer. + /* + * CONDITION 3: no collision detected; enlarge child memory block and + * increment seeker pointer. */ _sal_mem_set_allocated(g_procs[pidx].sp); @@ -839,8 +906,9 @@ static void alloc(uint32 pidx, boolean forward) static void swap(uint32 pidx) { - /* Swap parent and child memory blocks. This function is the basis of - Salisian metabolism. + /* + * Swap parent and child memory blocks. This function is the basis of + * Salisian metabolism. */ assert(g_is_init); assert(pidx < g_capacity); @@ -862,7 +930,8 @@ static void swap(uint32 pidx) static void split(uint32 pidx) { - /* Split child memory block into a new organism. A new baby is born. :-) + /* + * Split child memory block into a new organism. A new baby is born. :-) */ assert(g_is_init); assert(pidx < g_capacity); @@ -881,9 +950,10 @@ static void split(uint32 pidx) static void one_reg_op(uint32 pidx, uint8 inst) { - /* Here we group all 1-register operations. These include incrementing, - decrementing, placing zero or one on a register, and the negation - operation. + /* + * Here we group all 1-register operations. These include incrementing, + * decrementing, placing zero or one on a register, and the negation + * operation. */ uint32_p reg; assert(g_is_init); @@ -928,9 +998,10 @@ static void one_reg_op(uint32 pidx, uint8 inst) static void if_not_zero(uint32 pidx) { - /* Conditional operator. Like in most programming languages, this - instruction is needed to allow organism execution to branch into different - execution streams. + /* + * Conditional operator. Like in most programming languages, this + * instruction is needed to allow organism execution to branch into + * different execution streams. */ uint32_p reg; assert(g_is_init); @@ -953,8 +1024,9 @@ static void if_not_zero(uint32 pidx) static void three_reg_op(uint32 pidx, uint8 inst) { - /* Here we group all 3-register arithmetic operations. These include - addition, subtraction, multiplication and division. + /* + * Here we group all 3-register arithmetic operations. These include + * addition, subtraction, multiplication and division. */ uint32_p regs[3]; assert(g_is_init); @@ -979,7 +1051,9 @@ static void three_reg_op(uint32 pidx, uint8 inst) *regs[0] = *regs[1] * *regs[2]; break; case DIVN: - /* Division by 0 is not allowed and causes a fault. */ + /* + * Division by 0 is not allowed and causes a fault. + */ if (!(*regs[2])) { on_fault(pidx); increment_ip(pidx); @@ -997,16 +1071,19 @@ static void three_reg_op(uint32 pidx, uint8 inst) static void load(uint32 pidx) { - /* Load an instruction from a given address into a specified register. This - is used by organisms during their reproduction cycle. + /* + * Load an instruction from a given address into a specified register. This + * is used by organisms during their reproduction cycle. */ uint32_p regs[2]; assert(g_is_init); assert(pidx < g_capacity); assert(!sal_proc_is_free(pidx)); - if (!get_register_pointers(pidx, regs, 2) || - !sal_mem_is_address_valid(*regs[0])) { + if ( + !get_register_pointers(pidx, regs, 2) || + !sal_mem_is_address_valid(*regs[0]) + ) { on_fault(pidx); increment_ip(pidx); return; @@ -1024,9 +1101,10 @@ static void load(uint32 pidx) static boolean is_writeable_by(uint32 pidx, uint32 address) { - /* Check whether an organisms has writing rights on a specified address. - Any organism may write to any valid address that is either self owned or - not allocated. + /* + * Check whether an organisms has writing rights on a specified address. + * Any organism may write to any valid address that is either self owned or + * not allocated. */ assert(g_is_init); assert(pidx < g_capacity); @@ -1040,23 +1118,28 @@ static boolean is_writeable_by(uint32 pidx, uint32 address) uint32 lo2 = g_procs[pidx].mb2a; uint32 hi1 = lo1 + g_procs[pidx].mb1s; uint32 hi2 = lo2 + g_procs[pidx].mb2s; - return ((address >= lo1 && address < hi1) || - (address >= lo2 && address < hi2)); + return ( + (address >= lo1 && address < hi1) || + (address >= lo2 && address < hi2) + ); } } static void write(uint32 pidx) { - /* Write instruction on a given register into a specified address. This is - used by organisms during their reproduction cycle. + /* + * Write instruction on a given register into a specified address. This is + * used by organisms during their reproduction cycle. */ uint32_p regs[2]; assert(g_is_init); assert(pidx < g_capacity); assert(!sal_proc_is_free(pidx)); - if (!get_register_pointers(pidx, regs, 2) || - !sal_mem_is_address_valid(*regs[0]) || !sal_is_inst(*regs[1])) { + if ( + !get_register_pointers(pidx, regs, 2) || + !sal_mem_is_address_valid(*regs[0]) || !sal_is_inst(*regs[1]) + ) { on_fault(pidx); increment_ip(pidx); return; @@ -1077,7 +1160,8 @@ static void write(uint32 pidx) static void send(uint32 pidx) { - /* Send instruction on given register into the common sender. + /* + * Send instruction on given register into the common sender. */ uint32_p reg; assert(g_is_init); @@ -1102,9 +1186,10 @@ static void send(uint32 pidx) static void receive(uint32 pidx) { - /* Receive a single instruction from the common receiver and store it into - a specified register. In case the receiver is unset, it will return the - NOP0 instruction. + /* + * Receive a single instruction from the common receiver and store it into + * a specified register. In case the receiver is unset, it will return the + * NOP0 instruction. */ uint32_p reg; assert(g_is_init); @@ -1124,8 +1209,9 @@ static void receive(uint32 pidx) static void push(uint32 pidx) { - /* Push value on register into the stack. This is useful as a secondary - memory resource. + /* + * Push value on register into the stack. This is useful as a secondary + * memory resource. */ uint32_p reg; uint32 sidx; @@ -1149,7 +1235,8 @@ static void push(uint32 pidx) static void pop(uint32 pidx) { - /* Pop value from the stack into a given register. + /* + * Pop value from the stack into a given register. */ uint32_p reg; uint32 sidx; @@ -1175,8 +1262,9 @@ static void pop(uint32 pidx) static void proc_cycle(uint32 pidx) { - /* Cycle a process once. Organisms will always execute one instruction per - simulation cycle. + /* + * Cycle a process once. Organisms will always execute one instruction per + * simulation cycle. */ uint8 inst; assert(g_is_init); @@ -1252,16 +1340,18 @@ static void proc_cycle(uint32 pidx) void _sal_proc_cycle(void) { - /* The process module cycle consists of a series of steps, which are needed - to preserve overall correctness. + /* + * The process module cycle consists of a series of steps, which are needed + * to preserve overall correctness. */ assert(g_is_init); assert(module_is_valid()); - /* Iterate through all organisms in the reaper queue. First organism to - execute is the one pointed to by 'g_last' (the one on top of the queue). - Last one to execute is 'g_first'. We go around the circular queue, making - sure to modulo (%) around when iterator goes below zero. + /* + * Iterate through all organisms in the reaper queue. First organism to + * execute is the one pointed to by 'g_last' (the one on top of the queue). + * Last one to execute is 'g_first'. We go around the circular queue, making + * sure to modulo (%) around when iterator goes below zero. */ if (g_count) { uint32 pidx = g_last; @@ -1273,7 +1363,8 @@ void _sal_proc_cycle(void) proc_cycle(pidx); } - /* Kill oldest processes whenever memory gets filled over capacity. + /* + * Kill oldest processes whenever memory gets filled over capacity. */ while (sal_mem_get_allocated() > sal_mem_get_capacity()) { proc_kill(); diff --git a/src/render.c b/src/render.c index a4ed262..66db0c4 100644 --- a/src/render.c +++ b/src/render.c @@ -9,28 +9,31 @@ #define BLOCK_FLAG 0x40 #define IP_FLAG 0x80 -static void apply_flag(uint32 origin, uint32 max_pos, uint32 cell_size, - uint32 address, uint32 flag, uint8_p buffer) -{ +static void apply_flag( + uint32 origin, uint32 max_pos, uint32 cell_size, uint32 address, + uint32 flag, uint8_p buffer +) { if (address >= origin && address < max_pos) { - /* Flag falls inside rendered image. We can 'and' the bit to the - corresponding pixel. + /* + * Flag falls inside rendered image. We can 'and' the bit to the + * corresponding pixel. */ uint32 pixel = (address - origin) / cell_size; buffer[pixel] |= flag; } } -void sal_ren_get_image(uint32 origin, uint32 cell_size, uint32 buff_size, - uint8_p buffer) -{ - /* Render a 1D image of a given section of memory, at a given resolution - (zoom) and store it in a pre-allocated 'buffer'. - - On the Salis python handler we draw memory as a 1D 'image' on the WORLD - page. If we were to render this image directly on python, it would be - excruciatingly slow, as we have to iterate over large areas of memory! - Therefore, this memory module comes with a built-in, super fast renderer. +void sal_ren_get_image( + uint32 origin, uint32 cell_size, uint32 buff_size, uint8_p buffer +) { + /* + * Render a 1D image of a given section of memory, at a given resolution + * (zoom) and store it in a pre-allocated 'buffer'. + * + * On the Salis python handler we draw memory as a 1D 'image' on the WORLD + * page. If we were to render this image directly on python, it would be + * excruciatingly slow, as we have to iterate over large areas of memory! + * Therefore, this memory module comes with a built-in, super fast renderer. */ uint32 i; uint32 max_pos; @@ -40,8 +43,9 @@ void sal_ren_get_image(uint32 origin, uint32 cell_size, uint32 buff_size, assert(buff_size); assert(buffer); - /* We make use of openmp for multi-threaded looping. This allows even - faster render times, wherever openmp is supported. + /* + * We make use of openmp for multi-threaded looping. This allows even faster + * render times, wherever openmp is supported. */ #pragma omp parallel for for (i = 0; i < buff_size; i++) { @@ -68,8 +72,9 @@ void sal_ren_get_image(uint32 origin, uint32 cell_size, uint32 buff_size, buffer[i] |= (uint8)(alloc_flag); } - /* We also iterate through all processes and append extra bit flags to the - rendered image signaling process IP position and memory block limits. + /* + * We also iterate through all processes and append extra bit flags to the + * rendered image signaling process IP position and memory block limits. */ max_pos = origin + (cell_size * buff_size); @@ -78,12 +83,14 @@ void sal_ren_get_image(uint32 origin, uint32 cell_size, uint32 buff_size, if (!sal_proc_is_free(i)) { Process proc = sal_proc_get_proc(i); apply_flag(origin, max_pos, cell_size, proc.ip, IP_FLAG, buffer); - apply_flag(origin, max_pos, cell_size, proc.mb1a, BLOCK_FLAG, - buffer); + apply_flag( + origin, max_pos, cell_size, proc.mb1a, BLOCK_FLAG, buffer + ); if (proc.mb2s) { - apply_flag(origin, max_pos, cell_size, proc.mb2a, BLOCK_FLAG, - buffer); + apply_flag( + origin, max_pos, cell_size, proc.mb2a, BLOCK_FLAG, buffer + ); } } } diff --git a/src/salis.c b/src/salis.c index 32a14b8..102ca49 100644 --- a/src/salis.c +++ b/src/salis.c @@ -9,8 +9,9 @@ static uint32 g_epoch; void sal_main_init(uint32 order) { - /* Initialize all Salis modules to their initial states. We pass along any - arguments to their respective modules. + /* + * Initialize all Salis modules to their initial states. We pass along any + * arguments to their respective modules. */ assert(!g_is_init); _sal_mem_init(order); @@ -21,10 +22,11 @@ void sal_main_init(uint32 order) void sal_main_quit(void) { - /* Reset Salis and all of its modules back to zero. We may, thus, shutdown - Salis and re-initialize it with different parameters without having to - reload the library (useful, for example, when running data gathering - scripts that must iterate through many save files). + /* + * Reset Salis and all of its modules back to zero. We may, thus, shutdown + * Salis and re-initialize it with different parameters without having to + * reload the library (useful, for example, when running data gathering + * scripts that must iterate through many save files). */ assert(g_is_init); _sal_proc_quit(); @@ -37,8 +39,9 @@ void sal_main_quit(void) void sal_main_load(string file_name) { - /* Load simulation state from file. This file must have been created by - 'sal_main_save()'. + /* + * Load simulation state from file. This file must have been created by + * 'sal_main_save()'. */ FILE *file; assert(!g_is_init); @@ -56,9 +59,10 @@ void sal_main_load(string file_name) void sal_main_save(string file_name) { - /* Save simulation state to a file. This file may later be re-loaded with - 'sal_main_load()'. We save in binary format (to save space), which means - save files might not be entirely portable. + /* + * Save simulation state to a file. This file may later be re-loaded with + * 'sal_main_load()'. We save in binary format (to save space), which means + * save files might not be entirely portable. */ FILE *file; assert(g_is_init); @@ -76,21 +80,24 @@ void sal_main_save(string file_name) boolean sal_main_is_init(void) { - /* Check if Salis is currently initialized/running. + /* + * Check if Salis is currently initialized/running. */ return g_is_init; } -/* Getter methods for the Salis main module. +/* +* Getter methods for the Salis main module. */ UINT32_GETTER(main, cycle) UINT32_GETTER(main, epoch) void sal_main_cycle(void) { - /* Cycle the Salis simulator once. The combination of a cycle * epoch - counter allows us to track simulations for an insane period of time - (2^64 cycles). + /* + * Cycle the Salis simulator once. The combination of a cycle * epoch + * counter allows us to track simulations for an insane period of time + * (2^64 cycles). */ g_cycle++; @@ -98,7 +105,8 @@ void sal_main_cycle(void) g_epoch++; } - /* Cycle all of the Salis modules. + /* + * Cycle all of the Salis modules. */ _sal_mem_cycle(); _sal_evo_cycle(); |