.. _program_listing_file_include_libcaer_events_spike.h: Program Listing for File spike.h ================================ |exhale_lsh| :ref:`Return to documentation for file ` (``include/libcaer/events/spike.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef LIBCAER_EVENTS_SPIKE_H_ #define LIBCAER_EVENTS_SPIKE_H_ #include "common.h" #ifdef __cplusplus extern "C" { #endif #define SPIKE_SOURCE_CORE_ID_SHIFT 1 #define SPIKE_SOURCE_CORE_ID_MASK 0x0000001F #define SPIKE_CHIP_ID_SHIFT 6 #define SPIKE_CHIP_ID_MASK 0x0000003F #define SPIKE_NEURON_ID_SHIFT 12 #define SPIKE_NEURON_ID_MASK 0x000FFFFF PACKED_STRUCT(struct caer_spike_event { uint32_t data; int32_t timestamp; }); typedef struct caer_spike_event *caerSpikeEvent; typedef const struct caer_spike_event *caerSpikeEventConst; PACKED_STRUCT(struct caer_spike_event_packet { struct caer_event_packet_header packetHeader; struct caer_spike_event events[]; }); typedef struct caer_spike_event_packet *caerSpikeEventPacket; typedef const struct caer_spike_event_packet *caerSpikeEventPacketConst; static inline caerSpikeEventPacket caerSpikeEventPacketAllocate( int32_t eventCapacity, int16_t eventSource, int32_t tsOverflow) { return ((caerSpikeEventPacket) caerEventPacketAllocate(eventCapacity, eventSource, tsOverflow, SPIKE_EVENT, sizeof(struct caer_spike_event), offsetof(struct caer_spike_event, timestamp))); } static inline caerSpikeEventPacket caerSpikeEventPacketFromPacketHeader(caerEventPacketHeader header) { if (caerEventPacketHeaderGetEventType(header) != SPIKE_EVENT) { return (NULL); } return ((caerSpikeEventPacket) header); } static inline caerSpikeEventPacketConst caerSpikeEventPacketFromPacketHeaderConst(caerEventPacketHeaderConst header) { if (caerEventPacketHeaderGetEventType(header) != SPIKE_EVENT) { return (NULL); } return ((caerSpikeEventPacketConst) header); } static inline caerSpikeEvent caerSpikeEventPacketGetEvent(caerSpikeEventPacket packet, int32_t n) { // Check that we're not out of bounds. if (n < 0 || n >= caerEventPacketHeaderGetEventCapacity(&packet->packetHeader)) { caerLogEHO(CAER_LOG_CRITICAL, "Spike Event", "Called caerSpikeEventPacketGetEvent() with invalid event offset %" PRIi32 ", while maximum allowed value is %" PRIi32 ".", n, caerEventPacketHeaderGetEventCapacity(&packet->packetHeader) - 1); return (NULL); } // Return a pointer to the specified event. return (packet->events + n); } static inline caerSpikeEventConst caerSpikeEventPacketGetEventConst(caerSpikeEventPacketConst packet, int32_t n) { // Check that we're not out of bounds. if (n < 0 || n >= caerEventPacketHeaderGetEventCapacity(&packet->packetHeader)) { caerLogEHO(CAER_LOG_CRITICAL, "Spike Event", "Called caerSpikeEventPacketGetEventConst() with invalid event offset %" PRIi32 ", while maximum allowed value is %" PRIi32 ".", n, caerEventPacketHeaderGetEventCapacity(&packet->packetHeader) - 1); return (NULL); } // Return a pointer to the specified event. return (packet->events + n); } static inline int32_t caerSpikeEventGetTimestamp(caerSpikeEventConst event) { return (I32T(le32toh(U32T(event->timestamp)))); } static inline int64_t caerSpikeEventGetTimestamp64(caerSpikeEventConst event, caerSpikeEventPacketConst packet) { return (I64T((U64T(caerEventPacketHeaderGetEventTSOverflow(&packet->packetHeader)) << TS_OVERFLOW_SHIFT) | U64T(caerSpikeEventGetTimestamp(event)))); } static inline void caerSpikeEventSetTimestamp(caerSpikeEvent event, int32_t timestamp) { if (timestamp < 0) { // Negative means using the 31st bit! caerLogEHO(CAER_LOG_CRITICAL, "Spike Event", "Called caerSpikeEventSetTimestamp() with negative value!"); return; } event->timestamp = I32T(htole32(U32T(timestamp))); } static inline bool caerSpikeEventIsValid(caerSpikeEventConst event) { return (GET_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK)); } static inline void caerSpikeEventValidate(caerSpikeEvent event, caerSpikeEventPacket packet) { if (!caerSpikeEventIsValid(event)) { SET_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK, 1); // Also increase number of events and valid events. // Only call this on (still) invalid events! caerEventPacketHeaderSetEventNumber( &packet->packetHeader, caerEventPacketHeaderGetEventNumber(&packet->packetHeader) + 1); caerEventPacketHeaderSetEventValid( &packet->packetHeader, caerEventPacketHeaderGetEventValid(&packet->packetHeader) + 1); } else { caerLogEHO(CAER_LOG_CRITICAL, "Spike Event", "Called caerSpikeEventValidate() on already valid event."); } } static inline void caerSpikeEventInvalidate(caerSpikeEvent event, caerSpikeEventPacket packet) { if (caerSpikeEventIsValid(event)) { CLEAR_NUMBITS32(event->data, VALID_MARK_SHIFT, VALID_MARK_MASK); // Also decrease number of valid events. Number of total events doesn't change. // Only call this on valid events! caerEventPacketHeaderSetEventValid( &packet->packetHeader, caerEventPacketHeaderGetEventValid(&packet->packetHeader) - 1); } else { caerLogEHO(CAER_LOG_CRITICAL, "Spike Event", "Called caerSpikeEventInvalidate() on already invalid event."); } } static inline uint8_t caerSpikeEventGetSourceCoreID(caerSpikeEventConst event) { return U8T(GET_NUMBITS32(event->data, SPIKE_SOURCE_CORE_ID_SHIFT, SPIKE_SOURCE_CORE_ID_MASK)); } static inline void caerSpikeEventSetSourceCoreID(caerSpikeEvent event, uint8_t sourceCoreID) { CLEAR_NUMBITS32(event->data, SPIKE_SOURCE_CORE_ID_SHIFT, SPIKE_SOURCE_CORE_ID_MASK); SET_NUMBITS32(event->data, SPIKE_SOURCE_CORE_ID_SHIFT, SPIKE_SOURCE_CORE_ID_MASK, sourceCoreID); } static inline uint8_t caerSpikeEventGetChipID(caerSpikeEventConst event) { return U8T(GET_NUMBITS32(event->data, SPIKE_CHIP_ID_SHIFT, SPIKE_CHIP_ID_MASK)); } static inline void caerSpikeEventSetChipID(caerSpikeEvent event, uint8_t chipID) { CLEAR_NUMBITS32(event->data, SPIKE_CHIP_ID_SHIFT, SPIKE_CHIP_ID_MASK); SET_NUMBITS32(event->data, SPIKE_CHIP_ID_SHIFT, SPIKE_CHIP_ID_MASK, chipID); } static inline uint32_t caerSpikeEventGetNeuronID(caerSpikeEventConst event) { return U32T(GET_NUMBITS32(event->data, SPIKE_NEURON_ID_SHIFT, SPIKE_NEURON_ID_MASK)); } static inline void caerSpikeEventSetNeuronID(caerSpikeEvent event, uint32_t neuronID) { CLEAR_NUMBITS32(event->data, SPIKE_NEURON_ID_SHIFT, SPIKE_NEURON_ID_MASK); SET_NUMBITS32(event->data, SPIKE_NEURON_ID_SHIFT, SPIKE_NEURON_ID_MASK, neuronID); } #define CAER_SPIKE_ITERATOR_ALL_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = 0; \ caerSpikeIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader); \ caerSpikeIteratorCounter++) { \ caerSpikeEvent caerSpikeIteratorElement = caerSpikeEventPacketGetEvent(SPIKE_PACKET, caerSpikeIteratorCounter); #define CAER_SPIKE_CONST_ITERATOR_ALL_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = 0; \ caerSpikeIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader); \ caerSpikeIteratorCounter++) { \ caerSpikeEventConst caerSpikeIteratorElement \ = caerSpikeEventPacketGetEventConst(SPIKE_PACKET, caerSpikeIteratorCounter); #define CAER_SPIKE_ITERATOR_ALL_END } #define CAER_SPIKE_ITERATOR_VALID_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = 0; \ caerSpikeIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader); \ caerSpikeIteratorCounter++) { \ caerSpikeEvent caerSpikeIteratorElement \ = caerSpikeEventPacketGetEvent(SPIKE_PACKET, caerSpikeIteratorCounter); \ if (!caerSpikeEventIsValid(caerSpikeIteratorElement)) { \ continue; \ } // Skip invalid Spike events. #define CAER_SPIKE_CONST_ITERATOR_VALID_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = 0; \ caerSpikeIteratorCounter < caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader); \ caerSpikeIteratorCounter++) { \ caerSpikeEventConst caerSpikeIteratorElement \ = caerSpikeEventPacketGetEventConst(SPIKE_PACKET, caerSpikeIteratorCounter); \ if (!caerSpikeEventIsValid(caerSpikeIteratorElement)) { \ continue; \ } // Skip invalid Spike events. #define CAER_SPIKE_ITERATOR_VALID_END } #define CAER_SPIKE_REVERSE_ITERATOR_ALL_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader) - 1; \ caerSpikeIteratorCounter >= 0; caerSpikeIteratorCounter--) { \ caerSpikeEvent caerSpikeIteratorElement = caerSpikeEventPacketGetEvent(SPIKE_PACKET, caerSpikeIteratorCounter); #define CAER_SPIKE_CONST_REVERSE_ITERATOR_ALL_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader) - 1; \ caerSpikeIteratorCounter >= 0; caerSpikeIteratorCounter--) { \ caerSpikeEventConst caerSpikeIteratorElement \ = caerSpikeEventPacketGetEventConst(SPIKE_PACKET, caerSpikeIteratorCounter); #define CAER_SPIKE_REVERSE_ITERATOR_ALL_END } #define CAER_SPIKE_REVERSE_ITERATOR_VALID_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader) - 1; \ caerSpikeIteratorCounter >= 0; caerSpikeIteratorCounter--) { \ caerSpikeEvent caerSpikeIteratorElement \ = caerSpikeEventPacketGetEvent(SPIKE_PACKET, caerSpikeIteratorCounter); \ if (!caerSpikeEventIsValid(caerSpikeIteratorElement)) { \ continue; \ } // Skip invalid spike events. #define CAER_SPIKE_CONST_REVERSE_ITERATOR_VALID_START(SPIKE_PACKET) \ for (int32_t caerSpikeIteratorCounter = caerEventPacketHeaderGetEventNumber(&(SPIKE_PACKET)->packetHeader) - 1; \ caerSpikeIteratorCounter >= 0; caerSpikeIteratorCounter--) { \ caerSpikeEventConst caerSpikeIteratorElement \ = caerSpikeEventPacketGetEventConst(SPIKE_PACKET, caerSpikeIteratorCounter); \ if (!caerSpikeEventIsValid(caerSpikeIteratorElement)) { \ continue; \ } // Skip invalid spike events. #define CAER_SPIKE_REVERSE_ITERATOR_VALID_END } #ifdef __cplusplus } #endif #endif /* LIBCAER_EVENTS_SPIKE_H_ */