aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/common.h27
-rw-r--r--include/instset.h4
-rw-r--r--include/salis.h6
-rw-r--r--src/common.c66
-rw-r--r--src/process.c6
-rw-r--r--src/salis.c9
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 <assert.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
#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)