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 const U32 timeSize =
static_cast<U32
>(serBuf.
getSize());
80 for (U32 i = 0; i < timeSize; i++) {
82 foldedTime = (foldedTime << 8) | (foldedTime >> 24);
83 foldedTime ^=
static_cast<U32
>(timeBuf[i]);
87 const U64 raw =
reinterpret_cast<U64
>(&seed);
88 const U32 foldedStack =
static_cast<U32
>(raw ^ (raw >> 32));
90 seed = foldedTime ^ foldedStack;
103 this->m_hashSeed = seed;
110 static_assert(std::is_unsigned<FwChanIdType>::value,
"FwChanIdType must be unsigned");
111 static_assert(
sizeof(
FwChanIdType) <=
sizeof(U32),
"FwChanIdType must fit within U32 for safe hash cast");
112 static_assert(TLMCHAN_NUM_TLM_HASH_SLOTS > 0,
"TLMCHAN_NUM_TLM_HASH_SLOTS must be greater than zero");
116 if (this->m_chanIdSize >= 4) {
118 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U32>::max()), static_cast<FwAssertArgType>(
id));
120 U32 h =
static_cast<U32
>(id) ^ static_cast<U32>(this->m_hashSeed);
129 result =
static_cast<FwChanIdType>(h % TLMCHAN_NUM_TLM_HASH_SLOTS);
130 }
else if (this->m_chanIdSize == 2) {
132 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U16>::max()), static_cast<FwAssertArgType>(
id));
134 U16 h = (
static_cast<U16
>(id)) ^ (
static_cast<U16
>(this->m_hashSeed) & static_cast<U16>(0xFFFFU));
137 h =
static_cast<U16
>(h ^ (h >> 7));
138 h =
static_cast<U16
>(h * WANG16_C1);
139 h =
static_cast<U16
>(h ^ (h >> 5));
140 h =
static_cast<U16
>(h * WANG16_C2);
141 h =
static_cast<U16
>(h ^ (h >> 3));
143 result =
static_cast<FwChanIdType>(h % TLMCHAN_NUM_TLM_HASH_SLOTS);
146 FW_ASSERT(
id <= static_cast<FwChanIdType>(std::numeric_limits<U8>::max()), static_cast<FwAssertArgType>(
id));
150 const U8 h =
static_cast<U8>(id) ^ (static_cast<U8>(this->m_hashSeed) &
static_cast<U8>(0xFFU));
151 result =
static_cast<FwChanIdType>((h % TLMCHAN_HASH_MOD_VALUE) % TLMCHAN_NUM_TLM_HASH_SLOTS);
156 void TlmChan::pingIn_handler(
const FwIndexType portNum, U32 key) {
169 TlmEntry* activeEntry = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
170 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
172 if (activeEntry->id ==
id) {
175 activeEntry = activeEntry->next;
182 TlmEntry* inactiveEntry = this->m_tlmEntries[1 -
static_cast<U8>(this->m_activeBuffer)].slots[index];
183 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS; bucket++) {
185 if (inactiveEntry->id ==
id) {
188 inactiveEntry = inactiveEntry->next;
195 if (activeEntry && inactiveEntry) {
198 val = inactiveEntry->buffer;
199 timeTag = inactiveEntry->lastUpdate;
202 val = activeEntry->buffer;
203 timeTag = activeEntry->lastUpdate;
206 if (inactiveEntry->updated) {
207 val = inactiveEntry->buffer;
208 timeTag = inactiveEntry->lastUpdate;
211 val = activeEntry->buffer;
212 timeTag = activeEntry->lastUpdate;
216 }
else if (activeEntry) {
217 val = activeEntry->buffer;
218 timeTag = activeEntry->lastUpdate;
220 }
else if (inactiveEntry) {
221 val = inactiveEntry->buffer;
222 timeTag = inactiveEntry->lastUpdate;
233 TlmEntry* entryToUse =
nullptr;
234 TlmEntry* prevEntry =
nullptr;
237 if (this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].slots[index]) {
238 entryToUse = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
240 for (
FwChanIdType bucket = 0; bucket < TLMCHAN_HASH_BUCKETS + 1; bucket++) {
242 if (entryToUse->id ==
id) {
245 prevEntry = entryToUse;
246 entryToUse = entryToUse->next;
251 if (this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free >= TLMCHAN_HASH_BUCKETS) {
256 entryToUse = &this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)]
257 .buckets[this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free++];
259 prevEntry->next = entryToUse;
260 entryToUse->next =
nullptr;
267 if (this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)].free >= TLMCHAN_HASH_BUCKETS) {
271 this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index] =
272 &this->m_tlmEntries[static_cast<U8>(this->m_activeBuffer)]
273 .buckets[this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].free++];
274 entryToUse = this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].slots[index];
275 entryToUse->next =
nullptr;
279 entryToUse->used =
true;
281 entryToUse->updated =
true;
282 entryToUse->lastUpdate = timeTag;
283 entryToUse->buffer = val;
286 void TlmChan::Run_handler(
FwIndexType portNum, U32 context) {
296 this->m_activeBuffer =
297 (this->m_activeBuffer == ActiveBuffer::Buffer_0) ? ActiveBuffer::Buffer_1 : ActiveBuffer::Buffer_0;
303 for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
304 this->m_tlmEntries[
static_cast<U8>(this->m_activeBuffer)].buckets[entry].updated =
false;
318 U32 entriesProcessed = 0;
319 U32 entriesDeferred = 0;
325 for (U32 entry = 0; entry < TLMCHAN_HASH_BUCKETS; entry++) {
326 TlmEntry* p_entry = &this->m_tlmEntries[1 -
static_cast<U8>(this->m_activeBuffer)].buckets[entry];
327 if ((p_entry->updated) && (p_entry->used)) {
338 if (entriesProcessed >= TLMCHAN_MAX_ENTRIES_PER_RUN) {
349 stat = pkt.
addValue(p_entry->id, p_entry->lastUpdate, p_entry->buffer);
356 FW_ASSERT(
false, static_cast<FwAssertArgType>(stat));
360 p_entry->updated =
false;
374 if (entriesDeferred > 0) {
375 this->m_procCapCount++;
Serialization/Deserialization operation was successful.
Serializable::SizeType getSize() const override
Get current buffer size.
Status now() override
Get the current time.
TlmChan(const char *compName)
No room left in the buffer to serialize data.
bool isConnected_PktSend_OutputPort(FwIndexType portNum) const
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
void log_WARNING_HI_TlmChanBucketPoolExhausted(FwChanIdType Id)