summaryrefslogtreecommitdiff
path: root/spires_memristor_sim/spires_interface.py
diff options
context:
space:
mode:
Diffstat (limited to 'spires_memristor_sim/spires_interface.py')
-rw-r--r--spires_memristor_sim/spires_interface.py119
1 files changed, 100 insertions, 19 deletions
diff --git a/spires_memristor_sim/spires_interface.py b/spires_memristor_sim/spires_interface.py
index 3f1e302..b7e5fff 100644
--- a/spires_memristor_sim/spires_interface.py
+++ b/spires_memristor_sim/spires_interface.py
@@ -1,35 +1,116 @@
import ctypes
import numpy
import torch
+import random
-spires_lib = ctypes.CDLL("../spires/build/.libspires.so")
+LIF_DISCRETE = 0
-spires_lib.spires_reservoir_step.argtypes = [ctypes.POINTER(ctypes.c_float)]
-spires_lib.spires_reservoir_step.restype = None
+#load the spires library
+spires_lib = ctypes.CDLL("../spires/lib/libspires.so")
+
+# C signautes for creating reservoir
+spires_lib.create_reservoir.argtypes = [
+ ctypes.c_size_t,
+ ctypes.c_size_t,
+ ctypes.c_size_t,
+ ctypes.c_double,
+ ctypes.c_double,
+ ctypes.c_double,
+ ctypes.c_double,
+ ctypes.c_double,
+ ctypes.c_int,
+ ctypes.c_int,
+ ctypes.POINTER(ctypes.c_double)
+]
+spires_lib.create_reservoir.restype = ctypes.c_void_p
+
+# C signatures for reservoir destruction
+spires_lib.free_reservoir.argtypes = [ctypes.c_void_p]
+spires_lib.free_reservoir.restype = None
+
+# C signatures for step reservoir function
+spires_lib.update_neuron.argtypes = [
+ ctypes.c_void_p, #Pointer to spires reservoir struct
+ ctypes.c_int,
+ ctypes.c_double,
+ ctypes.c_double
+]
+spires_lib.update_neuron.restype = None
+
+# C signatures for get neuron spike function
+spires_lib.read_reservoir_spikes.argtypes = [
+ ctypes.c_void_p,
+ ctypes.POINTER(ctypes.c_float)
+]
+spires_lib.read_reservoir_spikes.restype = None
+
+def init_spires_reservoir(reservoir_size):
+ print("Creating spires reservoir")
+
+ neuron_parameters = (ctypes.c_double * 4)(0.0, 1.0, 0.2, 0.5)
+ c_neuron_parameters = ctypes.cast(neuron_parameters, ctypes.POINTER(ctypes.c_double))
+
+ reservoir_ptr = spires_lib.create_reservoir(
+ ctypes.c_size_t(int(reservoir_size)), # num neurons
+ ctypes.c_size_t(int(reservoir_size)), # num neurons
+ ctypes.c_size_t(2), # num_outputs
+ ctypes.c_double(0.9), # spectral radius
+ ctypes.c_double(0.8), # ei_ratio
+ ctypes.c_double(1.0), # input_strength
+ ctypes.c_double(0.1), # connectivity
+ ctypes.c_double(1.0), # dt
+ ctypes.c_int(1), # connectivity type ( 1 = sparse)
+ ctypes.c_int(LIF_DISCRETE), # neuron type
+ c_neuron_parameters # neuron params
+ )
+
+ #allocate empty void pointer, (reservoir will go here)
+ if not reservoir_ptr:
+ raise RuntimeError(f"Spires faile to initialize the reservoir: {status_code}")
+ else:
+ print("Spires reservoir initialized")
+
+ # reservoir_ptr._keep_alive = neuron_parameters
+
+ return reservoir_ptr
+
+def free_spires_reservoir(reservoir_ptr):
+ print("Freeing the spires reservoir")
+ spires_lib.free_reservoir(reservoir_ptr)
+ return 0
+
#change currents from tensor to a flat C pointer array for spires to read
-def send_currents_to_spires(currents):
+def send_currents_to_spires(reservoir_ptr, currents_tensor):
+ print("Sending currents to spires")
# ----- extract from pytorhc graph -----
# .detach() removes it from auto gradient tracking
# .cpu() make sure data is in RAM, not VRAM
# .numpy() maps it to numpy array
- numpy_array = torch_tensor.detach().cpu().numpy()
-
- # ----- makes suren layout matches 32 bit float C-array -----
- # .astype(npfloat32) forces standard CC float precistion
+ # ----- makes suren layout matches 64 bit double C-array -----
+ # .astype(npfloat64) forces standard CC float precistion
# .flatten() makes sure the memory is a 1D block
- contiguous_array = numpy_array.astype(np.float32).flatten()
+ numpy_array = currents_tensor.detach().cpu().numpy().astype(numpy.float64).flatten()
- # ----- Ensure raw memory pointer -----
- c_float_ptr = contiguous_array.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
- array_size = contiguous_array.size
+ some_ptr = ctypes.cast(reservoir_ptr, ctypes.POINTER(ctypes.POINTER(ctypes.c_void_p)))
- # ----- Call the C library -----
- spires_lib.spires_reservoir_step(c_float_ptr, array_size)
- return contiguous_array
+ neurons_array = some_ptr[0]
- # NEED TO MODIFY SPIRES FOR THIS?? :((
+ print("updating the neurons")
+ for i in range(len(numpy_array)):
+ neuron_ptr = neurons_array[i]
+ input_current = numpy_array[i]
-def read_spikes_from_spires():
- placeholder = 0
- return 0
+ spires_lib.update_neuron(neuron_ptr, LIF_DISCRETE, input_current, 1.0)
+
+ return numpy_array
+
+def read_spikes_from_spires(reservoir_ptr, size=0):
+ print("Recieved spikes from spires")
+ #didnt do any safety checking womp womp
+ returned_spikes = numpy.zeros(size, dtype=numpy.float64)
+ c_spike_ptr = returned_spikes.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
+
+ spires_lib.read_reservoir_spikes(reservoir_ptr, c_spike_ptr)
+
+ return returned_spikes