diff options
Diffstat (limited to 'spires_memristor_sim/spires_interface.py')
| -rw-r--r-- | spires_memristor_sim/spires_interface.py | 119 |
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 |
