00001 /*************************************************************************** 00002 * SpikeStream Simulation * 00003 * Copyright (C) 2007 by David Gamez * 00004 * david@davidgamez.eu * 00005 * Version 0.1 * 00006 * * 00007 * This program is free software; you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation; either version 2 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License * 00018 * along with this program; if not, write to the * 00019 * Free Software Foundation, Inc., * 00020 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00021 ***************************************************************************/ 00022 00023 #ifndef SPIKESTREAMSIMULATION_H 00024 #define SPIKESTREAMSIMULATION_H 00025 00026 //SpikeStream includes 00027 #include "DBInterface.h" 00028 #include "Neuron.h" 00029 #include "Synapse.h" 00030 #include "TaskHolder.h" 00031 #include "DeviceManager.h" 00032 #include "PatternManager.h" 00033 #include "ClassLoader.h" 00034 #include "SimulationClock.h" 00035 #include "PerformanceTimer.h" 00036 00037 //Other includes 00038 #include <stack> 00039 #include <google/dense_hash_map> 00040 using HASH_NAMESPACE::hash; 00041 using GOOGLE_NAMESPACE::dense_hash_map; 00042 00043 00044 /*! Struct to hold messages that arrive early out of sequence.*/ 00045 struct EarlyMessage { 00046 int senderTID; 00047 int bufferID; 00048 int timeStep; 00049 }; 00050 00051 00052 /*! Struct to hold statistics about simulation.*/ 00053 struct Statistics { 00054 int startTimeStep; 00055 int neuronFireTotal; 00056 int spikeTotal; 00057 }; 00058 00059 00060 //---------------------- SpikeStream Simulation ---------------------------- 00061 /*! The main class for the control of the simulation. This class is spawned 00062 from an initiating parent class which acts as the central node for the 00063 simulation. Each instance of this class is responsible for simulating 00064 part of the neural network - generally a neuron group. */ 00065 00066 /* FIXME AT SOME POINT SPLIT THIS HUGE CLASS UP INTO SUB CLASSES, SUCH AS 00067 NEURON MANAGER, SYNAPSE MANAGER MESSAGE HANDLER ETC. */ 00068 //-------------------------------------------------------------------------- 00069 00070 class SpikeStreamSimulation { 00071 00072 public: 00073 SpikeStreamSimulation(); 00074 SpikeStreamSimulation(int argc, char **argv); 00075 ~SpikeStreamSimulation(); 00076 static unsigned int getNeuronGrpID(); 00077 static void systemError(const char* message); 00078 static void systemError(const string &message); 00079 static void systemError_double(const string &message, double messageData1); 00080 static void systemError_int(const string &message, int messageData1); 00081 static void systemError(const char *message, int messageData1); 00082 static void systemInfo(const char *message); 00083 static void systemInfo(const char *message, bool messageData1); 00084 static void systemInfo(const char *message, int messageData1); 00085 00086 00087 //======================== PUBLIC VARIABLES ====================== 00088 /*! Clock for the simulation.*/ 00089 static SimulationClock *simulationClock; 00090 00091 00092 #ifdef RECORD_STATISTICS 00093 00094 /*! Period in microseconds in over which statistics are gathered 00095 before simulation is stopped.*/ 00096 #define STATS_MONITORING_PERIOD 300000000 00097 00098 /*! Struct to hold statistics.*/ 00099 static Statistics statistics; 00100 00101 /*! Timer for monitoring period.*/ 00102 PerformanceTimer statisticsTimer; 00103 00104 #endif//RECORD_STATISTICS 00105 00106 00107 00108 private: 00109 //========================= VARIABLES ============================ 00110 /*! Task ID of this task.*/ 00111 static int thisTaskID; 00112 00113 /*! Task ID of the task that spawned this task.*/ 00114 static int parentTaskID; 00115 00116 /*! In the run method this controls whether the simulation should stop.*/ 00117 bool stop; 00118 00119 /*! When the simulation has an error it enters error state, waits 00120 for an exit message and then exits. This is to enable the Simulation 00121 Manager to clean up properly.*/ 00122 static bool errorState; 00123 00124 /*! Records whether all of the simulation data has been loaded.*/ 00125 bool simulationDataLoaded; 00126 00127 /*! Records whether the initial messages have been sent so that 00128 simulation can keep running.*/ 00129 bool simulationStarted; 00130 00131 /*! Records whether the simulation is running or not.*/ 00132 bool simulationRunning; 00133 00134 /*! ID of the neuron group that is being simulated by this task.*/ 00135 static unsigned int neuronGrpID; 00136 00137 /*! The type of neuron that is being simulated. This corresponds 00138 to an entry in the NeuronTypes database and a class library 00139 dynamically loaded at run time.*/ 00140 unsigned short neuronType; 00141 00142 /*! Map holding all of the synapses. The key in the outer dense_hash_map 00143 is the from neuron ID. The key in the inner dense_hash_map is the to 00144 neuron id. References to neurons are held within each synapse.*/ 00145 dense_hash_map<unsigned int, dense_hash_map<unsigned int, Synapse*, hash<unsigned int> >*, hash<unsigned int> > synapseMap; 00146 00147 /*! Map holding the synapse parameters for each of the connection groups 00148 Key is the connection group id.*/ 00149 map<unsigned int, map<string, double>* > connParameterMap; 00150 00151 /*! Array of all the neurons - held as references 00152 Although the neuron references are also held in the synapses they need to be 00153 updated once all the post synaptic membrane potentials have been calculated.*/ 00154 Neuron** neuronArray; 00155 00156 /*! Records the id of the first neuron in the group. Used to access a 00157 neuron by neuronID in the neuronArray.*/ 00158 unsigned int startNeuronID; 00159 00160 /*! Size of the neuron array.*/ 00161 unsigned int numberOfNeurons; 00162 00163 /*! Width of the neuron group being simulated by this task.*/ 00164 unsigned int neuronGrpWidth; 00165 00166 /*! Length of the neuron group being simulated by this task.*/ 00167 unsigned int neuronGrpLength; 00168 00169 /*! Keeps track of how many spike messages have been received. The spike list is sent 00170 when all spike messages have been received from other tasks.*/ 00171 unsigned int spikeMessageCount; 00172 00173 /*! The sum of the taskIDs of the tasks that will be sending spike messages 00174 to this task within each update cycle.*/ 00175 unsigned int spikeMessageTotal; 00176 00177 /*! Map holding references to all the task holders that handle spike 00178 messages. Each task holder class is responsible for sending spikes 00179 to a particular task and any additional monitoring tasks 00180 as well. Neurons hold a list of spike task holders that they use to 00181 add their spikes to the spike buffers held in this class. 00182 The key of this map is the destinationTaskID. 00183 The data of this map is the TaskHolder that sends messages.*/ 00184 map<int, TaskHolder*> spikeTaskHolderMap; 00185 00186 /*! Reference to a neuron task holder that holds the list of firing 00187 neurons in this simulation and sends messages to any task that 00188 want this information.*/ 00189 NeuronTaskHolder *neuronTaskHolder; 00190 00191 /*! Holds the link between a connection group and a task. 00192 The key is the connGrpID; the data is the taskID.*/ 00193 map<unsigned int, int> taskConnGrpMap; 00194 00195 /*! Holds the link between neuronGrpID and task ID 00196 The key is the neuronGrpID; the data is the taskID.*/ 00197 map<unsigned int, int> taskNeurGrpMap; 00198 00199 /*! Holds the start neuron ID for each task processing neurons 00200 The key is the task id, the data is the start neuron id of that 00201 neuron group.*/ 00202 map<int, unsigned int> startNeurIDTaskMap; 00203 00204 /*! Defines what type of simulation is being run in this task. 00205 These are defined in SimulationTypes.h.*/ 00206 unsigned int simulationType; 00207 00208 //References to the classes that handle database access 00209 DBInterface *networkDBInterface; 00210 DBInterface *patternDBInterface; 00211 DBInterface *deviceDBInterface; 00212 00213 /*! Reference to class for handling devices.*/ 00214 DeviceManager *deviceManager; 00215 00216 /*! Reference to class for handling patterns.*/ 00217 PatternManager *patternManager; 00218 00219 /*! Reference to class loader, which is used to create new neurons 00220 and synapses by dynamically loading them from libraries.*/ 00221 ClassLoader *classLoader; 00222 00223 /*! How many time steps each pattern will be presented for.*/ 00224 unsigned int timeStepsPerPattern; 00225 00226 /*! Used for synchronization - sets whether this layer has 00227 delayed itself in the last time step.*/ 00228 bool delayInLastTimeStep; 00229 00230 /*! Holds the messages received one time step out of sequence.*/ 00231 stack<EarlyMessage> earlyMessageStack; 00232 00233 /*! Controls how the task id is displayed.*/ 00234 static const bool printTIDHex = true; 00235 00236 /*! Map holding all the neurons that have received a spike during this timestep 00237 Neurons in this map are updated when all spikes have been received 00238 Map is used rather than vector to avoid filtering out multiple spikes 00239 to the same neuron. The key is the full neuronID.*/ 00240 dense_hash_map<unsigned int, bool, hash<unsigned int> > neuronUpdateMap; 00241 00242 /*! Used to calculate the from neuron id from spike messages 00243 stored here to avoid constant redeclaration.*/ 00244 unsigned int unpkFromNeurID; 00245 00246 /*! Used to calculate the to neuron id from spike messages 00247 stored here to avoid constant redeclaration.*/ 00248 unsigned int unpkToNeurID; 00249 00250 /*! Array to unpack the list of spikes into.*/ 00251 unsigned int* unpackArray; 00252 00253 /*! Used to get information about PVM functions. Stored here both to save 00254 redelcaring it and because it is sometimes not used when PVM_DEBUG is not 00255 set and so generates a warning.*/ 00256 int info; 00257 00258 /*! Determines whether the compute time for each timestep is calculated.*/ 00259 bool calculateComputeTime; 00260 00261 /*! Time structure to measure how long each processing loop takes.*/ 00262 timeval startComputeTimeStruct; 00263 00264 /*! Time structure to measure how long each processing loop takes.*/ 00265 timeval endComputeTimeStruct; 00266 00267 /*! Time taken for each time step.*/ 00268 unsigned int timeStepComputeTime_us; 00269 00270 /*! The minimum time step duration. Used to slow the simulation down.*/ 00271 unsigned int minTimeStepDuration_us; 00272 00273 /*! Controls whether noise is injected into the neurons.*/ 00274 bool noiseEnabled; 00275 00276 /*! Percent of neurons fired at each time step by noise function.*/ 00277 double percentNeurons_noise; 00278 00279 /*! Set to true when the percentage of neurons selected for noise is random.*/ 00280 bool randomPercentNoise; 00281 00282 /*! Are the noise neurons fired directly or by injecting synaptic current?.*/ 00283 bool directFiring_noise; 00284 00285 /*! Amount of synaptic current used for neurons fired by noise.*/ 00286 double synapticWeight_noise; 00287 00288 /*! Controls whether all neuron classes are updated at each time step.*/ 00289 bool updateAllNeurons; 00290 00291 /*! Controls whether all synapse classes are updated at each time step.*/ 00292 bool updateAllSynapses; 00293 00294 /*! Controls whether we are sending neuron data back to the main application 00295 for monitoring purposes.*/ 00296 bool neuronMonitorMode; 00297 00298 /*! The neurons that are being monitored. Use map to filter out duplicates.*/ 00299 dense_hash_map<unsigned int, bool, hash<unsigned int> > neuronMonitorMap; 00300 00301 /*! Controls whether we are sending synapse data back to the main application 00302 for monitoring purposes.*/ 00303 bool synapseMonitorMode; 00304 00305 /*! Map holding reference to the synapses that are being monitored. The key is 00306 an unsigned int array that is dynamically allocated on the heap.*/ 00307 map<unsigned int*, Synapse*, synapseKeyCompare> synapseMonitorMap; 00308 00309 00310 //======================== METHODS ============================== 00311 /*! Declare copy constructor private so it cannot be used inadvertently.*/ 00312 SpikeStreamSimulation (const SpikeStreamSimulation&); 00313 00314 /*! Declare assignment private so it cannot be used.*/ 00315 SpikeStreamSimulation operator = (const SpikeStreamSimulation&); 00316 00317 void addReceivingTask_Neurons(int taskID); 00318 void addReceivingTask_Spikes(int taskID); 00319 void addTaskIDToDatabase(); 00320 void cleanUpSimulation(); 00321 void fireRandomNeurons(double noiseAmount); 00322 void fireRandomNeurons_synaptic(double noiseAmount); 00323 void fireSpecifiedNeurons(); 00324 double getRandomPercentage(); 00325 void injectNoise(); 00326 bool loadGlobalParameters(); 00327 bool loadNeuronParameters(); 00328 void loadNeurons(); 00329 bool loadNoiseParameters(); 00330 void loadPreSynapticNeuronMaps(); 00331 void loadSimulationData(); 00332 bool loadSynapseParameters(); 00333 void loadSynapses(); 00334 void loadTasks(); 00335 void printSynapseMap(); 00336 static void printTID(); 00337 static void printTID(int taskID); 00338 void processSpikeList(unsigned int senderTID, int msgTimeStep); 00339 void reloadWeights(); 00340 void removeReceivingTask_Neurons(int removeTaskID); 00341 void removeReceivingTask_Spikes(int removeTaskID); 00342 void run(); 00343 void saveViewWeights(); 00344 void saveWeights(); 00345 static bool sendMessage(int taskID, int msgtag);//Static so it can be called from systemError() 00346 static bool sendMessage(int taskID, int msgtag, const char* msgdata);//Static so it can be called from systemError() 00347 static bool sendMessage(int taskID, int msgtag, unsigned int data1, const char* msgdata); 00348 bool sendMessage(int taskID, int msgtag, unsigned int data1, unsigned int data2, const char* msgdata); 00349 bool sendNeuronData(int taskID, int msgtag, unsigned int neuronID, double* dataArray, int arrayLength); 00350 void sendSpikeMessages(); 00351 bool sendSynapseData(int taskID, int msgtag, unsigned int fromNeurID, unsigned int toNeurID, double* dataArray, int arrayLength); 00352 void setDelayInLastTimeStep(bool dly); 00353 void setMaxBufferSize(); 00354 void setMinTimeStepDuration(int senderTID); 00355 void setUpdateMode(int senderTID); 00356 void startNeuronMonitoring(int senderTID, bool restart); 00357 void startSimulation(); 00358 void startSynapseMonitoring(int senderTID, bool restart); 00359 void stepSimulation(); 00360 void stopSimulation(); 00361 void stopNeuronMonitoring(int senderTID); 00362 void stopSynapseMonitoring(int senderTID); 00363 00364 }; 00365 00366 00367 #endif//SPIKESTREAMSIMULATION_H 00368
1.4.4