GCC Code Coverage Report


Directory: Svc/PassiveRateGroup/
File: PassiveRateGroup.cpp
Date: 2026-09-03 21:18:16
Exec Total Coverage
Lines: 60 68 88.2%
Functions: 6 7 85.7%
Branches: 42 50 84.0%

Line Branch Exec Source
1 /*
2 * \author: Tim Canham
3 * \file:
4 * \brief
5 *
6 * This file implements the PassiveRateGroup 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 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <Fw/Types/Assert.hpp>
16 #include <Os/Console.hpp>
17 #include <Svc/PassiveRateGroup/PassiveRateGroup.hpp>
18 #include <config/PassiveRateGroupCfg.hpp>
19 #include "config/FwSizeTypeAliasAc.h"
20
21 namespace Svc {
22 6 PassiveRateGroup::PassiveRateGroup(const char* compName)
23 : PassiveRateGroupComponentBase(compName),
24 6 m_cycles(0),
25 6 m_maxTime(0),
26 6 m_portCycleTimeHWMUsec{}, // Zero-initialize atomic array
27 6 m_rawTimeSource(Os::RAWTIME_DEFAULT),
28 12 m_numContexts(0) {}
29
30 12 PassiveRateGroup::~PassiveRateGroup() {}
31
32 46 Os::RawTime PassiveRateGroup::createRawTime() const {
33
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
46 return Os::RawTime(this->m_rawTimeSource);
34 }
35
36 6 void PassiveRateGroup::configure(const ContextArray& contexts, const Os::RawTimeSource rawTimeSource) {
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 6 this->m_numContexts = CONNECTION_COUNT_MAX;
41 // copy context values
42
2/2
✓ Branch 4 taken 60 times.
✓ Branch 5 taken 6 times.
66 for (FwIndexType entry = 0; entry < this->m_numContexts; entry++) {
43 60 this->m_contexts[entry] = contexts[static_cast<FwSizeType>(entry)];
44 }
45
46 6 this->m_rawTimeSource = rawTimeSource;
47 6 }
48
49 void PassiveRateGroup::configure(const U32 contexts[], const FwIndexType numContexts) {
50 FW_ASSERT(contexts != nullptr);
51 FW_ASSERT(numContexts == this->getNum_RateGroupMemberOut_OutputPorts(), static_cast<FwAssertArgType>(numContexts),
52 static_cast<FwAssertArgType>(this->getNum_RateGroupMemberOut_OutputPorts()));
53
54 ContextArray contextArray;
55 for (FwIndexType entry = 0; entry < numContexts; entry++) {
56 contextArray[static_cast<FwSizeType>(entry)] = static_cast<U32>(contexts[entry]);
57 }
58 this->configure(contextArray);
59 }
60
61 15 void PassiveRateGroup::CycleIn_handler(FwIndexType portNum, Os::RawTime& cycleStart) {
62
1/1
✓ Branch 2 taken 15 times.
15 Os::RawTime endTime = this->createRawTime();
63 15 FW_ASSERT(this->m_numContexts != 0);
64
65 // Pre-allocate RawTime objects outside loop to avoid repeated constructor calls
66
1/1
✓ Branch 2 taken 15 times.
15 Os::RawTime portStart = this->createRawTime();
67
1/1
✓ Branch 2 taken 15 times.
15 Os::RawTime portEnd = this->createRawTime();
68
1/1
✓ Branch 2 taken 15 times.
15 PassiveRateGroup_CycleTime portTimes;
69
70 // invoke any members of the rate group
71
2/2
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 15 times.
165 for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
72
2/3
✓ Branch 5 taken 150 times.
✓ Branch 7 taken 150 times.
✗ Branch 8 not taken.
150 if (this->isConnected_RateGroupMemberOut_OutputPort(port)) {
73 if (Svc::PassiveRateGroupCfg::PortCycleTime) {
74
1/1
✓ Branch 2 taken 150 times.
150 (void)portStart.now();
75 }
76
77
1/1
✓ Branch 9 taken 150 times.
150 this->RateGroupMemberOut_out(port, this->m_contexts[port]);
78
79 if (Svc::PassiveRateGroupCfg::PortCycleTime) {
80
1/1
✓ Branch 2 taken 150 times.
150 (void)portEnd.now();
81 150 U32 cycleTime;
82
1/1
✓ Branch 2 taken 150 times.
150 (void)portEnd.getDiffUsec(portStart, cycleTime);
83
1/1
✓ Branch 2 taken 150 times.
150 portTimes[static_cast<FwSizeType>(port)] = cycleTime;
84 // Update high water mark if current cycle time exceeds it (lock-free atomic)
85 150 U32 currentHWM =
86 150 this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].load(std::memory_order_relaxed);
87
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 71 times.
150 while (cycleTime > currentHWM) {
88
1/2
✓ Branch 5 taken 79 times.
✗ Branch 6 not taken.
158 if (this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].compare_exchange_weak(
89 currentHWM, cycleTime, std::memory_order_relaxed)) {
90 79 break;
91 }
92 }
93 }
94 }
95 }
96
97 // grab timer for endTime of cycle
98
1/1
✓ Branch 2 taken 15 times.
15 (void)endTime.now();
99
100 // get rate group execution time
101 15 U32 cycleTime;
102 // Cast to void as the only possible error is overflow, which we can't handle other
103 // than capping cycleTime to max value of U32 (which is done in getDiffUsec anyways)
104
1/1
✓ Branch 3 taken 15 times.
15 (void)endTime.getDiffUsec(cycleStart, cycleTime);
105
106 // Update max time atomically (lock-free, ISR-safe)
107 15 U32 currentMax = this->m_maxTime.load(std::memory_order_relaxed);
108
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
15 while (cycleTime > currentMax) {
109
1/2
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 if (this->m_maxTime.compare_exchange_weak(currentMax, cycleTime, std::memory_order_relaxed)) {
110 8 break;
111 }
112 }
113
114 15 U32 maxTime = this->m_maxTime.load(std::memory_order_relaxed);
115 15 U32 cycles = ++this->m_cycles;
116
117 if (Svc::PassiveRateGroupCfg::PortCycleTime) {
118 // Copy atomic array to telemetry structure for sending
119
1/1
✓ Branch 2 taken 15 times.
15 PassiveRateGroup_CycleTime portCycleTimeHWM;
120
2/2
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 15 times.
165 for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
121
1/1
✓ Branch 2 taken 150 times.
300 portCycleTimeHWM[static_cast<FwSizeType>(port)] =
122 300 this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].load(std::memory_order_relaxed);
123 }
124
2/2
✓ Branch 6 taken 15 times.
✓ Branch 9 taken 15 times.
15 this->tlmWrite_PortCycleTime(portTimes);
125
2/2
✓ Branch 6 taken 15 times.
✓ Branch 9 taken 15 times.
15 this->tlmWrite_PortCycleTimeHWM(portCycleTimeHWM);
126 15 }
127
128
2/2
✓ Branch 6 taken 15 times.
✓ Branch 9 taken 15 times.
15 this->tlmWrite_MaxCycleTime(maxTime);
129
2/2
✓ Branch 6 taken 15 times.
✓ Branch 9 taken 15 times.
15 this->tlmWrite_CycleTime(cycleTime);
130
2/2
✓ Branch 6 taken 15 times.
✓ Branch 9 taken 15 times.
15 this->tlmWrite_CycleCount(cycles);
131 30 }
132
133 1 void PassiveRateGroup::CLEAR_STATISTICS_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
134 // Clear max cycle time (lock-free atomic)
135 1 this->m_maxTime.store(0, std::memory_order_relaxed);
136 // Note: m_cycles is intentionally NOT cleared - it's a running total
137
138 // Clear all port cycle time high water marks (lock-free atomic)
139
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 times.
11 for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
140 10 this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].store(0, std::memory_order_relaxed);
141 }
142
143
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
144 1 }
145
146 } // namespace Svc
147