From 6b1444aa3918382aba127c16c671f045a3586e53 Mon Sep 17 00:00:00 2001 From: Paul Oliver Date: Thu, 29 Feb 2024 02:29:14 +0100 Subject: Common pipe replaced with sender/receiver functors. [#27] C library now only takes care of relaying data to/from functors, which must be provided by the wrapping application (in this case, a new python module named 'common.py'). --- include/common.h | 27 ++++++++++++++++++----- include/instset.h | 4 ++-- include/salis.h | 6 ++--- src/common.c | 66 +++++++++++++++++++------------------------------------ src/process.c | 6 ++--- src/salis.c | 9 +++----- 6 files changed, 55 insertions(+), 63 deletions(-) diff --git a/include/common.h b/include/common.h index 7386a34..50ac563 100644 --- a/include/common.h +++ b/include/common.h @@ -2,17 +2,34 @@ * @file common.h * @author Paul Oliver * -* This module controls the 'common pipe', which is the FIFO file through which +* This module controls the common sender and receiver functors, through which * communication between different simulations can occur. By calling SEND, -* processes may output local instructions through the pipe. These instructions -* may then be read by processes running on a different simulation instance. +* processes may output local instructions through a network. These instructions +* may then be read by processes running on a different simulation somewhere +* else. */ #ifndef SALIS_COMMON_H #define SALIS_COMMON_H -void _sal_comm_init(string pipe); -void _sal_comm_quit(void); +/* Typedef sender functor type for easy python parsing. +*/ +typedef void (*Sender)(uint8 inst); + +/* Typedef receiver functor type for easy python parsing. +*/ +typedef uint8 (*Receiver)(void); + +/* 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. +* @param receiver Receiver functor +*/ +SALIS_API void sal_comm_set_receiver(Receiver receiver); + void _sal_comm_send(uint8 inst); uint8 _sal_comm_receive(void); diff --git a/include/instset.h b/include/instset.h index eeb4600..a7f4773 100644 --- a/include/instset.h +++ b/include/instset.h @@ -44,8 +44,8 @@ enum { SALIS_INST DIVN, /**< / Divide two registers */ SALIS_INST LOAD, /**< L Load instruction from memory */ SALIS_INST WRTE, /**< W Write instruction into memory */ - SALIS_INST SEND, /**< S Send instruction to common pipe */ - SALIS_INST RECV, /**< R Receive instruction from common pipe */ + SALIS_INST SEND, /**< S Send instruction to common sender */ + SALIS_INST RECV, /**< R Receive instruction from common receiver */ SALIS_INST PSHN, /**< # Push value to stack */ SALIS_INST POPN /**< ~ Pop value from stack */ }; diff --git a/include/salis.h b/include/salis.h index 8b261b1..75ef9dd 100644 --- a/include/salis.h +++ b/include/salis.h @@ -22,9 +22,8 @@ /** Initialize Salis simulation. * @param order Order of memory (memory_size == 1 << order) -* @param pipe Desired path and file name of common pipe */ -SALIS_API void sal_main_init(uint32 order, string pipe); +SALIS_API void sal_main_init(uint32 order); /** Free resources and quit Salis. */ @@ -32,9 +31,8 @@ SALIS_API void sal_main_quit(void); /** Load existing Salis simulation from saved file. * @param file_name Path of the save file to be loaded -* @param pipe Desired path and file name of common pipe */ -SALIS_API void sal_main_load(string file_name, string pipe); +SALIS_API void sal_main_load(string file_name); /** Save Salis simulation to a file. * @param file_name Path of the save file to be created diff --git a/src/common.c b/src/common.c index 3653252..402320e 100644 --- a/src/common.c +++ b/src/common.c @@ -1,69 +1,49 @@ #include -#include -#include -#include #include "types.h" #include "instset.h" #include "common.h" -static boolean g_is_init; -static int g_file_desc; +static Sender g_sender; +static Receiver g_receiver; -void _sal_comm_init(string pipe) +void sal_comm_set_sender(Sender sender) { - /* Initialize the common pipe. This module is the only one on Salis that - makes use of Linux specific headers and types. If you want, feel free to - port this code into other platforms (should be easy). If you do so, let me - know and we can incorporate it into the Salis repository. + /* Set sender functor. Whenever an organism calls the SEND instruction, + this function will get called. When unset, SEND instruction is ignored. */ - assert(!g_is_init); - mkfifo(pipe, 0666); - g_is_init = TRUE; - - /* It's important to open the FIFO file in non-blocking mode, or else the - simulators might halt if the pipe becomes empty. - */ - g_file_desc = open(pipe, O_RDWR | O_NONBLOCK); - assert(g_file_desc != -1); + assert(sender); + g_sender = sender; } -void _sal_comm_quit(void) +void sal_comm_set_receiver(Receiver receiver) { - /* Close the common pipe FIFO file from within this instance. An empty pipe - file will remain unless it gets manually deleted. + /* Set receiver functor. Whenever an organism calls the RCVE instruction, + this function will get called. When unset, RCVE instruction is ignored. */ - assert(g_is_init); - close(g_file_desc); - g_is_init = FALSE; - g_file_desc = 0; + assert(receiver); + g_receiver = receiver; } void _sal_comm_send(uint8 inst) { - /* Send a single byte (instruction) to the common pipe. This function is - called by processes that execute the SEND instruction. Hopefully, some of - them 'learn' to use this as an advantage. - - In the future, I want to make the common pipe able to communicate across - local networks (LANs) and over the Internet. + /* Send a single byte (instruction) to the sender. This function is called + by processes that execute the SEND instruction. */ - assert(g_is_init); assert(sal_is_inst(inst)); - write(g_file_desc, &inst, 1); + + if (g_sender) { + g_sender(inst); + } } uint8 _sal_comm_receive(void) { - /* Receive a single byte (instruction) from the common pipe. This function - is called by processes that execute the RCVE instruction. If the pipe is - empty, this function returns the NOP0 instruction. + /* 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. */ - uint8 inst; - ssize_t res; - assert(g_is_init); - res = read(g_file_desc, &inst, 1); - - if (res) { + if (g_receiver) { + uint8 inst = g_receiver(); assert(sal_is_inst(inst)); return inst; } else { diff --git a/src/process.c b/src/process.c index 2b9fff8..eb89a8d 100644 --- a/src/process.c +++ b/src/process.c @@ -1077,7 +1077,7 @@ static void write(uint32 pidx) static void send(uint32 pidx) { - /* Send instruction on given register into the common pipe. + /* Send instruction on given register into the common sender. */ uint32_p reg; assert(g_is_init); @@ -1102,8 +1102,8 @@ static void send(uint32 pidx) static void receive(uint32 pidx) { - /* Receive a single instruction from the common pipe and store it into a - specified register. In case the common pipe is empty, it will return the + /* 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; diff --git a/src/salis.c b/src/salis.c index 1aae1fa..32a14b8 100644 --- a/src/salis.c +++ b/src/salis.c @@ -7,14 +7,13 @@ static boolean g_is_init; static uint32 g_cycle; static uint32 g_epoch; -void sal_main_init(uint32 order, string pipe) +void sal_main_init(uint32 order) { /* 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); - _sal_comm_init(pipe); _sal_evo_init(); _sal_proc_init(); g_is_init = TRUE; @@ -30,17 +29,16 @@ void sal_main_quit(void) assert(g_is_init); _sal_proc_quit(); _sal_evo_quit(); - _sal_comm_quit(); _sal_mem_quit(); g_is_init = FALSE; g_cycle = 0; g_epoch = 0; } -void sal_main_load(string file_name, string pipe) +void sal_main_load(string file_name) { /* Load simulation state from file. This file must have been created by - 'sal_main_save()'. File name of common pipe must also be provided. + 'sal_main_save()'. */ FILE *file; assert(!g_is_init); @@ -54,7 +52,6 @@ void sal_main_load(string file_name, string pipe) _sal_evo_load_from(file); _sal_proc_load_from(file); fclose(file); - _sal_comm_init(pipe); } void sal_main_save(string file_name) -- cgit v1.2.1