GCC Code Coverage Report


Directory: Svc/ActiveRateGroup/
File: ActiveRateGroup.cpp
Date: 2026-11-03 21:17:39
Exec Total Coverage
Lines: 46 55 83.6%
Functions: 7 8 87.5%
Branches: 24 32 75.0%

Line Branch Exec Source
1 /*
2 * \author: Tim Canham
3 * \file:
4 * \brief
5 *
6 * This file implements the ActiveRateGroup component,
7 * which invokes a set of components the comprise the rate group.
8 *
9 * Copyright 2014-2015, by the California Institute of Technology.
10 * ALL RIGHTS RESERVED. United States Government Sponsorship
11 * acknowledged.
12 *
13 */
14
15 #include <Fw/FPrimeBasicTypes.hpp>
16 #include <Fw/Types/Assert.hpp>
17 #include <Os/Console.hpp>
18 #include <Svc/ActiveRateGroup/ActiveRateGroup.hpp>
19 #include <config/ActiveRateGroupCfg.hpp>
20
21 namespace Svc {
22
23 // The cycle-started flag is stored from the cycle caller's thread, which may be interrupt context;
24 // a std::atomic implemented with a hidden lock would not be safe there.
25 static_assert(ATOMIC_BOOL_LOCK_FREE == 2, "std::atomic<bool> must be lock-free for the cycle-started flag");
26
27 8 ActiveRateGroup::ActiveRateGroup(const char* compName)
28 : ActiveRateGroupComponentBase(compName),
29 8 m_cycles(0),
30 8 m_maxTime(0),
31 8 m_cycleStarted(false),
32 8 m_numContexts(0),
33 8 m_overrunThrottle(0),
34 16 m_cycleSlips(0) {}
35
36 8 void ActiveRateGroup::configure(const ContextArray& contexts) {
37 static_assert(FW_NUM_ARRAY_ELEMENTS(m_contexts) == NUM_RATEGROUPMEMBEROUT_OUTPUT_PORTS,
38 "Context table size must match the number of rate group member output ports");
39
40 8 this->m_numContexts = CONNECTION_COUNT_MAX;
41 // copy context values
42
2/2
✓ Branch 4 taken 80 times.
✓ Branch 5 taken 8 times.
88 for (FwIndexType entry = 0; entry < this->m_numContexts; entry++) {
43 80 this->m_contexts[entry] = contexts[static_cast<FwSizeType>(entry)];
44 }
45 8 }
46
47 ✗ void ActiveRateGroup::configure(const U32 contexts[], const FwIndexType numContexts) {
48 ✗ FW_ASSERT(contexts != nullptr);
49 ✗ FW_ASSERT(numContexts == this->getNum_RateGroupMemberOut_OutputPorts(), static_cast<FwAssertArgType>(numContexts),
50 static_cast<FwAssertArgType>(this->getNum_RateGroupMemberOut_OutputPorts()));
51
52 ✗ ContextArray contextArray;
53 ✗ for (FwIndexType entry = 0; entry < numContexts; entry++) {
54 ✗ contextArray[static_cast<FwSizeType>(entry)] = contexts[entry];
55 }
56 ✗ this->configure(contextArray);
57 ✗ }
58
59 16 ActiveRateGroup::~ActiveRateGroup() {}
60
61 6 void ActiveRateGroup::preamble() {
62 6 this->log_DIAGNOSTIC_RateGroupStarted();
63 6 }
64
65 29 void ActiveRateGroup::CycleIn_handler(FwIndexType portNum, Os::RawTime& cycleStart) {
66 // Make sure it's been configured
67 29 FW_ASSERT(this->m_numContexts != 0);
68
69
1/1
✓ Branch 2 taken 29 times.
29 Os::RawTime endTime;
70
71 // Clear the flag set by this cycle's CycleIn_preMsgHook. A cycle message whose hook ran
72 // between the dequeue and this store is coalesced with this cycle: one slip per delay.
73 29 this->m_cycleStarted.store(false, std::memory_order_relaxed);
74
75 // invoke any members of the rate group
76
2/2
✓ Branch 4 taken 290 times.
✓ Branch 5 taken 29 times.
319 for (FwIndexType port = 0; port < this->m_numContexts; port++) {
77
2/3
✓ Branch 5 taken 290 times.
✓ Branch 7 taken 290 times.
✗ Branch 8 not taken.
290 if (this->isConnected_RateGroupMemberOut_OutputPort(port)) {
78
1/1
✓ Branch 10 taken 290 times.
290 this->RateGroupMemberOut_out(port, static_cast<U32>(this->m_contexts[port]));
79 }
80 }
81
82 // grab timer for endTime of cycle
83
1/1
✓ Branch 2 taken 29 times.
29 Os::RawTime::Status timeStatus = endTime.now();
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (timeStatus != Os::RawTime::Status::OP_OK) {
85 ✗ this->log_WARNING_HI_RateGroupTimeGetError(Os::RawTimeStatus(static_cast<Os::RawTimeStatus::T>(timeStatus)));
86 }
87
88 // get rate group execution time
89 29 U32 cycleTime;
90 // Cast to void as the only possible error is overflow, which we can't handle other
91 // than capping cycleTime to max value of U32 (which is done in getDiffUsec anyways)
92
1/1
✓ Branch 3 taken 29 times.
29 (void)endTime.getDiffUsec(cycleStart, cycleTime);
93
94 // check to see if the time has exceeded the previous maximum
95
2/2
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 22 times.
29 if (cycleTime > this->m_maxTime) {
96 7 this->m_maxTime = cycleTime;
97 }
98
99 // update cycle telemetry
100
2/2
✓ Branch 6 taken 29 times.
✓ Branch 13 taken 29 times.
29 this->tlmWrite_RgMaxTime(this->m_maxTime);
101
102 // check for cycle slip. That will happen if new cycle message has been received
103 // which will cause flag will be set again.
104
2/2
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 7 times.
29 if (this->m_cycleStarted.load(std::memory_order_relaxed)) {
105 22 this->m_cycleSlips++;
106
2/2
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 3 times.
22 if (this->m_overrunThrottle < ACTIVE_RATE_GROUP_OVERRUN_THROTTLE) {
107
1/1
✓ Branch 9 taken 19 times.
19 this->log_WARNING_HI_RateGroupCycleSlip(this->m_cycles);
108 19 this->m_overrunThrottle++;
109 }
110 // update cycle slips
111
2/2
✓ Branch 6 taken 22 times.
✓ Branch 13 taken 22 times.
22 this->tlmWrite_RgCycleSlips(this->m_cycleSlips);
112 } else { // if cycle is okay start decrementing throttle value
113
2/2
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3 times.
7 if (this->m_overrunThrottle > 0) {
114 4 this->m_overrunThrottle--;
115 }
116 }
117
118 // increment cycle
119 29 this->m_cycles++;
120 58 }
121
122 50 void ActiveRateGroup::CycleIn_preMsgHook(FwIndexType portNum, Os::RawTime& cycleStart) {
123 // set flag to indicate cycle has started. Check in thread for overflow.
124 50 this->m_cycleStarted.store(true, std::memory_order_relaxed);
125 50 }
126
127 1 void ActiveRateGroup::PingIn_handler(FwIndexType portNum, U32 key) {
128 // return the key to health
129 1 this->PingOut_out(0, key);
130 1 }
131
132 } // namespace Svc
133