/***************************************************************************
* EDLUTMatlab.cpp *
* ------------------- *
* copyright : (C) 2010 by Jesus Garrido *
* email : jgarrido@atc.ugr.es *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <time.h>
#include <math.h> // TODO: maybe remove this
#include <iostream>
#include "mex.h"
#include "../include/simulation/Simulation.h"
#include "../include/communication/FileInputSpikeDriver.h"
#include "../include/communication/FileOutputSpikeDriver.h"
#include "../include/communication/ArrayInputSpikeDriver.h"
#include "../include/communication/ArrayOutputSpikeDriver.h"
#include "../include/spike/EDLUTFileException.h"
#include "../include/spike/EDLUTException.h"
#include "../include/spike/Network.h"
using namespace std;
/*!
*
* \note Input arguments in mex file:
* 1. Simulation time (-time kernel parameter).
* 2. Network File (-nf kernel parameter).
* 3. Weights File (-wf kernel parameter).
* 4. Input File (-if kernel parameter).
* 5. Log File (-log kernel parameter).
*
*
* \note Obligatory parameters:
* -time Simulation_Time(in_seconds) It sets the total simulation time.
* -nf Network_File It sets the network description file.
* -wf Weights_File It sets the weights file.
*
* \note parameters:
* -info It shows the network information.
* -sf File_Name It saves the final weights in file File_Name.
* -wt Save_Weight_Step It sets the step time between weights saving.
* -st Step_Time(in_seconds) It sets the step time in simulation.
* -log File_Name It saves the activity register in file File_Name.
* -if Input_File It adds the Input_File file in the input sources of the simulation.
* -of Output_File It adds the Output_File file in the output targets of the simulation.
* -ic IPDirection:Port Server|Client It adds the connection as a server or a client in the specified address in the input sources of the simulation.
* -oc IPDirection:Port Server|Client It adds the connection as a server or a client in the specified address in the output targets of the simulation.
* -ioc IPDirection:Port Server|Client It adds the connection as a server or a client in the specified address in the input sources and in the output targets of the simulation.
*
*/
extern void _main();
const int numInputArgs = 5;
const int numOutputArgs = 2;
// Function declarations.
// -----------------------------------------------------------------
double getMatlabScalar(const mxArray* ptr);
char * getMatlabString(const mxArray* ptr);
double& createMatlabScalar(mxArray*& ptr);
double* createMatlabDoubleArray(mxArray*& ptr,int OutputNumber);
long int* createMatlabIntArray(mxArray*& ptr,int OutputNumber);
// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
// Check to see if we have the correct number of input and output
// arguments.
if (nrhs != numInputArgs){
mexErrMsgTxt("Incorrect number of input arguments");
mexErrMsgTxt("Use: [SpikeTimes, CellNumbers] = EDLUTKernel(SimulationTime,NetworkFile,WeightFile,InputFile,LogFile)");
}
if (nlhs != numOutputArgs){
mexErrMsgTxt("Incorrect number of output arguments");
mexErrMsgTxt("[SpikeTimes, CellNumbers] = EDLUTKernel(SimulationTime,NetworkFile,WeightFile,InputFile,LogFile)");
}
// Get the inputs.
double SimulationTime = getMatlabScalar(prhs[0]);
char * NetworkFile = getMatlabString(prhs[1]);
char * WeightFile = getMatlabString(prhs[2]);
char * InputFile = getMatlabString(prhs[3]);
char * LogFile = getMatlabString(prhs[4]);
clock_t startt,endt;
double * OutputSpikeTimes;
long int * OutputSpikeCells;
cout << "Int size: " << sizeof(int) << endl;
cout << "Long int size: " << sizeof(long int) << endl;
srand ( time(NULL) );
try {
Simulation Simul(NetworkFile, WeightFile, SimulationTime, 0);
// Create a new input object to add input spikes
// ArrayInputSpikeDriver * InputDriver = new ArrayInputSpikeDriver();
//Simul->AddInputSpikeDriver(InputDriver);
// Create a new output object to get output spikes
ArrayOutputSpikeDriver * OutputDriver = new ArrayOutputSpikeDriver();
Simul.AddOutputSpikeDriver(OutputDriver);
FileInputSpikeDriver * InputDriver = new FileInputSpikeDriver(InputFile);
Simul.AddInputSpikeDriver(InputDriver);
FileOutputSpikeDriver * MonitorDriver = new FileOutputSpikeDriver(LogFile,false);
Simul.AddMonitorActivityDriver(MonitorDriver);
cout << "Simulating network..." << endl;
startt=clock();
Simul.RunSimulation();
endt=clock();
// Get outputs and print them
int OutputNumber = OutputDriver->GetBufferedSpikes(OutputSpikeTimes,OutputSpikeCells);
// Create the output. It is also a double-precision scalar.
double* SpikeTimes = createMatlabDoubleArray(plhs[0],OutputNumber);
long int* SpikeCells = createMatlabIntArray(plhs[1],OutputNumber);
if (OutputNumber>0){
memcpy(SpikeTimes, OutputSpikeTimes, OutputNumber*sizeof(double));
memcpy(SpikeCells, OutputSpikeCells, OutputNumber*sizeof(long int));
delete [] OutputSpikeTimes;
delete [] OutputSpikeCells;
}
cout << "Oky doky" << endl;
cout << "Elapsed time: " << (endt-startt)/(float)CLOCKS_PER_SEC << " sec" << endl;
cout << "Number of updates: " << Simul.GetSimulationUpdates() << endl;
cout << "Mean number of spikes in heap: " << Simul.GetHeapAcumSize()/(float)Simul.GetSimulationUpdates() << endl;
cout << "Updates per second: " << Simul.GetSimulationUpdates()/((endt-startt)/(float)CLOCKS_PER_SEC) << endl;
delete OutputDriver;
delete InputDriver;
delete MonitorDriver;
} catch (EDLUTFileException Exc){
cerr << Exc << ": " << Exc.GetErrorNum() << endl;
} catch (EDLUTException Exc){
cerr << Exc << ": " << Exc.GetErrorNum() << endl;
}
}
double getMatlabScalar (const mxArray* ptr) {
// Make sure the input argument is a scalar in double-precision.
if (!mxIsDouble(ptr) || mxGetNumberOfElements(ptr) != 1)
mexErrMsgTxt("The input argument must be a double-precision scalar");
return *mxGetPr(ptr);
}
char * getMatlabString (const mxArray* ptr) {
// Make sure the input argument is a scalar in double-precision.
if (!mxIsChar(ptr))
mexErrMsgTxt("The input argument must be a string");
return mxArrayToString (ptr);
}
double& createMatlabScalar (mxArray*& ptr) {
ptr = mxCreateDoubleMatrix(1,1,mxREAL);
return *mxGetPr(ptr);
}
double* createMatlabDoubleArray(mxArray*& ptr,int OutputNumber){
ptr = mxCreateDoubleMatrix(OutputNumber,1,mxREAL);
return mxGetPr(ptr);
}
long int* createMatlabIntArray(mxArray*& ptr,int OutputNumber){
ptr = mxCreateNumericMatrix(OutputNumber,1,mxINT32_CLASS,mxREAL);
return (long int *) mxGetData(ptr);
}