Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update/passive rg #2051

Merged
merged 11 commits into from
May 30, 2023
2 changes: 2 additions & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,8 @@ params
PARENB
PARODD
parseable
PASSIVERATEGROUP
PASSIVERATEGROUPIMPLTESTER
pathlib
pathmaker
pbuild
Expand Down
1 change: 1 addition & 0 deletions Svc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/GroundInterface/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Framer/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FramingProtocol/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Health/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/PassiveRateGroup")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/PolyDb/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/PrmDb/")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RateGroupDriver/")
Expand Down
29 changes: 29 additions & 0 deletions Svc/PassiveRateGroup/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#### CMakeLists.txt PassiveRateGroup ####

# Specifies the sources for this module with optional sources included by platform
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/PassiveRateGroup.cpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveRateGroup.hpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveRateGroup.fpp"
)


# Specifies any module dependencies not detectable via the model file dependency detection
#set(MOD_DEPS ...)

# Registers this module with the fprime build system
register_fprime_module()

# Specifies the sources specifically associated with unit tests in this module
set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/test/ut/PassiveRateGroupTester.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/PassiveRateGroupImplTester.cpp"
"${CMAKE_CURRENT_LIST_DIR}/PassiveRateGroup.fpp"
)


# Specifies any unit test modules
#set(UT_MOD_DEPS ...)

# Registers this module with the fprime build system
register_fprime_ut()
67 changes: 67 additions & 0 deletions Svc/PassiveRateGroup/PassiveRateGroup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* \author: Tim Canham
* \file:
* \brief
*
* This file implements the PassiveRateGroup component,
* which invokes a set of components the comprise the rate group.
*
* Copyright 2014-2015, by the California Institute of Technology.
* ALL RIGHTS RESERVED. United States Government Sponsorship
* acknowledged.
*/

#include <FpConfig.hpp>
#include <Fw/Types/Assert.hpp>
#include <Os/Log.hpp>
#include <Svc/PassiveRateGroup/PassiveRateGroup.hpp>

namespace Svc {
PassiveRateGroup::PassiveRateGroup(const char* compName)

Check notice

Code scanning / CodeQL

Use of basic integral type

compName uses the basic integral type char rather than a typedef with size and signedness.
: PassiveRateGroupComponentBase(compName), m_cycles(0), m_maxTime(0), m_numContexts(0) {
}

PassiveRateGroup::~PassiveRateGroup() {}

Check notice

Code scanning / CodeQL

More than one statement per line

This line contains 2 statements; only one is allowed.

void PassiveRateGroup::configure(NATIVE_INT_TYPE contexts[], NATIVE_INT_TYPE numContexts) {

Check notice

Code scanning / CodeQL

Use of basic integral type

contexts uses the basic integral type int rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Use of basic integral type

numContexts uses the basic integral type int rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Long function without assertion

All functions of more than 10 lines should have at least one assertion.

Check notice

Code scanning / CodeQL

No raw arrays in interfaces

Raw arrays should not be used in interfaces. A container class should be used instead.
FW_ASSERT(contexts);
FW_ASSERT(numContexts == this->getNum_RateGroupMemberOut_OutputPorts(),numContexts,this->getNum_RateGroupMemberOut_OutputPorts());
FW_ASSERT(FW_NUM_ARRAY_ELEMENTS(this->m_contexts) == this->getNum_RateGroupMemberOut_OutputPorts(),
FW_NUM_ARRAY_ELEMENTS(this->m_contexts),
this->getNum_RateGroupMemberOut_OutputPorts());

this->m_numContexts = numContexts;
// copy context values
for (NATIVE_INT_TYPE entry = 0; entry < this->m_numContexts; entry++) {

Check notice

Code scanning / CodeQL

Use of basic integral type

entry uses the basic integral type int rather than a typedef with size and signedness.
this->m_contexts[entry] = contexts[entry];
}
}


void PassiveRateGroup::CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart) {

Check notice

Code scanning / CodeQL

Use of basic integral type

portNum uses the basic integral type int rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Long function without assertion

All functions of more than 10 lines should have at least one assertion.
TimerVal end;
FW_ASSERT(this->m_numContexts);

// invoke any members of the rate group
for (NATIVE_INT_TYPE port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {

Check notice

Code scanning / CodeQL

Use of basic integral type

port uses the basic integral type int rather than a typedef with size and signedness.
if (this->isConnected_RateGroupMemberOut_OutputPort(port)) {
this->RateGroupMemberOut_out(port, this->m_contexts[port]);
}
}
Comment on lines +46 to +50

Check warning

Code scanning / CodeQL

Unbounded loop

This loop does not have a fixed bound.

// grab timer for end of cycle
end.take();

// get rate group execution time
U32 cycle_time = end.diffUSec(cycleStart);

Check warning

Code scanning / CodeQL

Unchecked function argument

This use of parameter cycleStart has not been checked.

// check to see if the time has exceeded the previous maximum
if (cycle_time > this->m_maxTime) {
this->m_maxTime = cycle_time;
}
this->tlmWrite_MaxCycleTime(this->m_maxTime);
this->tlmWrite_CycleTime(cycle_time);
this->tlmWrite_CycleCount(++this->m_cycles);
}

} // namespace Svc
30 changes: 30 additions & 0 deletions Svc/PassiveRateGroup/PassiveRateGroup.fpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Svc {

@ A rate group passive component with input and output scheduler ports
passive component PassiveRateGroup {

@ The rate group cycle input
sync input port CycleIn: Cycle

@ Scheduler output port to rate group members
output port RateGroupMemberOut: [PassiveRateGroupOutputPorts] Sched

@ Max execution time of rate group cycle
telemetry MaxCycleTime: U32 update on change format "{} us"

@ Execution time of current cycle
telemetry CycleTime: U32 format "{} us"

@ Count of number of cycles
telemetry CycleCount: U32

# Standard ports
@ A port for getting the time
time get port Time

@ A port for emitting telemetry
telemetry port Tlm

}

}
75 changes: 75 additions & 0 deletions Svc/PassiveRateGroup/PassiveRateGroup.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* \author: Tim Canham
* \file:
* \brief
*
* This file implements the PassiveRateGroup component,
* which invokes a set of components the comprise the rate group.
*
* Copyright 2014-2015, by the California Institute of Technology.
* ALL RIGHTS RESERVED. United States Government Sponsorship
* acknowledged.
*/

#ifndef SVC_PASSIVERATEGROUP_IMPL_HPP
#define SVC_PASSIVERATEGROUP_IMPL_HPP

#include <Svc/PassiveRateGroup/PassiveRateGroupComponentAc.hpp>

namespace Svc {

//! \class PassiveRateGroupImpl
//! \brief Executes a set of components as part of a rate group
//!
//! PassiveRateGroup takes an input cycle call to begin the rate group cycle.
//! It calls each output port in succession and passes the value in the context
//! array at the index corresponding to the output port number. It keeps track of the execution
//! time of the rate group and detects overruns.
//!

class PassiveRateGroup : public PassiveRateGroupComponentBase {
public:
//! \brief PassiveRateGroupImpl constructor
//!
//! The constructor of the class clears all the flags and copies the
//! contents of the context array to private storage.
//!
//! \param compName Name of the component
explicit PassiveRateGroup(const char* compName); //! \brief PassiveRateGroupImpl initialization function

//! \brief PassiveRateGroup configuration function
//!
//! The configuration function takes an array of context values to pass to
//! members of the rate group.
//!
//! \param contexts Array of integers that contain the context values that will be sent
//! to each member component. The index of the array corresponds to the
//! output port number.
//! \param numContexts The number of elements in the context array.
void configure(NATIVE_INT_TYPE contexts[], NATIVE_INT_TYPE numContexts);

//! \brief PassiveRateGroupImpl destructor
//!
//! The destructor of the class is empty
~PassiveRateGroup();

PRIVATE:
//! \brief Input cycle port handler
//!
//! The cycle port handler calls each component in the rate group in turn,
//! passing the context value. It computes the execution time each cycle,
//! and writes it to a telemetry value if it reaches a maximum time
//!
//! \param portNum incoming port call. For this class, should always be zero
//! \param cycleStart value stored by the cycle driver, used to compute execution time.
void CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart);

U32 m_cycles; //!< cycles executed
U32 m_maxTime; //!< maximum execution time in microseconds
NATIVE_INT_TYPE m_numContexts; //!< number of contexts

Check notice

Code scanning / CodeQL

Use of basic integral type

m_numContexts uses the basic integral type int rather than a typedef with size and signedness.
NATIVE_INT_TYPE m_contexts[NUM_RATEGROUPMEMBEROUT_OUTPUT_PORTS]; //!< Must match number of output ports

Check notice

Code scanning / CodeQL

Use of basic integral type

m_contexts uses the basic integral type int rather than a typedef with size and signedness.
};

} // namespace Svc

#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions Svc/PassiveRateGroup/docs/sdd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<title>PassiveRateGroup Component SDD</title>
# RateGroupDriver Component

## 1. Introduction

`Svc::PassiveRateGroup` is an passive component that drives a set of components connected to `Svc::Sched` output ports. It contains an synchronous input `Svc::Cycle` port that drives all the operations. The component invokes each output port in order, passing an argument specified in the supplied context list. It tracks execution time of the cycle.

## 2. Requirements

The requirements for `Svc::PassiveRateGroup` are as follows:

Requirement | Description | Verification Method
----------- | ----------- | -------------------
FPRIME-PRG-001 | The `Svc::PassiveRateGroup` component shall be passive and will be driven by an input synchronous port call | Inspection, Unit test
FPRIME-PRG-002 | The `Svc::PassiveRateGroup` component shall invoke its output ports in order, passing the value contained in a table based on port number | Unit Test
FPRIME-PRG-003 | The `Svc::PassiveRateGroup` component shall track the time required to execute the rate group and report it as telemetry | Unit Test


## 3. Design

### 3.1 Context

#### 3.1.1 Component Diagram

The `Svc::PassiveRateGroup` component has the following component diagram:

![PassiveRateGroup Diagram](img/PassiveRateGroupBDD.png "PassiveRateGroup")

#### 3.1.2 Ports

The `Svc::PassiveRateGroup` component uses the following port types:

Port Data Type | Name | Direction | Kind | Usage
-------------- | ---- | --------- | ---- | -----
Svc::Cycle | CycleIn | Input | synchronous | Receive a call to run one cycle of the rate group
[`Svc::Sched`](../../Sched/docs/sdd.md) | RateGroupMemberOut | Output | n/a | Rate group ports

#### 3.2 Functional Description

The `Svc::PassiveRateGroup` component has one input port that is used to drive all of the processing. The component calls the output ports in order, passing the context from the context list as the port argument.

### 3.3 Scenarios

#### 3.3.1 Rate Group Port Call

As described in the Functional Description section, the `Svc::PassiveRateGroup` component accepts calls to the CycleIn and invokes the RateGroupMemberOut ports:

**Sequence Diagram**
```mermaid
sequenceDiagram
participant RateGroupDriver
participant PassiveRateGroup
participant Callee
RateGroupDriver ->> PassiveRateGroup: CycleIn
loop for each callee
PassiveRateGroup ->> Callee: RateGroupMemberOut[N]
Callee -->> PassiveRateGroup:
end
PassiveRateGroup -->> RateGroupDriver:
```

### 3.4 State

`Svc::PassiveRateGroup` has no state machines.

### 3.5 Algorithms

`Svc::PassiveRateGroup` has no significant algorithms.

## 4. Change Log

Date | Description
---- | -----------
2/9/2017 | First Draft



84 changes: 84 additions & 0 deletions Svc/PassiveRateGroup/test/ut/PassiveRateGroupImplTester.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
LeStarch marked this conversation as resolved.
Show resolved Hide resolved
* \author Tim Canham
* \file
* \brief
*
* This file is the test component for the active rate group unit test.
*
* Code Generated Source Code Header
*
* Copyright 2014-2015, by the California Institute of Technology.
* ALL RIGHTS RESERVED. United States Government Sponsorship
* acknowledged.
*/

#include <gtest/gtest.h>
#include <Fw/Test/UnitTest.hpp>
#include <Svc/PassiveRateGroup/test/ut/PassiveRateGroupTester.hpp>

#include <cstdio>
#include <cstring>

namespace Svc {

void PassiveRateGroupTester::init(NATIVE_INT_TYPE instance) {
PassiveRateGroupGTestBase::init();
}

PassiveRateGroupTester::PassiveRateGroupTester(Svc::PassiveRateGroup& inst)
: PassiveRateGroupGTestBase("testerbase", 100), m_impl(inst), m_callOrder(0) {
this->clearPortCalls();
}

void PassiveRateGroupTester::clearPortCalls() {
memset(this->m_callLog, 0, sizeof(this->m_callLog));
this->m_callOrder = 0;
}

PassiveRateGroupTester::~PassiveRateGroupTester() {}

void PassiveRateGroupTester::from_RateGroupMemberOut_handler(NATIVE_INT_TYPE portNum, NATIVE_UINT_TYPE context) {
ASSERT_TRUE(portNum < static_cast<NATIVE_INT_TYPE>(FW_NUM_ARRAY_ELEMENTS(m_impl.m_RateGroupMemberOut_OutputPort)));
this->m_callLog[portNum].portCalled = true;
this->m_callLog[portNum].contextVal = context;
this->m_callLog[portNum].order = this->m_callOrder++;
}

void PassiveRateGroupTester::runNominal(NATIVE_INT_TYPE contexts[],
NATIVE_UINT_TYPE numContexts,
NATIVE_INT_TYPE instance) {
TEST_CASE(101.1.1, "Run nominal rate group execution");

// clear events
this->clearTlm();

Svc::TimerVal timer;
timer.take();

// clear port call log
this->clearPortCalls();

REQUIREMENT("FPRIME-PRG-001");
// call active rate group with timer val
this->invoke_to_CycleIn(0, timer);


// check calls
REQUIREMENT("FPRIME-PRG-002");
for (NATIVE_UINT_TYPE portNum = 0;
portNum < static_cast<NATIVE_INT_TYPE>(FW_NUM_ARRAY_ELEMENTS(this->m_impl.m_RateGroupMemberOut_OutputPort)); portNum++) {
ASSERT_TRUE(this->m_callLog[portNum].portCalled);
ASSERT_EQ(this->m_callLog[portNum].contextVal, contexts[portNum]);
ASSERT_EQ(this->m_callLog[portNum].order, portNum);
}
// Cycle times should be non-zero
REQUIREMENT("FPRIME-PRG-003");
ASSERT_TLM_MaxCycleTime_SIZE(1);
ASSERT_TLM_CycleTime_SIZE(1);
ASSERT_TLM_CycleCount_SIZE(1);
ASSERT_GT(this->tlmHistory_MaxCycleTime->at(0).arg, 0);
ASSERT_GT(this->tlmHistory_CycleTime->at(0).arg, 0);
ASSERT_GT(this->tlmHistory_CycleCount->at(0).arg, 0);
}

} // namespace Svc
Loading