26 SpikeWriterText(
const std::string &filename,
const std::string &delimiter =
" ",
bool header =
false)
27 : m_Stream(filename), m_Delimiter(delimiter)
30 m_Stream.precision(16);
33 m_Stream <<
"Time [ms], Neuron ID" << std::endl;
38 #if !defined(__GNUC__) || __clang__ || __GNUC__ > 4 40 : m_Stream(
std::move(other.m_Stream)),
41 m_Delimiter(
std::move(other.m_Delimiter))
50 void recordSpikes(
double t,
unsigned int spikeCount,
const unsigned int *currentSpikes)
52 for(
unsigned int i = 0; i < spikeCount; i++) {
53 m_Stream << t << m_Delimiter << currentSpikes[i] << std::endl;
61 std::ofstream m_Stream;
62 const std::string m_Delimiter;
73 : m_Stream(filename), m_Delimiter(delimiter)
76 m_Stream.precision(16);
79 m_Stream <<
"Time [ms], Neuron ID" << std::endl;
84 #if !defined(__GNUC__) || __clang__ || __GNUC__ > 4 86 : m_Stream(
std::move(other.m_Stream)),
87 m_Delimiter(
std::move(other.m_Delimiter)),
88 m_Cache(
std::move(other.m_Cache))
104 for(
const auto ×tep : m_Cache) {
106 for(
unsigned int spike : timestep.second) {
108 m_Stream << timestep.first << m_Delimiter << spike << std::endl;
120 void recordSpikes(
double t,
unsigned int spikeCount,
const unsigned int *currentSpikes)
123 m_Cache.emplace_back();
126 m_Cache.back().first = t;
129 m_Cache.back().second.reserve(spikeCount);
132 std::copy_n(currentSpikes, spikeCount, std::back_inserter(m_Cache.back().second));
139 std::ofstream m_Stream;
140 const std::string m_Delimiter;
142 std::list<std::pair<double, std::vector<unsigned int>>> m_Cache;
149 template<
typename Writer = SpikeWriterText>
153 typedef unsigned int& (*GetCurrentSpikeCountFunc)(
unsigned int);
154 typedef unsigned int* (*GetCurrentSpikesFunc)(
unsigned int);
156 template<
typename... WriterArgs>
158 GetCurrentSpikeCountFunc getCurrentSpikeCount, WriterArgs &&... writerArgs)
159 : Writer(
std::forward<WriterArgs>(writerArgs)...), m_Batch(batch),
160 m_GetCurrentSpikes(getCurrentSpikes), m_GetCurrentSpikeCount(getCurrentSpikeCount), m_Sum(0)
164 template<
typename... WriterArgs>
165 SpikeRecorder(GetCurrentSpikesFunc getCurrentSpikes, GetCurrentSpikeCountFunc getCurrentSpikeCount,
166 WriterArgs &&... writerArgs)
167 :
SpikeRecorder(0, getCurrentSpikes, getCurrentSpikeCount,
std::forward<WriterArgs>(writerArgs)...)
178 const unsigned int spikeCount = m_GetCurrentSpikeCount(m_Batch);
180 this->
recordSpikes(t, spikeCount, m_GetCurrentSpikes(m_Batch));
183 unsigned int getSum()
const{
return m_Sum; }
189 const unsigned int m_Batch;
190 GetCurrentSpikesFunc m_GetCurrentSpikes;
191 GetCurrentSpikeCountFunc m_GetCurrentSpikeCount;
202 unsigned int popSize,
unsigned int numTimesteps,
bool append =
false)
205 const unsigned int numWords = ((popSize + 31) / 32) * numTimesteps;
208 std::ofstream spikes(filename, append ? std::ofstream::app | std::ofstream::binary : std::ofstream::binary);
209 spikes.write(reinterpret_cast<const char*>(spkRecord),
sizeof(uint32_t) * numWords);
213 inline int _clz(
unsigned int value)
216 unsigned long leadingZero = 0;
217 if(_BitScanReverse(&leadingZero, value)) {
218 return 31 - leadingZero;
224 return __builtin_clz(value);
240 unsigned int popSize,
unsigned int numTimesteps,
double dt = 1.0,
241 const std::string &delimiter =
" ",
bool header =
false,
bool append =
false,
242 double startTime = 0.0)
245 const unsigned int timestepWords = (popSize + 31) / 32;
248 std::ofstream stream(filename, append ? std::ofstream::app : std::ofstream::out);
249 stream.precision(16);
253 stream <<
"Time [ms], Neuron ID" << std::endl;
257 for(
unsigned int t = 0; t < numTimesteps; t++) {
259 const double time = startTime + (t * dt);
262 for(
unsigned int w = 0; w < timestepWords; w++) {
264 uint32_t spikeWord = spkRecord[(t * timestepWords) + w];
267 unsigned int neuronID = (w * 32) + 31;
270 while(spikeWord != 0) {
272 const int numLZ =
_clz(spikeWord);
276 spikeWord = (numLZ == 31) ? 0 : (spikeWord << (numLZ + 1));
282 stream << time << delimiter << neuronID << std::endl;
void writeTextSpikeRecording(const std::string &filename, const uint32_t *spkRecord, unsigned int popSize, unsigned int numTimesteps, double dt=1.0, const std::string &delimiter=" ", bool header=false, bool append=false, double startTime=0.0)
Definition: spikeRecorder.h:239
Class to write spikes to text file.
Definition: spikeRecorder.h:23
void writeBinarySpikeRecording(const std::string &filename, const uint32_t *spkRecord, unsigned int popSize, unsigned int numTimesteps, bool append=false)
Writes spikes recorded using GeNN's spike timing sytem directly to binary file.
Definition: spikeRecorder.h:201
void recordSpikes(double t, unsigned int spikeCount, const unsigned int *currentSpikes)
Definition: spikeRecorder.h:120
SpikeRecorder(unsigned int batch, GetCurrentSpikesFunc getCurrentSpikes, GetCurrentSpikeCountFunc getCurrentSpikeCount, WriterArgs &&... writerArgs)
Definition: spikeRecorder.h:157
Class to read spikes from neuron groups.
Definition: spikeRecorder.h:150
void writeCache()
Definition: spikeRecorder.h:101
SpikeWriterTextCached(const std::string &filename, const std::string &delimiter=" ", bool header=false)
Definition: spikeRecorder.h:72
void record(double t)
Definition: spikeRecorder.h:176
void recordSpikes(double t, unsigned int spikeCount, const unsigned int *currentSpikes)
Definition: spikeRecorder.h:50
SpikeRecorder(GetCurrentSpikesFunc getCurrentSpikes, GetCurrentSpikeCountFunc getCurrentSpikeCount, WriterArgs &&... writerArgs)
Definition: spikeRecorder.h:165
SpikeWriterText(const std::string &filename, const std::string &delimiter=" ", bool header=false)
Definition: spikeRecorder.h:26
Class to write spikes to text file, caching in memory before writing.
Definition: spikeRecorder.h:69
int _clz(unsigned int value)
Definition: spikeRecorder.h:213
SpikeWriterText(SpikeWriterText &&other)
Definition: spikeRecorder.h:39
~SpikeWriterTextCached()
Definition: spikeRecorder.h:93
SpikeWriterTextCached(SpikeWriterTextCached &&other)
Definition: spikeRecorder.h:85
unsigned int getSum() const
Definition: spikeRecorder.h:183