fprime/Svc/FpySequencer/FpySequencer.hpp
Thomas Boyer-Chammard d669ea2c5a
Replace FpConfig.h header with FPP model elements (#4393)
* Update FpConfig.h

* Update AcConstants.fpp

* Update FPrimeBasicTypes.hpp

* Update BasicTypes.h

* Update FpySequencer.hpp

* Update FpConfig.h

* Update FPrimeBasicTypes.hpp

* Update BasicTypes.h

* Update BasicTypes.h

* Update BasicTypes.h

* Update BasicTypes.h

* Update BasicTypes.h

* Update BasicTypes.h

* Update BasicTypes.h

* Update FPrimeBasicTypes.hpp

* Update FPrimeBasicTypes.hpp

* Update FpConfig.h

* Update AcConstants.fpp

* Revert casts

* Add static_cast in asserts, reorganize files per feature

* Fix static_assert after merging devel

* Add assert to static cast

* clean up comments and TODOs

* formatting

* Fix formatting

* Fix RHEL8 error

* Other UT cast fix

* cast one side only

* fix spelling and move assert count to FpConstants

* Reorder and comments

* rob test

* re-add double cast

* Revert testing static_cast

* Update docs

* use SIZE_OF variables instead of hardcoding value

* Update FpConfig in CMake tests

---------

Co-authored-by: ekswang <eric.k.wang@jpl.nasa.gov>
2025-11-06 16:29:15 -08:00

839 lines
41 KiB
C++

// ======================================================================
// \title FpySequencer.hpp
// \author zimri.leisher
// \brief hpp file for FpySequencer component implementation class
// ======================================================================
#ifndef FpySequencer_HPP
#define FpySequencer_HPP
#include "Fw/Types/MemAllocator.hpp"
#include "Fw/Types/StringBase.hpp"
#include "Fw/Types/SuccessEnumAc.hpp"
#include "Fw/Types/WaitEnumAc.hpp"
#include "Os/File.hpp"
#include "Svc/FpySequencer/DirectiveIdEnumAc.hpp"
#include "Svc/FpySequencer/FlagIdEnumAc.hpp"
#include "Svc/FpySequencer/FooterSerializableAc.hpp"
#include "Svc/FpySequencer/FppConstantsAc.hpp"
#include "Svc/FpySequencer/FpySequencerComponentAc.hpp"
#include "Svc/FpySequencer/FpySequencer_GoalStateEnumAc.hpp"
#include "Svc/FpySequencer/HeaderSerializableAc.hpp"
#include "Svc/FpySequencer/SequenceSerializableAc.hpp"
#include "Svc/FpySequencer/StatementSerializableAc.hpp"
#include "config/FppConstantsAc.hpp"
static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits<U8>::max(),
"Sequence arg count must be below U8 max");
static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(),
"Sequence statement count must be below U16 max");
static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits<Svc::Fpy::StackSizeType>::max(),
"Max stack size must be below Svc::Fpy::StackSizeType max");
static_assert(Svc::Fpy::MAX_STACK_SIZE >= static_cast<FwSizeType>(FW_TLM_BUFFER_MAX_SIZE),
"Max stack size must be greater than max tlm buffer size");
static_assert(Svc::Fpy::MAX_STACK_SIZE >= static_cast<FwSizeType>(FW_PARAM_BUFFER_MAX_SIZE),
"Max stack size must be greater than max prm buffer size");
static_assert(Svc::Fpy::FLAG_COUNT < std::numeric_limits<U8>::max(), "Flag count must be less than U8 max");
namespace Svc {
using Signal = FpySequencer_SequencerStateMachineStateMachineBase::Signal;
using State = FpySequencer_SequencerStateMachineStateMachineBase::State;
using DirectiveError = Fpy::DirectiveErrorCode;
class FpySequencer : public FpySequencerComponentBase {
friend class FpySequencerTester;
public:
union DirectiveUnion {
FpySequencer_WaitRelDirective waitRel;
FpySequencer_WaitAbsDirective waitAbs;
FpySequencer_GotoDirective gotoDirective;
FpySequencer_IfDirective ifDirective;
FpySequencer_NoOpDirective noOp;
FpySequencer_PushTlmValDirective pushTlmVal;
FpySequencer_PushTlmValAndTimeDirective pushTlmValAndTime;
FpySequencer_PushPrmDirective pushPrm;
FpySequencer_ConstCmdDirective constCmd;
FpySequencer_StackOpDirective stackOp;
FpySequencer_ExitDirective exit;
FpySequencer_AllocateDirective allocate;
FpySequencer_StoreConstOffsetDirective storeConstOffset;
FpySequencer_LoadDirective load;
FpySequencer_PushValDirective pushVal;
FpySequencer_DiscardDirective discard;
FpySequencer_MemCmpDirective memCmp;
FpySequencer_StackCmdDirective stackCmd;
FpySequencer_PushTimeDirective pushTime;
FpySequencer_SetFlagDirective setFlag;
FpySequencer_GetFlagDirective getFlag;
FpySequencer_GetFieldDirective getField;
FpySequencer_PeekDirective peek;
FpySequencer_AssertDirective assert;
FpySequencer_StoreDirective store;
DirectiveUnion() {}
~DirectiveUnion() {}
};
class Stack {
public:
// the byte array of the program stack, storing lvars, operands and function calls
U8 bytes[Fpy::MAX_STACK_SIZE] = {0};
// how many bytes high the stack is
Fpy::StackSizeType size = 0;
// pops a value off of the top of the stack
// converts it from big endian
template <typename T>
T pop();
// pushes a value onto the top of the stack
// converts it to big endian
template <typename T>
void push(T val);
// pops a byte array from the top of the stack into the destination array
// does not convert endianness
void pop(U8* dest, Fpy::StackSizeType size);
// pushes a byte array to the top of the stack from the source array
// leaves the source array unmodified
// does not convert endianness
void push(U8* src, Fpy::StackSizeType size);
// pushes zero bytes to the stack
void pushZeroes(Fpy::StackSizeType byteCount);
// returns a pointer to the next unused byte at the top of the stack
U8* top();
// returns a pointer to the first byte of the lvars array
U8* lvars();
// returns the stack height at which the lvar array begins
Fpy::StackSizeType lvarOffset();
};
// ----------------------------------------------------------------------
// Construction, initialization, and destruction
// ----------------------------------------------------------------------
//! Construct object FpySequencer
//!
FpySequencer(const char* const compName /*!< The component name*/
);
//! Destroy object FpySequencer
//!
~FpySequencer();
private:
//! Handler for command RUN
//!
//! Loads, validates and runs a sequence
void RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName, //!< The name of the sequence file
FpySequencer_BlockState block //!< Return command status when complete or not
) override;
//! Handler for command VALIDATE
//!
//! Loads and validates a sequence
void VALIDATE_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName //!< The name of the sequence file
) override;
//! Handler for command RUN_VALIDATED
//!
//! Runs a previously validated sequence
void RUN_VALIDATED_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
FpySequencer_BlockState block //!< Return command status when complete or not
) override;
//! Handler for command CANCEL
//!
//! Cancels a running or validated sequence
void CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;
//! Handler for command SET_BREAKPOINT
//!
//! Sets the breakpoint which will pause the execution of the sequencer when
//! reached, until unpaused by the CONTINUE command. Will pause just before
//! dispatching the specified statement. This command is valid in all states. Breakpoint
//! settings are cleared after a sequence ends execution.
void SET_BREAKPOINT_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
U32 stmtIdx, //!< The statement index to pause execution before.
bool breakOnce //!< Whether or not to break only once at this breakpoint
) override;
//! Handler for command BREAK
//!
//! Pauses the execution of the sequencer, just before it is about to dispatch the next statement,
//! until unpaused by the CONTINUE command, or stepped by the STEP command. This command is only valid in the
//! RUNNING state.
void BREAK_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;
//! Handler for command CONTINUE
//!
//! Continues the automatic execution of the sequence after it has been paused. If a breakpoint is still
//! set, it may pause again on that breakpoint. This command is only valid in the RUNNING.PAUSED state.
void CONTINUE_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;
//! Handler for command CLEAR_BREAKPOINT
//!
//! Clears the breakpoint, but does not continue executing the sequence. This command
//! is valid in all states. This happens automatically when a sequence ends execution.
void CLEAR_BREAKPOINT_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;
//! Handler for command STEP
//!
//! Dispatches and awaits the result of the next directive, or ends the sequence if no more directives remain.
//! Returns to the RUNNING.PAUSED state if the directive executes successfully. This command is only valid in the
//! RUNNING.PAUSED state.
void STEP_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;
//! Handler for command SET_FLAG
//!
//! Sets the value of a flag. See Fpy.FlagId docstrings for info on each flag.
//! This command is only valid in the RUNNING state.
void SET_FLAG_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
Svc::Fpy::FlagId flag,
bool value) override;
//! Handler for command DUMP_STACK_TO_FILE
//!
//! Writes the contents of the stack to a file. This command is only valid in the RUNNING.PAUSED state.
void DUMP_STACK_TO_FILE_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName //!< The name of the output file
) override;
// ----------------------------------------------------------------------
// Functions to implement for internal state machine actions
// ----------------------------------------------------------------------
//! Implementation for action signalEntered of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! simply raises the "entered" signal
void Svc_FpySequencer_SequencerStateMachine_action_signalEntered(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action setSequenceFilePath of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the current sequence file path member var
void Svc_FpySequencer_SequencerStateMachine_action_setSequenceFilePath(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
) override;
//! Implementation for action setSequenceBlockState of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the block state of the sequence to be run
void Svc_FpySequencer_SequencerStateMachine_action_setSequenceBlockState(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
) override;
//! Implementation for action validate of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! performs all steps necessary for sequence validation, and raises a signal result_success or result_failure
void Svc_FpySequencer_SequencerStateMachine_action_validate(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action report_seqSucceeded of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! reports that a sequence succeeded
void Svc_FpySequencer_SequencerStateMachine_action_report_seqSucceeded(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action report_seqCancelled of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! reports that a sequence was cancelled
void Svc_FpySequencer_SequencerStateMachine_action_report_seqCancelled(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action setGoalState_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the goal state to RUNNING
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_RUNNING(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action setGoalState_VALID of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the goal state to VALID
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_VALID(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action setGoalState_IDLE of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the goal state to IDLE
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_IDLE(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action sendCmdResponse_OK of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! responds to the calling command with OK
void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_OK(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action sendCmdResponse_EXECUTION_ERROR of state machine
//! Svc_FpySequencer_SequencerStateMachine
//!
//! responds to the calling command with EXECUTION_ERROR
void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_EXECUTION_ERROR(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action dispatchStatement of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! iterates to the next statement and dispatches it
void Svc_FpySequencer_SequencerStateMachine_action_dispatchStatement(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action clearSequenceFile of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! clears all variables related to the loading/validating of the sequence file
void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceFile(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action checkShouldWake of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! checks if sequencer should wake from sleep
void Svc_FpySequencer_SequencerStateMachine_action_checkShouldWake(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action resetRuntime of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! resets the sequence runtime
void Svc_FpySequencer_SequencerStateMachine_action_resetRuntime(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action checkStatementTimeout of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! checks if the current statement has timed out
void Svc_FpySequencer_SequencerStateMachine_action_checkStatementTimeout(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action incrementSequenceCounter of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! increments the m_sequencesStarted counter
void Svc_FpySequencer_SequencerStateMachine_action_incrementSequenceCounter(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action clearBreakpoint of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! clears the breakpoint, allowing execution of the sequence to continue
void Svc_FpySequencer_SequencerStateMachine_action_clearBreakpoint(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action report_seqBroken of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! reports that a breakpoint was hit
void Svc_FpySequencer_SequencerStateMachine_action_report_seqBroken(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action setBreakpoint of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the breakpoint to the provided args
void Svc_FpySequencer_SequencerStateMachine_action_setBreakpoint(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
const Svc::FpySequencer_BreakpointArgs& value //!< The value
) override;
//! Implementation for action setBreakBeforeNextLine of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the "break on next line" flag to true
void Svc_FpySequencer_SequencerStateMachine_action_setBreakBeforeNextLine(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action clearBreakBeforeNextLine of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! sets the "break on next line" flag to false
void Svc_FpySequencer_SequencerStateMachine_action_clearBreakBeforeNextLine(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action report_seqFailed of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! called when a sequence failed to execute successfully
void Svc_FpySequencer_SequencerStateMachine_action_report_seqFailed(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
//! Implementation for action report_seqStarted of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! reports that a sequence was started
void Svc_FpySequencer_SequencerStateMachine_action_report_seqStarted(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) override;
protected:
// ----------------------------------------------------------------------
// Functions to implement for internal state machine guards
// ----------------------------------------------------------------------
//! Implementation for guard goalStateIs_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! return true if the goal state is RUNNING
bool Svc_FpySequencer_SequencerStateMachine_guard_goalStateIs_RUNNING(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) const override;
//! Implementation for guard shouldBreak of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! return true if should break at this point in execution, before dispatching
//! next stmt
bool Svc_FpySequencer_SequencerStateMachine_guard_shouldBreak(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) const override;
//! Implementation for guard breakOnce of state machine Svc_FpySequencer_SequencerStateMachine
//!
//! return true if this breakpoint should only happen once
bool Svc_FpySequencer_SequencerStateMachine_guard_breakOnce(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) const override;
// ----------------------------------------------------------------------
// Handlers to implement for typed input ports
// ----------------------------------------------------------------------
//! Handler for input port checkTimers
void checkTimers_handler(FwIndexType portNum, //!< The port number
U32 context //!< The call order
) override;
//! Handler for input port cmdResponseIn
void cmdResponseIn_handler(FwIndexType portNum, //!< The port number
FwOpcodeType opCode, //!< Command Op Code
U32 cmdSeq, //!< Command Sequence
const Fw::CmdResponse& response //!< The command response argument
) override;
//! Handler for input port seqRunIn
void seqRunIn_handler(FwIndexType portNum, const Fw::StringBase& filename) override;
//! Handler for input port pingIn
void pingIn_handler(FwIndexType portNum, //!< The port number
U32 key //!< Value to return to pinger
) override;
//! Handler for input port tlmWrite
void tlmWrite_handler(FwIndexType portNum, //!< The port number
U32 context //!< The call order
) override;
//! Internal interface handler for directive_waitAbs
void directive_waitAbs_internalInterfaceHandler(const FpySequencer_WaitAbsDirective& directive) override;
//! Internal interface handler for directive_waitRel
void directive_waitRel_internalInterfaceHandler(const FpySequencer_WaitRelDirective& directive) override;
//! Internal interface handler for directive_goto
void directive_goto_internalInterfaceHandler(const Svc::FpySequencer_GotoDirective& directive) override;
//! Internal interface handler for directive_if
void directive_if_internalInterfaceHandler(const Svc::FpySequencer_IfDirective& directive) override;
//! Internal interface handler for directive_noOp
void directive_noOp_internalInterfaceHandler(const Svc::FpySequencer_NoOpDirective& directive) override;
//! Internal interface handler for directive_pushTlmVal
void directive_pushTlmVal_internalInterfaceHandler(const Svc::FpySequencer_PushTlmValDirective& directive) override;
//! Internal interface handler for directive_pushTlmValAndTime
void directive_pushTlmValAndTime_internalInterfaceHandler(
const Svc::FpySequencer_PushTlmValAndTimeDirective& directive) override;
//! Internal interface handler for directive_pushPrm
void directive_pushPrm_internalInterfaceHandler(const Svc::FpySequencer_PushPrmDirective& directive) override;
//! Internal interface handler for directive_constCmd
void directive_constCmd_internalInterfaceHandler(const Svc::FpySequencer_ConstCmdDirective& directive) override;
//! Internal interface handler for directive_stackOp
void directive_stackOp_internalInterfaceHandler(const Svc::FpySequencer_StackOpDirective& directive) override;
//! Internal interface handler for directive_exit
void directive_exit_internalInterfaceHandler(const Svc::FpySequencer_ExitDirective& directive) override;
//! Internal interface handler for directive_allocate
void directive_allocate_internalInterfaceHandler(const Svc::FpySequencer_AllocateDirective& directive) override;
//! Internal interface handler for directive_storeConstOffset
void directive_storeConstOffset_internalInterfaceHandler(
const Svc::FpySequencer_StoreConstOffsetDirective& directive) override;
//! Internal interface handler for directive_load
void directive_load_internalInterfaceHandler(const Svc::FpySequencer_LoadDirective& directive) override;
//! Internal interface handler for directive_pushVal
void directive_pushVal_internalInterfaceHandler(const Svc::FpySequencer_PushValDirective& directive) override;
//! Internal interface handler for directive_discard
void directive_discard_internalInterfaceHandler(const Svc::FpySequencer_DiscardDirective& directive) override;
//! Internal interface handler for directive_memCmp
void directive_memCmp_internalInterfaceHandler(const Svc::FpySequencer_MemCmpDirective& directive) override;
//! Internal interface handler for directive_stackCmd
void directive_stackCmd_internalInterfaceHandler(const Svc::FpySequencer_StackCmdDirective& directive) override;
//! Internal interface handler for directive_pushTime
void directive_pushTime_internalInterfaceHandler(const Svc::FpySequencer_PushTimeDirective& directive) override;
//! Internal interface handler for directive_setFlag
void directive_setFlag_internalInterfaceHandler(const Svc::FpySequencer_SetFlagDirective& directive) override;
//! Internal interface handler for directive_getFlag
void directive_getFlag_internalInterfaceHandler(const Svc::FpySequencer_GetFlagDirective& directive) override;
//! Internal interface handler for directive_getField
void directive_getField_internalInterfaceHandler(const Svc::FpySequencer_GetFieldDirective& directive) override;
//! Internal interface handler for directive_peek
void directive_peek_internalInterfaceHandler(const Svc::FpySequencer_PeekDirective& directive) override;
//! Internal interface handler for directive_assert
void directive_assert_internalInterfaceHandler(const Svc::FpySequencer_AssertDirective& directive) override;
//! Internal interface handler for directive_store
void directive_store_internalInterfaceHandler(const Svc::FpySequencer_StoreDirective& directive) override;
void parametersLoaded() override;
void parameterUpdated(FwPrmIdType id) override;
public:
void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes);
void deallocateBuffer(Fw::MemAllocator& allocator);
private:
static constexpr U32 CRC_INITIAL_VALUE = 0xFFFFFFFFU;
// allocated at startup
Fw::ExternalSerializeBuffer m_sequenceBuffer;
// id of allocator that gave us m_sequenceBuffer
FwEnumStoreType m_allocatorId;
// assigned by the user via cmd
Fw::String m_sequenceFilePath;
// the sequence, loaded in memory
Fpy::Sequence m_sequenceObj;
// live running computation of CRC (updated as we read)
U32 m_computedCRC;
// whether or not the sequence we're about to run should return immediately or
// block on completion
FpySequencer_BlockState m_sequenceBlockState;
// if we are to block on completion, save the opCode and cmdSeq we should
// return
FwOpcodeType m_savedOpCode;
U32 m_savedCmdSeq;
// the goal state is the state that we're trying to reach in the sequencer
// if it's RUNNING, then we should promptly go to RUNNING once we validate the
// sequence. if it's VALID, we should wait after VALIDATING
FpySequencer_GoalState m_goalState;
// the total number of sequences this sequencer has started since construction
U64 m_sequencesStarted;
// the total number of statements this sequencer has dispatched, successfully or
// otherwise, since construction
U64 m_statementsDispatched;
// the runtime state of the sequence. encapsulates all state
// needed to run the sequence.
// this is distinct from the state of the sequencer. the
// sequencer and all its state is really just a shell to load
// and execute this runtime.
struct Runtime {
// the index of the next statement to be executed
U32 nextStatementIndex = 0;
// the opcode of the statement that is currently executing
U8 currentStatementOpcode = Fpy::DirectiveId::INVALID;
// the opcode of the command that we are currently awaiting, or 0 if we are executing a directive
FwOpcodeType currentCmdOpcode = 0;
// the time we dispatched the statement that is currently executing
Fw::Time currentStatementDispatchTime = Fw::Time();
// the absolute time we should wait for until returning
// a statement response
Fw::Time wakeupTime = Fw::Time();
Stack stack = Stack();
// the sequencer runtime flags. these are modifiable by the sequence and control
// various aspects of the sequencer.
// these get set to a default value from FpySequencerCfg
bool flags[Fpy::FLAG_COUNT] = {0};
} m_runtime;
// the state of the debugger. debugger is separate from runtime
// because it can be set up before running the sequence.
struct BreakpointInfo {
// whether or not to break at the debug breakpoint index
bool breakpointInUse = false;
// whether or not to remove the breakpoint after breaking on it
bool breakOnlyOnceOnBreakpoint = false;
// the statement index at which to break, before dispatching
U32 breakpointIndex = 0;
// whether or not to break before dispatching the next line,
// independent of what line it is.
// can be used in combination with breakpointIndex
bool breakBeforeNextLine = false;
} m_breakpoint;
// debug information about the sequence. only valid in the PAUSED state
// which you can access via BREAK or SET_BREAKPOINT cmds
struct DebugInfo {
// true if there are no statements remaining in the sequence file
bool reachedEndOfFile = false;
// true if we were able to deserialize the next statement successfully
bool nextStatementReadSuccess = false;
// the opcode of the next statement to dispatch.
U8 nextStatementOpcode = 0;
// if the next statement is a cmd directive, the opcode of that cmd
FwOpcodeType nextCmdOpcode = 0;
// the size of the stack. store this separately from the real stack size
// so we can avoid changing this during runtime, only modify it during
// debug
Fpy::StackSizeType stackSize = 0;
} m_debug;
struct Telemetry {
// the number of statements that failed to execute
U64 statementsFailed = 0;
// the number of sequences successfully completed
U64 sequencesSucceeded = 0;
// the number of sequences that failed to validate or execute
U64 sequencesFailed = 0;
// the number of sequences that have been cancelled
U64 sequencesCancelled = 0;
// the error code of the last directive that ran
DirectiveError lastDirectiveError = DirectiveError::NO_ERROR;
// the index of the last directive that errored
U64 directiveErrorIndex = 0;
// the opcode of the last directive that errored
Fpy::DirectiveId directiveErrorId = Fpy::DirectiveId::INVALID;
} m_tlm;
// ----------------------------------------------------------------------
// Validation state
// ----------------------------------------------------------------------
static void updateCrc(U32& crc, //!< The CRC to update
const U8* buffer, //!< The buffer
FwSizeType bufferSize //!< The buffer size
);
// loads the sequence in memory, and does header/crc/integrity checks.
// return SUCCESS if sequence is valid, FAILURE otherwise
Fw::Success validate();
// reads and validates the header from the m_sequenceBuffer
// return SUCCESS if sequence is valid, FAILURE otherwise
Fw::Success readHeader();
// reads and validates the body from the m_sequenceBuffer
// return SUCCESS if sequence is valid, FAILURE otherwise
Fw::Success readBody();
// reads and validates the footer from the m_sequenceBuffer
// return SUCCESS if sequence is valid, FAILURE otherwise
Fw::Success readFooter();
// reads some bytes from the open file into the m_sequenceBuffer.
// updates the CRC by default, but can be turned off if the contents
// aren't included in CRC.
// return success if successful
Fw::Success readBytes(Os::File& file,
FwSizeType readLen,
const FpySequencer_FileReadStage& readStage,
bool updateCrc = true);
// ----------------------------------------------------------------------
// Run state
// ----------------------------------------------------------------------
// utility method for updating telemetry based on a directive error code
void handleDirectiveErrorCode(Fpy::DirectiveId id, DirectiveError err);
// dispatches the next statement
Signal dispatchStatement();
// deserializes a directive from bytes into the Fpy type
// returns success if able to deserialize, and returns the Fpy type object
// as a reference, in a union of all the possible directive type objects
Fw::Success deserializeDirective(const Fpy::Statement& stmt, DirectiveUnion& deserializedDirective);
// dispatches a deserialized sequencer directive to the right handler.
void dispatchDirective(const DirectiveUnion& directive, const Fpy::DirectiveId& id);
// checks whether the currently executing statement timed out
Signal checkStatementTimeout();
// checks whether the sequencer should wake from sleeping
Signal checkShouldWake();
// return true if state is a substate of RUNNING
bool isRunningState(State state);
// update a struct containing debug telemetry, or defaults if not in debug break
void updateDebugTelemetryStruct();
// ----------------------------------------------------------------------
// Directives
// ----------------------------------------------------------------------
// sends a signal based on a signal id
void sendSignal(Signal signal);
// dispatches a command, returns whether successful or not
Fw::Success sendCmd(FwOpcodeType opcode, const U8* argBuf, FwSizeType argBufSize);
// returns the index of the current statement
U32 currentStatementIdx();
// we split these functions up into the internalInterfaceInvoke and these custom member funcs
// so that we can unit test them easier
Signal waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& error);
Signal waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive, DirectiveError& error);
Signal goto_directiveHandler(const FpySequencer_GotoDirective& directive, DirectiveError& error);
Signal if_directiveHandler(const FpySequencer_IfDirective& directive, DirectiveError& error);
Signal noOp_directiveHandler(const FpySequencer_NoOpDirective& directive, DirectiveError& error);
Signal pushTlmVal_directiveHandler(const FpySequencer_PushTlmValDirective& directive, DirectiveError& error);
Signal pushTlmValAndTime_directiveHandler(const FpySequencer_PushTlmValAndTimeDirective& directive,
DirectiveError& error);
Signal pushPrm_directiveHandler(const FpySequencer_PushPrmDirective& directive, DirectiveError& error);
Signal constCmd_directiveHandler(const FpySequencer_ConstCmdDirective& directive, DirectiveError& error);
Signal stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive, DirectiveError& error);
DirectiveError op_or();
DirectiveError op_and();
DirectiveError op_ieq();
DirectiveError op_ine();
DirectiveError op_ult();
DirectiveError op_ule();
DirectiveError op_ugt();
DirectiveError op_uge();
DirectiveError op_slt();
DirectiveError op_sle();
DirectiveError op_sgt();
DirectiveError op_sge();
DirectiveError op_feq();
DirectiveError op_fne();
DirectiveError op_flt();
DirectiveError op_fle();
DirectiveError op_fgt();
DirectiveError op_fge();
DirectiveError op_not();
DirectiveError op_fpext();
DirectiveError op_fptrunc();
DirectiveError op_fptoui();
DirectiveError op_fptosi();
DirectiveError op_sitofp();
DirectiveError op_uitofp();
DirectiveError op_iadd();
DirectiveError op_isub();
DirectiveError op_imul();
DirectiveError op_udiv();
DirectiveError op_sdiv();
DirectiveError op_umod();
DirectiveError op_smod();
DirectiveError op_fadd();
DirectiveError op_fsub();
DirectiveError op_fmul();
DirectiveError op_fdiv();
DirectiveError op_float_floor_div();
DirectiveError op_fpow();
DirectiveError op_flog();
DirectiveError op_fmod();
DirectiveError op_siext_8_64();
DirectiveError op_siext_16_64();
DirectiveError op_siext_32_64();
DirectiveError op_ziext_8_64();
DirectiveError op_ziext_16_64();
DirectiveError op_ziext_32_64();
DirectiveError op_itrunc_64_8();
DirectiveError op_itrunc_64_16();
DirectiveError op_itrunc_64_32();
Signal exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& error);
Signal allocate_directiveHandler(const FpySequencer_AllocateDirective& directive, DirectiveError& error);
Signal storeConstOffset_directiveHandler(const FpySequencer_StoreConstOffsetDirective& directive,
DirectiveError& error);
Signal load_directiveHandler(const FpySequencer_LoadDirective& directive, DirectiveError& error);
Signal pushVal_directiveHandler(const FpySequencer_PushValDirective& directive, DirectiveError& error);
Signal discard_directiveHandler(const FpySequencer_DiscardDirective& directive, DirectiveError& error);
Signal memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive, DirectiveError& error);
Signal stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& error);
Signal pushTime_directiveHandler(const FpySequencer_PushTimeDirective& directive, DirectiveError& error);
Signal setFlag_directiveHandler(const FpySequencer_SetFlagDirective& directive, DirectiveError& error);
Signal getFlag_directiveHandler(const FpySequencer_GetFlagDirective& directive, DirectiveError& error);
Signal getField_directiveHandler(const FpySequencer_GetFieldDirective& directive, DirectiveError& error);
Signal peek_directiveHandler(const FpySequencer_PeekDirective& directive, DirectiveError& error);
Signal assert_directiveHandler(const FpySequencer_AssertDirective& directive, DirectiveError& error);
Signal store_directiveHandler(const FpySequencer_StoreDirective& directive, DirectiveError& error);
};
} // namespace Svc
#endif