22 static_assert(std::numeric_limits<FwChanIdType>::max() >= TLMCHAN_HASH_BUCKETS,
23 "Cannot have more hash buckets than maximum telemetry ids in the system");
25 static_assert(std::numeric_limits<FwChanIdType>::max() >= TLMCHAN_NUM_TLM_HASH_SLOTS,
26 "Cannot have more hash slots than maximum telemetry ids in the system");
35 static_assert(TLMCHAN_MAX_ENTRIES_PER_RUN > 0,
"TLMCHAN_MAX_ENTRIES_PER_RUN must be greater than zero");
36 static_assert(TLMCHAN_MAX_ENTRIES_PER_RUN <= TLMCHAN_HASH_BUCKETS,
37 "TLMCHAN_MAX_ENTRIES_PER_RUN cannot exceed TLMCHAN_HASH_BUCKETS");
44 for (
FwChanIdType entry = 0; entry < TLMCHAN_NUM_TLM_HASH_SLOTS; entry++) {
45 this->m_tlmEntries[0].slots[entry] =
nullptr;
46 this->m_tlmEntries[1].slots[entry] =
nullptr;
49 for (
FwChanIdType entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
50 this->m_tlmEntries[0].buckets[entry].used =
false;
51 this->m_tlmEntries[0].buckets[entry].updated =
false;
52 this->m_tlmEntries[0].buckets[entry].bucketNo = entry;
53 this->m_tlmEntries[0].buckets[entry].next =
nullptr;
54 this->m_tlmEntries[0].buckets[entry].id = 0;
55 this->m_tlmEntries[1].buckets[entry].used =
false;
56 this->m_tlmEntries[1].buckets[entry].updated =
false;
57 this->m_tlmEntries[1].buckets[entry].bucketNo = entry;
58 this->m_tlmEntries[1].buckets[entry].next =
nullptr;
59 this->m_tlmEntries[1].buckets[entry].id = 0;
62 this->m_tlmEntries[0].free = 0;
63 this->m_tlmEntries[1].free = 0;
66 this->m_chanIdSize =
static_cast<U32
>(
sizeof(
FwChanIdType));
79 for (U32 i = 0; i < static_cast<U32>(serBuf.
getSize()); i++) {
81 foldedTime = (foldedTime << 8) | (foldedTime >> 24);
82 foldedTime ^=
static_cast<U32
>(timeBuf[i]);
86 const U64 raw =
reinterpret_cast<U64>(&seed);
87 const U32 foldedStack =
static_cast<U32
>(raw ^ (raw >> 32));
89 seed = foldedTime ^ foldedStack;
102 this->m_hashSeed = seed;
109 static_assert(std::is_unsigned<FwChanIdType>::value,
"FwChanIdType must be unsigned");
110 static_assert(
sizeof(
FwChanIdType) <=
sizeof(U32),
"FwChanIdType must fit within U32 for safe hash cast");
111 static_assert(TLMCHAN_NUM_TLM_HASH_SLOTS > 0,
"TLMCHAN_NUM_TLM_HASH_SLOTS must be greater than zero");
115 if (this->m_chanIdSize >= 4) {
117 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U32>::max()), static_cast<FwAssertArgType>(
id));
119 U32 h =
static_cast<U32
>(id) ^ static_cast<U32>(this->m_hashSeed);
128 result =
static_cast<FwChanIdType>(h % TLMCHAN_NUM_TLM_HASH_SLOTS);
129 }
else if (this->m_chanIdSize == 2) {
131 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U16>::max()), static_cast<FwAssertArgType>(
id));
133 U16 h = (
static_cast<U16
>(id)) ^ (
static_cast<U16
>(this->m_hashSeed) & static_cast<U16>(0xFFFFU));
136 h =
static_cast<U16
>(h ^ (h >> 7));
137 h =
static_cast<U16
>(h * WANG16_C1);
138 h =
static_cast<U16
>(h ^ (h >> 5));
139 h =
static_cast<U16
>(h * WANG16_C2);
140 h =
static_cast<U16
>(h ^ (h >> 3));
142 result =
static_cast<FwChanIdType>(h % TLMCHAN_NUM_TLM_HASH_SLOTS);
145 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U8>::max()), static_cast<FwAssertArgType>(
id));
149 const U8 h =
static_cast<U8>(id) ^ (static_cast<U8>(this->m_hashSeed) &
static_cast<U8>(0xFFU));
150 result =
static_cast<FwChanIdType>((h % TLMCHAN_HASH_MOD_VALUE) % TLMCHAN_NUM_TLM_HASH_SLOTS);
155 void TlmChan::pingIn_handler(
const FwIndexType portNum, U32 key) {
168 TlmEntry* activeEntry = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
169 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
171 if (activeEntry->id ==
id) {
174 activeEntry = activeEntry->next;
181 TlmEntry* inactiveEntry = this->m_tlmEntries[1 -
static_cast<U8>(this->m_activeBuffer)].slots[index];
182 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
184 if (inactiveEntry->id ==
id) {
187 inactiveEntry = inactiveEntry->next;
194 if (activeEntry && inactiveEntry) {
197 val = inactiveEntry->buffer;
198 timeTag = inactiveEntry->lastUpdate;
201 val = activeEntry->buffer;
202 timeTag = activeEntry->lastUpdate;
205 if (inactiveEntry->updated) {
206 val = inactiveEntry->buffer;
207 timeTag = inactiveEntry->lastUpdate;
210 val = activeEntry->buffer;
211 timeTag = activeEntry->lastUpdate;
215 }
else if (activeEntry) {
216 val = activeEntry->buffer;
217 timeTag = activeEntry->lastUpdate;
219 }
else if (inactiveEntry) {
220 val = inactiveEntry->buffer;
221 timeTag = inactiveEntry->lastUpdate;
232 TlmEntry* entryToUse =
nullptr;
233 TlmEntry* prevEntry =
nullptr;
236 if (this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].slots[index]) {
237 entryToUse = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
239 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS + 1; bucket++) {
241 if (entryToUse->id ==
id) {
244 prevEntry = entryToUse;
245 entryToUse = entryToUse->next;
249 FW_ASSERT(this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free < TLMCHAN_HASH_BUCKETS);
251 entryToUse = &this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)]
252 .buckets[this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free++];
254 prevEntry->next = entryToUse;
255 entryToUse->next =
nullptr;
260 FW_ASSERT(this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free < TLMCHAN_HASH_BUCKETS);
261 this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index] =
262 &this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)]
263 .buckets[this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].free++];
264 entryToUse = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
265 entryToUse->next =
nullptr;
269 entryToUse->used =
true;
271 entryToUse->updated =
true;
272 entryToUse->lastUpdate = timeTag;
273 entryToUse->buffer = val;
276 void TlmChan::Run_handler(
FwIndexType portNum, U32 context) {
286 this->m_activeBuffer =
287 (this->m_activeBuffer == ActiveBuffer::Buffer_0) ? ActiveBuffer::Buffer_1 : ActiveBuffer::Buffer_0;
293 for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
294 this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].buckets[entry].updated =
false;
308 U32 entriesProcessed = 0;
309 U32 entriesDeferred = 0;
314 for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
315 TlmEntry* p_entry = &this->m_tlmEntries[1 -
static_cast<U8>(this->m_activeBuffer)].buckets[entry];
316 if ((p_entry->updated) && (p_entry->used)) {
327 if (entriesProcessed >= TLMCHAN_MAX_ENTRIES_PER_RUN) {
337 stat = pkt.
addValue(p_entry->id, p_entry->lastUpdate, p_entry->buffer);
344 FW_ASSERT(0, static_cast<FwAssertArgType>(stat));
347 p_entry->updated =
false;
360 if (entriesDeferred > 0) {
361 this->m_procCapCount++;
Serialization/Deserialization operation was successful.
Serializable::SizeType getSize() const override
Get current buffer size.
TlmChan(const char *compName)
No room left in the buffer to serialize data.
bool isConnected_PktSend_OutputPort(FwIndexType portNum) const
Status now() override
Get the current time.
Fw::ComBuffer & getBuffer()
get buffer to send to the ground
Auto-generated base for TlmChan component.
Component that stores telemetry channel values.
FwSizeType getNumEntries()
get the number of packets added via addValue()
SerializeStatus
forward declaration for string
SerializeStatus addValue(FwChanIdType id, Time &timeTag, TlmBuffer &buffer)
Add telemetry value to buffer.
void PktSend_out(FwIndexType portNum, Fw::ComBuffer &data, U32 context) const
Invoke output port PktSend.
virtual void lock()
Lock the guarded mutex.
void pingOut_out(FwIndexType portNum, U32 key) const
Invoke output port pingOut.
External serialize buffer with no copy semantics.
FwIdType FwChanIdType
The type of a telemetry channel identifier.
SerializeStatus resetPktSer()
Reset serialization of values. This should be done when starting to accumulate a new set of values...
void log_WARNING_HI_TlmChanEpochProcessingCapReached(U32 numDeferred, U32 numTimesDeferredCountReached) const
void resetSer() override
Reset serialization pointer to beginning of buffer.
uint8_t U8
8-bit unsigned integer
static TimeComparison compare(const Time &time1, const Time &time2)
Fw::SerializeStatus serializeTo(Fw::SerialBufferBase &buffer, Fw::Endianness mode=Fw::Endianness::BIG) const override
Serialize the contents of the RawTimeInterface object into a buffer.
PlatformIndexType FwIndexType
virtual void unLock()
Unlock the guarded mutex.
RateGroupDivider component implementation.
FwChanIdType doHash(FwChanIdType id) const