From 36a07dd967d347642a9d450dcf93a3f04a8d504a Mon Sep 17 00:00:00 2001 From: Simone Morettini Date: Fri, 27 Oct 2023 00:09:47 +0200 Subject: [PATCH] Implementation of the offsets in the RateGroupDriver (#2166) * Implementation of the offsets * Fix comment * Fix spell error * Changing configure interface by addind DividersSet * Update RPI topology * Removing numDivisors from call * Removing memset clear as the constructor handles zeroed initialization * Fixing ASSERT and removing m_numDivisors * Renaming divisersSet to diviserSet --------- Co-authored-by: Simone Morettini Co-authored-by: Michael D Starch --- RPI/Top/instances.fpp | 7 ++- Ref/Top/RefTopology.cpp | 7 +-- Svc/RateGroupDriver/README | 11 +++-- Svc/RateGroupDriver/RateGroupDriver.cpp | 39 +++++++-------- Svc/RateGroupDriver/RateGroupDriver.hpp | 48 ++++++++++++------- .../test/ut/RateGroupDriverImplTester.cpp | 6 +-- .../test/ut/RateGroupDriverImplTester.hpp | 2 +- .../test/ut/RateGroupDriverTester.cpp | 8 ++-- 8 files changed, 69 insertions(+), 59 deletions(-) diff --git a/RPI/Top/instances.fpp b/RPI/Top/instances.fpp index 106406246a..055215cb6c 100644 --- a/RPI/Top/instances.fpp +++ b/RPI/Top/instances.fpp @@ -291,13 +291,12 @@ module RPI { { phase Fpp.ToCpp.Phases.configObjects """ - NATIVE_INT_TYPE rgDivs[Svc::RateGroupDriver::DIVIDER_SIZE] = { 1, 10, 0 }; + Svc::RateGroupDriver::DividerSet rgDivs{{{1, 0}, {10, 0}, {0, 0}}}; """ - + phase Fpp.ToCpp.Phases.configComponents """ rateGroupDriverComp.configure( - ConfigObjects::rateGroupDriverComp::rgDivs, - FW_NUM_ARRAY_ELEMENTS(ConfigObjects::rateGroupDriverComp::rgDivs) + ConfigObjects::rateGroupDriverComp::rgDivs ); """ } diff --git a/Ref/Top/RefTopology.cpp b/Ref/Top/RefTopology.cpp index 4266f97111..b95c3e47ba 100644 --- a/Ref/Top/RefTopology.cpp +++ b/Ref/Top/RefTopology.cpp @@ -35,8 +35,9 @@ Fw::MallocAllocator mallocator; Svc::FprimeFraming framing; Svc::FprimeDeframing deframing; -// The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz -NATIVE_INT_TYPE rateGroupDivisors[Svc::RateGroupDriver::DIVIDER_SIZE] = {1, 2, 4}; +// The reference topology divides the incoming clock signal (1Hz) into sub-signals: 1Hz, 1/2Hz, and 1/4Hz and +// zero offset for all the dividers +Svc::RateGroupDriver::DividerSet rateGroupDivisorsSet{{{1, 0}, {2, 0}, {4, 0}}}; // Rate groups may supply a context token to each of the attached children whose purpose is set by the project. The // reference topology sets each token to zero as these contexts are unused in this project. @@ -87,7 +88,7 @@ void configureTopology() { cmdSeq.allocateBuffer(0, mallocator, CMD_SEQ_BUFFER_SIZE); // Rate group driver needs a divisor list - rateGroupDriverComp.configure(rateGroupDivisors, FW_NUM_ARRAY_ELEMENTS(rateGroupDivisors)); + rateGroupDriverComp.configure(rateGroupDivisorsSet); // Rate groups require context arrays. Empty for Reference example. rateGroup1Comp.configure(rateGroup1Context, FW_NUM_ARRAY_ELEMENTS(rateGroup1Context)); diff --git a/Svc/RateGroupDriver/README b/Svc/RateGroupDriver/README index f8b02e3da4..b9a8ad16d8 100644 --- a/Svc/RateGroupDriver/README +++ b/Svc/RateGroupDriver/README @@ -1,6 +1,9 @@ -This component takes a primary clock tick in the system and divides it down to drive output ports. -Constructor arguments define the divisors for each port. The output ports are meant to be connected -to the input ports of rate groups to drive them at the correct rate. +This component takes a primary clock tick in the system and divides it down to drive output ports. +Constructor arguments define the divisors for each port. +The dividers argument define the divisors for each port as well as an offset to allow the triggering +for the rate group to be offset from each other. +The output ports are meant to be connected to the input ports of rate groups to drive them at the +correct rate. RateGroupDriverComponentAi.xml - XML definition of rate group driver component -RateGroupDriverImpl.hpp(.cpp) - Implementation for rate group driver \ No newline at end of file +RateGroupDriverImpl.hpp(.cpp) - Implementation for rate group driver \ No newline at end of file diff --git a/Svc/RateGroupDriver/RateGroupDriver.cpp b/Svc/RateGroupDriver/RateGroupDriver.cpp index 082a10f0eb..cc9e3515d1 100644 --- a/Svc/RateGroupDriver/RateGroupDriver.cpp +++ b/Svc/RateGroupDriver/RateGroupDriver.cpp @@ -8,59 +8,52 @@ namespace Svc { RateGroupDriver::RateGroupDriver(const char* compName) : RateGroupDriverComponentBase(compName), - m_numDividers(0),m_ticks(0),m_rollover(1) { + m_ticks(0),m_rollover(1),m_configured(false) { } - void RateGroupDriver::configure(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers) + void RateGroupDriver::configure(const DividerSet& dividerSet) { // check arguments - FW_ASSERT(dividers); - FW_ASSERT(numDividers); - this->m_numDividers = numDividers; - FW_ASSERT(numDividers <= static_cast(FW_NUM_ARRAY_ELEMENTS(this->m_dividers)), - numDividers, - static_cast(FW_NUM_ARRAY_ELEMENTS(this->m_dividers))); + FW_ASSERT(dividerSet.dividers); // verify port/table size matches FW_ASSERT(FW_NUM_ARRAY_ELEMENTS(this->m_dividers) == this->getNum_CycleOut_OutputPorts(), static_cast(FW_NUM_ARRAY_ELEMENTS(this->m_dividers)), this->getNum_CycleOut_OutputPorts()); - // clear table - ::memset(this->m_dividers,0,sizeof(this->m_dividers)); // copy provided array of dividers - for (NATIVE_INT_TYPE entry = 0; entry < numDividers; entry++) { - this->m_dividers[entry] = dividers[entry]; + for (NATIVE_UINT_TYPE entry = 0; entry < RateGroupDriver::DIVIDER_SIZE; entry++) { + // A port with an offset equal or bigger than the divisor is not accepted because it would never be called + FW_ASSERT((dividerSet.dividers[entry].offset==0)||(dividerSet.dividers[entry].offset < dividerSet.dividers[entry].divisor), + dividerSet.dividers[entry].offset, + dividerSet.dividers[entry].divisor); + this->m_dividers[entry] = dividerSet.dividers[entry]; // rollover value should be product of all dividers to make sure integer rollover doesn't jump cycles // only use non-zero dividers - if (dividers[entry] != 0) { - this->m_rollover *= dividers[entry]; + if (dividerSet.dividers[entry].divisor != 0) { + this->m_rollover *= dividerSet.dividers[entry].divisor; } } - + this->m_configured = true; } RateGroupDriver::~RateGroupDriver() { } - void RateGroupDriver::init(NATIVE_INT_TYPE instanceId) { - RateGroupDriverComponentBase::init(instanceId); - } - void RateGroupDriver::CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart) { // Make sure that the dividers have been configured: // If this asserts, add the configure() call to initialization. - FW_ASSERT(this->m_numDividers); + FW_ASSERT(this->m_configured); // Loop through each divider. For a given port, the port will be called when the divider value // divides evenly into the number of ticks. For example, if the divider value for a port is 4, // it would be called every fourth invocation of the CycleIn port. - for (NATIVE_INT_TYPE entry = 0; entry < this->m_numDividers; entry++) { - if (this->m_dividers[entry] != 0) { + for (NATIVE_UINT_TYPE entry = 0; entry < RateGroupDriver::DIVIDER_SIZE; entry++) { + if (this->m_dividers[entry].divisor != 0) { if (this->isConnected_CycleOut_OutputPort(entry)) { - if ((this->m_ticks % this->m_dividers[entry]) == 0) { + if ((this->m_ticks % this->m_dividers[entry].divisor) == this->m_dividers[entry].offset) { this->CycleOut_out(entry,cycleStart); } } diff --git a/Svc/RateGroupDriver/RateGroupDriver.hpp b/Svc/RateGroupDriver/RateGroupDriver.hpp index 57a3b18062..8016295145 100644 --- a/Svc/RateGroupDriver/RateGroupDriver.hpp +++ b/Svc/RateGroupDriver/RateGroupDriver.hpp @@ -33,6 +33,31 @@ namespace Svc { class RateGroupDriver : public RateGroupDriverComponentBase { public: + //! Size of the divider table, provided as a constants to users passing the table in + static const NATIVE_UINT_TYPE DIVIDER_SIZE = NUM_CYCLEOUT_OUTPUT_PORTS; + + //! \class Divider + //! \brief Struct describing a divider + struct Divider{ + //! Initializes divisor and offset to 0 (unused) + Divider() : divisor(0), offset(0) + {} + //! Initializes divisor and offset to passed-in pair + Divider(NATIVE_INT_TYPE divisorIn, NATIVE_INT_TYPE offsetIn) : + divisor(divisorIn), offset(offsetIn) + {} + //! Divisor + NATIVE_INT_TYPE divisor; + //! Offset + NATIVE_INT_TYPE offset; + }; + + //! \class DividerSet + //! \brief Struct containing an array of dividers + struct DividerSet { + //! Dividers + Divider dividers[Svc::RateGroupDriver::DIVIDER_SIZE]; + }; //! \brief RateGroupDriver constructor //! @@ -43,17 +68,10 @@ namespace Svc { //! RateGroupDriver(const char* compName); - //! \brief RateGroupDriver initialization function - //! - //! The init() function initializes the autocoded base class - - void init(NATIVE_INT_TYPE instanceId = 0); - //! \brief RateGroupDriver configuration function - //! \param dividers array of integers used to divide down input tick - //! \param numDividers size of dividers array + //! \param dividersSet set of dividers used to divide down input tick - void configure(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers); + void configure(const DividerSet& dividersSet); //! \brief RateGroupDriverImpl destructor @@ -66,18 +84,16 @@ namespace Svc { void CycleIn_handler(NATIVE_INT_TYPE portNum, Svc::TimerVal& cycleStart); //! divider array - NATIVE_INT_TYPE m_dividers[NUM_CYCLEOUT_OUTPUT_PORTS]; - - //! size of divider array - NATIVE_INT_TYPE m_numDividers; + Divider m_dividers[NUM_CYCLEOUT_OUTPUT_PORTS]; //! tick counter NATIVE_INT_TYPE m_ticks; + //! rollover counter NATIVE_INT_TYPE m_rollover; - public: - //! Size of the divider table, provided as a constants to users passing the table in - static const NATIVE_UINT_TYPE DIVIDER_SIZE = NUM_CYCLEOUT_OUTPUT_PORTS; + + //! has the configure method been called + bool m_configured; }; } diff --git a/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.cpp b/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.cpp index 2b1841f1b3..70e3102af5 100644 --- a/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.cpp +++ b/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.cpp @@ -37,7 +37,7 @@ namespace Svc { this->m_portCalls[portNum] = true; } - void RateGroupDriverImplTester::runSchedNominal(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers) { + void RateGroupDriverImplTester::runSchedNominal(Svc::RateGroupDriver::DividerSet dividersSet, NATIVE_INT_TYPE numDividers) { TEST_CASE(106.1.1,"Nominal Execution"); COMMENT( @@ -48,7 +48,7 @@ namespace Svc { NATIVE_INT_TYPE expected_rollover = 1; for (NATIVE_INT_TYPE div = 0; div < numDividers; div++) { - expected_rollover *= dividers[div]; + expected_rollover *= dividersSet.dividers[div].divisor; } ASSERT_EQ(expected_rollover,this->m_impl.m_rollover); @@ -65,7 +65,7 @@ namespace Svc { ASSERT_EQ((cycle+1)%expected_rollover,this->m_impl.m_ticks); // check for various intervals for (NATIVE_INT_TYPE div = 0; div < numDividers; div++) { - if (cycle % dividers[div] == 0) { + if (cycle % dividersSet.dividers[div].divisor == dividersSet.dividers[div].offset) { EXPECT_TRUE(this->m_portCalls[div]); } else { EXPECT_FALSE(this->m_portCalls[div]); diff --git a/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.hpp b/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.hpp index 8b958e0f40..d03cce4055 100644 --- a/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.hpp +++ b/Svc/RateGroupDriver/test/ut/RateGroupDriverImplTester.hpp @@ -20,7 +20,7 @@ namespace Svc { void init(NATIVE_INT_TYPE instance = 0); - void runSchedNominal(NATIVE_INT_TYPE dividers[], NATIVE_INT_TYPE numDividers); + void runSchedNominal(Svc::RateGroupDriver::DividerSet dividersSet, NATIVE_INT_TYPE numDividers); private: diff --git a/Svc/RateGroupDriver/test/ut/RateGroupDriverTester.cpp b/Svc/RateGroupDriver/test/ut/RateGroupDriverTester.cpp index 50bcea1a79..6c80fd68e1 100644 --- a/Svc/RateGroupDriver/test/ut/RateGroupDriverTester.cpp +++ b/Svc/RateGroupDriver/test/ut/RateGroupDriverTester.cpp @@ -31,10 +31,10 @@ void connectPorts(Svc::RateGroupDriver& impl, Svc::RateGroupDriverImplTester& te TEST(RateGroupDriverTest,NominalSchedule) { - NATIVE_INT_TYPE dividers[] = {1,2,3}; + Svc::RateGroupDriver::DividerSet dividersSet{{{1, 0}, {2, 1}, {3, 0}}}; Svc::RateGroupDriver impl("RateGroupDriver"); - impl.configure(dividers,FW_NUM_ARRAY_ELEMENTS(dividers)); + impl.configure(dividersSet); Svc::RateGroupDriverImplTester tester(impl); @@ -44,7 +44,7 @@ TEST(RateGroupDriverTest,NominalSchedule) { // connect ports connectPorts(impl,tester); - tester.runSchedNominal(dividers,FW_NUM_ARRAY_ELEMENTS(dividers)); + tester.runSchedNominal(dividersSet,FW_NUM_ARRAY_ELEMENTS(dividersSet.dividers)); } @@ -53,5 +53,3 @@ int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } - -