/***************************************************************************
* SimulinkBlockInterface.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 "../../../include/simulation/Simulation.h"
#include "../../../include/communication/InputBooleanArrayDriver.h"
#include "../../../include/communication/OutputBooleanArrayDriver.h"
#include "../../../include/communication/FileOutputSpikeDriver.h"
#include "../../../include/communication/FileOutputWeightDriver.h"
#include <ctime>
// Define input parameters
#define PARAMNET ssGetSFcnParam(S,0) // Network description file
#define PARAMWEIGHT ssGetSFcnParam(S,1) // Weight description file
#define PARAMLOG ssGetSFcnParam(S,2) // Log activity output file
#define PARAMTDSTEP ssGetSFcnParam(S,3) // Time-driven simulation step
#define PARAMINPUT ssGetSFcnParam(S,4) // Input map - Vector mapping each input line with an input cell
#define PARAMOUTPUT ssGetSFcnParam(S,5) // Output map - Vector mapping each output line with an output cell
#define PARAMSWFILE ssGetSFcnParam(S,6) // File where the synaptic weights will be stored.
#define PARAMSWTIME ssGetSFcnParam(S,7) // Step time between consecutive weight saving.
SimulinkBlockInterface::SimulinkBlockInterface(): Simul(0), InputDriver(0), OutputDriver(0), FileDriver(0), WeightDriver(0){
}
SimulinkBlockInterface::~SimulinkBlockInterface() {
if (this->Simul!=0){
delete this->Simul;
}
this->Simul = 0;
if (this->InputDriver!=0){
delete this->InputDriver;
}
this->InputDriver = 0;
if (this->OutputDriver!=0){
delete this->OutputDriver;
}
this->OutputDriver = 0;
if (this->FileDriver!=0){
delete this->FileDriver;
}
this->FileDriver = 0;
if (this->WeightDriver!=0){
delete this->WeightDriver;
}
this->WeightDriver;
}
void SimulinkBlockInterface::InitializeSimulation(SimStruct *S){
// Initialize the Simulation Object
// Get the inputs.
double SimulationTime = 1e100;
char NetworkFile[128];
mxGetString(PARAMNET, NetworkFile, 128);
char WeightFile[128];
mxGetString(PARAMWEIGHT, WeightFile, 128);
char LogFile[128];
mxGetString(PARAMLOG, LogFile, 128);
char SavingWeightFile[128];
mxGetString(PARAMSWFILE, SavingWeightFile, 128);
srand (time(NULL));
time_T Step = ssGetSampleTime(S, 0);
try {
this->Simul = new Simulation(NetworkFile, WeightFile, SimulationTime, 0);
this->WeightDriver = new FileOutputWeightDriver (SavingWeightFile);
this->Simul->AddOutputWeightDriver(this->WeightDriver);
real_T * SavingWeightStep = (real_T *)mxGetData(PARAMSWTIME);
double SWStep = (double) SavingWeightStep[0];
if (SWStep!=0){
this->Simul->SetSaveStep(SWStep);
}
// real_T * TimeDrivenStep = (real_T *)mxGetData(PARAMTDSTEP);
// double TDStep = (double) TimeDrivenStep[0];
// if (TDStep!=0){
// this->Simul->SetTimeDrivenStep(TDStep);
// }
real_T * InputCells = (real_T *)mxGetData(PARAMINPUT);
unsigned int NumberOfElements = (unsigned int) mxGetNumberOfElements(PARAMINPUT);
int * IntInputCells = new int [NumberOfElements];
for (unsigned int i=0; i<NumberOfElements; ++i){
IntInputCells[i] = (int)(InputCells[i]);
}
// Create a new input object to add input spikes
this->InputDriver = new InputBooleanArrayDriver(NumberOfElements, IntInputCells);
this->Simul->AddInputSpikeDriver(this->InputDriver);
delete [] IntInputCells;
real_T * OutputCells = (real_T *) mxGetData(PARAMOUTPUT);
unsigned int NumberOfElementsOut = (unsigned int) mxGetNumberOfElements(PARAMOUTPUT);
int * IntOutputCells = new int [NumberOfElementsOut];
for (unsigned int i=0; i<NumberOfElementsOut; ++i){
IntOutputCells[i] = (int) OutputCells[i];
}
// Create a new output object to get output spike
this->OutputDriver = new OutputBooleanArrayDriver(NumberOfElementsOut, IntOutputCells);
this->Simul->AddOutputSpikeDriver(this->OutputDriver);
delete [] IntOutputCells;
this->FileDriver = new FileOutputSpikeDriver(LogFile,false);
Simul->AddMonitorActivityDriver(this->FileDriver);
this->Simul->InitSimulation();
} catch (EDLUTFileException Exc){
ssPrintf("Error %li: %s in %s\n",Exc.GetErrorNum(),Exc.GetErrorMsg(),Exc.GetTaskMsg());
ssPrintf("Try %s\n",Exc.GetRepairMsg());
ssSetErrorStatus(S, "File error in initializing simulation object");
} catch (EDLUTException Exc){
ssPrintf("Error %li: %s in %s\n",Exc.GetErrorNum(),Exc.GetErrorMsg(),Exc.GetTaskMsg());
ssPrintf("Try %s\n",Exc.GetRepairMsg());
ssSetErrorStatus(S, "Error in initializing simulation object");
return;
}
}
void SimulinkBlockInterface::SimulateStep(SimStruct *S, int_T tid){
if (ssIsSampleHit(S,0,tid)){
//ssPrintf("Getting number of elements\n");
unsigned int NumberOfElements = (unsigned int) mxGetNumberOfElements(PARAMINPUT);
//ssPrintf("Found %i input signals\n",NumberOfElements);
bool * InputSignals = new bool [NumberOfElements];
InputPtrsType u = ssGetInputPortSignalPtrs(S,0);
InputBooleanPtrsType uPtrs = (InputBooleanPtrsType)u;
//ssPrintf("Input pointer obtained\n");
for (unsigned int i=0; i<NumberOfElements; ++i){
boolean_T value = *uPtrs[i];
InputSignals[i] = value;
//ssPrintf("Input signal %i: Value %i\n",i,value);
}
// Get current simulation time
time_T Step = ssGetSampleTime(S, 0);
double StepTime = (double) Step;
double CurrentTime = (double) ssGetT(S);
double NextTime = CurrentTime+StepTime;
//ssPrintf("Current time is %f and next time is %f\n",CurrentTime,NextTime);
this->InputDriver->LoadInputs(Simul->GetQueue(),Simul->GetNetwork(), (bool *) InputSignals, CurrentTime);
//ssPrintf("Input signals obtained\n");
Simul->RunSimulationSlot(NextTime);
//ssPrintf("Simulation step finished\n");
delete [] InputSignals;
}
}
void SimulinkBlockInterface::AssignOutputs(SimStruct *S){
unsigned int NumberOfElements = (unsigned int) mxGetNumberOfElements(PARAMOUTPUT);
bool * OutputSignals = new bool [NumberOfElements];
this->OutputDriver->GetBufferedSpikes(OutputSignals);
boolean_T * u = (boolean_T *) ssGetOutputPortSignal(S,0);
for (unsigned int i=0; i<NumberOfElements; ++i){
u[i] = (boolean_T) OutputSignals[i];
}
delete [] OutputSignals;
}