| 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 77 times.
✓ Branch 1 taken 73 times.
|
150 | while (cycleTime > currentHWM) { |
| 88 |
1/2✓ Branch 5 taken 77 times.
✗ Branch 6 not taken.
|
154 | if (this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].compare_exchange_weak( |
| 89 | currentHWM, cycleTime, std::memory_order_relaxed)) { | ||
| 90 | 77 | 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 10 times.
✓ Branch 1 taken 5 times.
|
15 | while (cycleTime > currentMax) { |
| 109 |
1/2✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | if (this->m_maxTime.compare_exchange_weak(currentMax, cycleTime, std::memory_order_relaxed)) { |
| 110 | 10 | 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 |