GCC Code Coverage Report


Directory: ./
File: FpySequencer.hpp
Date: 2026-09-03 22:13:45
Exec Total Coverage
Lines: 0 2 0.0%
Functions: 0 2 0.0%
Branches: 0 0 -%

Line Branch Exec Source
1 // ======================================================================
2 // \title FpySequencer.hpp
3 // \author zimri.leisher
4 // \brief hpp file for FpySequencer component implementation class
5 // ======================================================================
6
7 #ifndef FpySequencer_HPP
8 #define FpySequencer_HPP
9
10 #include <random>
11 #include "Fw/Types/FileNameString.hpp"
12 #include "Fw/Types/MemAllocator.hpp"
13 #include "Fw/Types/StringBase.hpp"
14 #include "Fw/Types/SuccessEnumAc.hpp"
15 #include "Fw/Types/WaitEnumAc.hpp"
16 #include "Os/File.hpp"
17 #include "Svc/FpySequencer/DirectiveIdEnumAc.hpp"
18 #include "Svc/FpySequencer/FooterSerializableAc.hpp"
19 #include "Svc/FpySequencer/FppConstantsAc.hpp"
20 #include "Svc/FpySequencer/FpySequencerComponentAc.hpp"
21 #include "Svc/FpySequencer/FpySequencer_GoalStateEnumAc.hpp"
22 #include "Svc/FpySequencer/HeaderSerializableAc.hpp"
23 #include "Svc/FpySequencer/SequenceSerializableAc.hpp"
24 #include "Svc/FpySequencer/StatementSerializableAc.hpp"
25 #include "Svc/Seq/BlockStateEnumAc.hpp"
26 #include "Utils/Hash/Hash.hpp"
27 #include "config/FppConstantsAc.hpp"
28
29 static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits<U8>::max(),
30 "Sequence arg count must be below U8 max");
31 static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(),
32 "Sequence statement count must be below U16 max");
33 static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits<Svc::Fpy::StackSizeType>::max(),
34 "Max stack size must be below Svc::Fpy::StackSizeType max");
35 static_assert(Svc::Fpy::MAX_STACK_SIZE >= static_cast<FwSizeType>(FW_TLM_BUFFER_MAX_SIZE),
36 "Max stack size must be greater than max tlm buffer size");
37 static_assert(Svc::Fpy::MAX_STACK_SIZE >= static_cast<FwSizeType>(FW_PARAM_BUFFER_MAX_SIZE),
38 "Max stack size must be greater than max prm buffer size");
39
40 namespace Svc {
41
42 using Signal = FpySequencer_SequencerStateMachineStateMachineBase::Signal;
43 using State = FpySequencer_SequencerStateMachineStateMachineBase::State;
44 using DirectiveError = Fpy::DirectiveErrorCode;
45
46 class FpySequencer : public FpySequencerComponentBase {
47 friend class FpySequencerTester;
48
49 public:
50 union DirectiveUnion {
51 FpySequencer_WaitRelDirective waitRel;
52 FpySequencer_WaitAbsDirective waitAbs;
53 FpySequencer_GotoDirective gotoDirective;
54 FpySequencer_IfDirective ifDirective;
55 FpySequencer_NoOpDirective noOp;
56 FpySequencer_PushTlmValDirective pushTlmVal;
57 FpySequencer_PushTlmValAndTimeDirective pushTlmValAndTime;
58 FpySequencer_PushPrmDirective pushPrm;
59 FpySequencer_ConstCmdDirective constCmd;
60 FpySequencer_StackOpDirective stackOp;
61 FpySequencer_ExitDirective exit;
62 FpySequencer_AllocateDirective allocate;
63 FpySequencer_StoreRelConstOffsetDirective storeRelConstOffset;
64 FpySequencer_LoadRelDirective loadRel;
65 FpySequencer_PushValDirective pushVal;
66 FpySequencer_DiscardDirective discard;
67 FpySequencer_MemCmpDirective memCmp;
68 FpySequencer_StackCmdDirective stackCmd;
69 FpySequencer_PushTimeDirective pushTime;
70 FpySequencer_SetSeedDirective setSeed;
71 FpySequencer_PushRandDirective pushRand;
72 FpySequencer_GetFieldDirective getField;
73 FpySequencer_PeekDirective peek;
74 FpySequencer_StoreRelDirective storeRel;
75 FpySequencer_CallDirective call;
76 FpySequencer_ReturnDirective returnDirective;
77 FpySequencer_LoadAbsDirective loadAbs;
78 FpySequencer_StoreAbsDirective storeAbs;
79 FpySequencer_StoreAbsConstOffsetDirective storeAbsConstOffset;
80 FpySequencer_PopEventDirective popEvent;
81 FpySequencer_PopSerializableDirective popSerializable;
82
83 DirectiveUnion() {}
84 ~DirectiveUnion() {}
85 };
86
87 class Stack {
88 public:
89 // the byte array of the program stack, storing lvars, operands and function calls
90 U8 bytes[Fpy::MAX_STACK_SIZE] = {0};
91 // how many bytes high the stack is
92 Fpy::StackSizeType size = 0;
93 // the byte offset from the start of the stack where the current function's local variables begin.
94 // analogous to a 'frame pointer'.
95 Fpy::StackSizeType currentFrameStart = 0;
96
97 // pops a value off of the top of the stack
98 // converts it from big endian
99 template <typename T>
100 T pop();
101
102 // pushes a value onto the top of the stack
103 // converts it to big endian
104 template <typename T>
105 void push(T val);
106
107 // pops a byte array from the top of the stack into the destination array
108 // does not convert endianness
109 void pop(U8* dest, Fpy::StackSizeType size);
110
111 // pushes a byte array to the top of the stack from the source array
112 // leaves the source array unmodified
113 // does not convert endianness
114 void push(const U8* src, Fpy::StackSizeType size);
115
116 // pushes zero bytes to the stack
117 void pushZeroes(Fpy::StackSizeType byteCount);
118
119 // returns a pointer to the next unused byte at the top of the stack
120 U8* top();
121
122 // Copies data from one region of the stack to another
123 // Asserts that both regions are within bounds and do not overlap
124 // Does not modify stack size
125 void copy(Fpy::StackSizeType destOffset, Fpy::StackSizeType srcOffset, Fpy::StackSizeType copySize);
126
127 // Moves data within the stack (handles overlapping regions)
128 // Asserts that both source and destination are within bounds
129 // Does not modify stack size
130 void move(Fpy::StackSizeType destOffset, Fpy::StackSizeType srcOffset, Fpy::StackSizeType moveSize);
131 };
132
133 // ----------------------------------------------------------------------
134 // Construction, initialization, and destruction
135 // ----------------------------------------------------------------------
136
137 //! Construct object FpySequencer
138 //!
139 FpySequencer(const char* const compName /*!< The component name*/
140 );
141
142 //! Destroy object FpySequencer
143 //!
144 ~FpySequencer();
145
146 private:
147 //! Handler for command RUN
148 //!
149 //! Loads, validates and runs a sequence
150 void RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode
151 U32 cmdSeq, //!< The command sequence number
152 const Fw::CmdStringArg& fileName, //!< The name of the sequence file
153 const Svc::BlockState& block //!< Return command status when complete or not
154 ) override;
155
156 //! Handler implementation for command RUN_ARGS
157 void RUN_ARGS_cmdHandler(FwOpcodeType opCode, //!< The opcode
158 U32 cmdSeq, //!< The command sequence number
159 const Fw::CmdStringArg& fileName, //!< The name of the sequence file
160 const Svc::BlockState& block, //!< Return command status when complete or not
161 const Svc::SeqArgs& args //!< Arguments to pass to the sequencer
162 ) override;
163
164 //! Handler for command VALIDATE
165 //!
166 //! Loads and validates a sequence
167 void VALIDATE_cmdHandler(FwOpcodeType opCode, //!< The opcode
168 U32 cmdSeq, //!< The command sequence number
169 const Fw::CmdStringArg& fileName //!< The name of the sequence file
170 ) override;
171
172 //! Handler implementation for command VALIDATE_ARGS
173 //!
174 //! Loads and validates a sequence with arguments
175 void VALIDATE_ARGS_cmdHandler(FwOpcodeType opCode, //!< The opcode
176 U32 cmdSeq, //!< The command sequence number
177 const Fw::CmdStringArg& fileName, //!< The name of the sequence file
178 const Svc::SeqArgs& buffer //!< Arguments to pass to the sequencer
179 ) override;
180
181 //! Handler implementation for command RUN_VALIDATED
182 //!
183 //! Must be called after VALIDATE. Runs the sequence that was validated.
184 void RUN_VALIDATED_cmdHandler(FwOpcodeType opCode, //!< The opcode
185 U32 cmdSeq, //!< The command sequence number
186 const Svc::BlockState& block //!< Return command status when complete or not
187 ) override;
188
189 //! Handler for command CANCEL
190 //!
191 //! Cancels a running or validated sequence
192 void CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode
193 U32 cmdSeq //!< The command sequence number
194 ) override;
195
196 //! Handler for command SET_BREAKPOINT
197 //!
198 //! Sets the breakpoint which will pause the execution of the sequencer when
199 //! reached, until unpaused by the CONTINUE command. Will pause just before
200 //! dispatching the specified statement. This command is valid in all states. Breakpoint
201 //! settings are cleared after a sequence ends execution.
202 void SET_BREAKPOINT_cmdHandler(FwOpcodeType opCode, //!< The opcode
203 U32 cmdSeq, //!< The command sequence number
204 U32 stmtIdx, //!< The statement index to pause execution before.
205 bool breakOnce //!< Whether or not to break only once at this breakpoint
206 ) override;
207
208 //! Handler for command BREAK
209 //!
210 //! Pauses the execution of the sequencer, just before it is about to dispatch the next statement,
211 //! until unpaused by the CONTINUE command, or stepped by the STEP command. This command is only valid in the
212 //! RUNNING state.
213 void BREAK_cmdHandler(FwOpcodeType opCode, //!< The opcode
214 U32 cmdSeq //!< The command sequence number
215 ) override;
216
217 //! Handler for command CONTINUE
218 //!
219 //! Continues the automatic execution of the sequence after it has been paused. If a breakpoint is still
220 //! set, it may pause again on that breakpoint. This command is only valid in the RUNNING.PAUSED state.
221 void CONTINUE_cmdHandler(FwOpcodeType opCode, //!< The opcode
222 U32 cmdSeq //!< The command sequence number
223 ) override;
224
225 //! Handler for command CLEAR_BREAKPOINT
226 //!
227 //! Clears the breakpoint, but does not continue executing the sequence. This command
228 //! is valid in all states. This happens automatically when a sequence ends execution.
229 void CLEAR_BREAKPOINT_cmdHandler(FwOpcodeType opCode, //!< The opcode
230 U32 cmdSeq //!< The command sequence number
231 ) override;
232
233 //! Handler for command STEP
234 //!
235 //! Dispatches and awaits the result of the next directive, or ends the sequence if no more directives remain.
236 //! Returns to the RUNNING.PAUSED state if the directive executes successfully. This command is only valid in the
237 //! RUNNING.PAUSED state.
238 void STEP_cmdHandler(FwOpcodeType opCode, //!< The opcode
239 U32 cmdSeq //!< The command sequence number
240 ) override;
241
242 //! Handler for command DUMP_STACK_TO_FILE
243 //!
244 //! Writes the contents of the stack to a file. This command is only valid in the RUNNING.PAUSED state.
245 void DUMP_STACK_TO_FILE_cmdHandler(FwOpcodeType opCode, //!< The opcode
246 U32 cmdSeq, //!< The command sequence number
247 const Fw::CmdStringArg& fileName //!< The name of the output file
248 ) override;
249
250 // ----------------------------------------------------------------------
251 // Functions to implement for internal state machine actions
252 // ----------------------------------------------------------------------
253
254 //! Implementation for action signalEntered of state machine Svc_FpySequencer_SequencerStateMachine
255 //!
256 //! simply raises the "entered" signal
257 void Svc_FpySequencer_SequencerStateMachine_action_signalEntered(
258 SmId smId, //!< The state machine id
259 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
260 ) override;
261
262 //! Implementation for action setSequenceFilePath of state machine Svc_FpySequencer_SequencerStateMachine
263 //!
264 //! sets the current sequence file path member var
265 void Svc_FpySequencer_SequencerStateMachine_action_setSequenceFilePath(
266 SmId smId, //!< The state machine id
267 Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
268 const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
269 ) override;
270
271 //! Implementation for action setSequenceBlockState of state machine Svc_FpySequencer_SequencerStateMachine
272 //!
273 //! sets the block state of the sequence to be run
274 void Svc_FpySequencer_SequencerStateMachine_action_setSequenceBlockState(
275 SmId smId, //!< The state machine id
276 Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
277 const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
278 ) override;
279
280 //! Implementation for action setSequenceArguments of state machine Svc_FpySequencer_SequencerStateMachine
281 //!
282 //! sets the arguments to pass to the sequence
283 void Svc_FpySequencer_SequencerStateMachine_action_setSequenceArguments(
284 SmId smId, //!< The state machine id
285 Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
286 const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
287 ) override;
288
289 //! Implementation for action validate of state machine Svc_FpySequencer_SequencerStateMachine
290 //!
291 //! performs all steps necessary for sequence validation, and raises a signal result_success or result_failure
292 void Svc_FpySequencer_SequencerStateMachine_action_validate(
293 SmId smId, //!< The state machine id
294 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
295 ) override;
296
297 //! Implementation for action report_seqSucceeded of state machine Svc_FpySequencer_SequencerStateMachine
298 //!
299 //! reports that a sequence succeeded
300 void Svc_FpySequencer_SequencerStateMachine_action_report_seqSucceeded(
301 SmId smId, //!< The state machine id
302 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
303 ) override;
304
305 //! Implementation for action report_seqCancelled of state machine Svc_FpySequencer_SequencerStateMachine
306 //!
307 //! reports that a sequence was cancelled
308 void Svc_FpySequencer_SequencerStateMachine_action_report_seqCancelled(
309 SmId smId, //!< The state machine id
310 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
311 ) override;
312
313 //! Implementation for action setGoalState_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
314 //!
315 //! sets the goal state to RUNNING
316 void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_RUNNING(
317 SmId smId, //!< The state machine id
318 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
319 ) override;
320
321 //! Implementation for action setGoalState_VALID of state machine Svc_FpySequencer_SequencerStateMachine
322 //!
323 //! sets the goal state to VALID
324 void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_VALID(
325 SmId smId, //!< The state machine id
326 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
327 ) override;
328
329 //! Implementation for action setGoalState_IDLE of state machine Svc_FpySequencer_SequencerStateMachine
330 //!
331 //! sets the goal state to IDLE
332 void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_IDLE(
333 SmId smId, //!< The state machine id
334 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
335 ) override;
336
337 //! Implementation for action sendCmdResponse_OK of state machine Svc_FpySequencer_SequencerStateMachine
338 //!
339 //! responds to the calling command with OK
340 void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_OK(
341 SmId smId, //!< The state machine id
342 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
343 ) override;
344
345 //! Implementation for action sendCmdResponse_EXECUTION_ERROR of state machine
346 //! Svc_FpySequencer_SequencerStateMachine
347 //!
348 //! responds to the calling command with EXECUTION_ERROR
349 void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_EXECUTION_ERROR(
350 SmId smId, //!< The state machine id
351 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
352 ) override;
353
354 //! Implementation for action dispatchStatement of state machine Svc_FpySequencer_SequencerStateMachine
355 //!
356 //! iterates to the next statement and dispatches it
357 void Svc_FpySequencer_SequencerStateMachine_action_dispatchStatement(
358 SmId smId, //!< The state machine id
359 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
360 ) override;
361
362 //! Implementation for action clearSequenceFile of state machine Svc_FpySequencer_SequencerStateMachine
363 //!
364 //! clears all variables related to the loading/validating of the sequence file
365 void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceFile(
366 SmId smId, //!< The state machine id
367 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
368 ) override;
369
370 //! Implementation for action clearSequenceArguments of state machine Svc_FpySequencer_SequencerStateMachine
371 //!
372 //! clears arguments
373 void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceArguments(
374 SmId smId, //!< The state machine id
375 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
376 ) override;
377
378 //! Implementation for action checkShouldWake of state machine Svc_FpySequencer_SequencerStateMachine
379 //!
380 //! checks if sequencer should wake from sleep
381 void Svc_FpySequencer_SequencerStateMachine_action_checkShouldWake(
382 SmId smId, //!< The state machine id
383 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
384 ) override;
385
386 //! Implementation for action resetRuntime of state machine Svc_FpySequencer_SequencerStateMachine
387 //!
388 //! resets the sequence runtime
389 void Svc_FpySequencer_SequencerStateMachine_action_resetRuntime(
390 SmId smId, //!< The state machine id
391 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
392 ) override;
393
394 //! Implementation for action checkStatementTimeout of state machine Svc_FpySequencer_SequencerStateMachine
395 //!
396 //! checks if the current statement has timed out
397 void Svc_FpySequencer_SequencerStateMachine_action_checkStatementTimeout(
398 SmId smId, //!< The state machine id
399 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
400 ) override;
401
402 //! Implementation for action incrementSequenceCounter of state machine Svc_FpySequencer_SequencerStateMachine
403 //!
404 //! increments the m_sequencesStarted counter
405 void Svc_FpySequencer_SequencerStateMachine_action_incrementSequenceCounter(
406 SmId smId, //!< The state machine id
407 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
408 ) override;
409
410 //! Implementation for action pushArgsToStack of state machine Svc_FpySequencer_SequencerStateMachine
411 //!
412 //! pushes sequence arguments to the stack
413 void Svc_FpySequencer_SequencerStateMachine_action_pushArgsToStack(
414 SmId smId, //!< The state machine id
415 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
416 ) override;
417
418 //! Implementation for action clearBreakpoint of state machine Svc_FpySequencer_SequencerStateMachine
419 //!
420 //! clears the breakpoint, allowing execution of the sequence to continue
421 void Svc_FpySequencer_SequencerStateMachine_action_clearBreakpoint(
422 SmId smId, //!< The state machine id
423 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
424 ) override;
425
426 //! Implementation for action report_seqBroken of state machine Svc_FpySequencer_SequencerStateMachine
427 //!
428 //! reports that a breakpoint was hit
429 void Svc_FpySequencer_SequencerStateMachine_action_report_seqBroken(
430 SmId smId, //!< The state machine id
431 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
432 ) override;
433
434 //! Implementation for action setBreakpoint of state machine Svc_FpySequencer_SequencerStateMachine
435 //!
436 //! sets the breakpoint to the provided args
437 void Svc_FpySequencer_SequencerStateMachine_action_setBreakpoint(
438 SmId smId, //!< The state machine id
439 Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
440 const Svc::FpySequencer_BreakpointArgs& value //!< The value
441 ) override;
442
443 //! Implementation for action setBreakBeforeNextLine of state machine Svc_FpySequencer_SequencerStateMachine
444 //!
445 //! sets the "break on next line" flag to true
446 void Svc_FpySequencer_SequencerStateMachine_action_setBreakBeforeNextLine(
447 SmId smId, //!< The state machine id
448 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
449 ) override;
450
451 //! Implementation for action clearBreakBeforeNextLine of state machine Svc_FpySequencer_SequencerStateMachine
452 //!
453 //! sets the "break on next line" flag to false
454 void Svc_FpySequencer_SequencerStateMachine_action_clearBreakBeforeNextLine(
455 SmId smId, //!< The state machine id
456 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
457 ) override;
458
459 //! Implementation for action report_seqFailed of state machine Svc_FpySequencer_SequencerStateMachine
460 //!
461 //! called when a sequence failed to execute successfully
462 void Svc_FpySequencer_SequencerStateMachine_action_report_seqFailed(
463 SmId smId, //!< The state machine id
464 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
465 ) override;
466
467 //! Implementation for action report_seqStarted of state machine Svc_FpySequencer_SequencerStateMachine
468 //!
469 //! reports that a sequence was started
470 void Svc_FpySequencer_SequencerStateMachine_action_report_seqStarted(
471 SmId smId, //!< The state machine id
472 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
473 ) override;
474
475 protected:
476 // ----------------------------------------------------------------------
477 // Functions to implement for internal state machine guards
478 // ----------------------------------------------------------------------
479
480 //! Implementation for guard goalStateIs_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
481 //!
482 //! return true if the goal state is RUNNING
483 bool Svc_FpySequencer_SequencerStateMachine_guard_goalStateIs_RUNNING(
484 SmId smId, //!< The state machine id
485 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
486 ) const override;
487
488 //! Implementation for guard shouldBreak of state machine Svc_FpySequencer_SequencerStateMachine
489 //!
490 //! return true if should break at this point in execution, before dispatching
491 //! next stmt
492 bool Svc_FpySequencer_SequencerStateMachine_guard_shouldBreak(
493 SmId smId, //!< The state machine id
494 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
495 ) const override;
496
497 //! Implementation for guard breakOnce of state machine Svc_FpySequencer_SequencerStateMachine
498 //!
499 //! return true if this breakpoint should only happen once
500 bool Svc_FpySequencer_SequencerStateMachine_guard_breakOnce(
501 SmId smId, //!< The state machine id
502 Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
503 ) const override;
504
505 // ----------------------------------------------------------------------
506 // Handlers to implement for typed input ports
507 // ----------------------------------------------------------------------
508
509 //! Handler for input port checkTimers
510 void checkTimers_handler(FwIndexType portNum, //!< The port number
511 U32 context //!< The call order
512 ) override;
513
514 //! Handler for input port cmdResponseIn
515 void cmdResponseIn_handler(FwIndexType portNum, //!< The port number
516 FwOpcodeType opCode, //!< Command Op Code
517 U32 cmdSeq, //!< Command Sequence
518 const Fw::CmdResponse& response //!< The command response argument
519 ) override;
520
521 //! Handler for input port seqRunIn
522 void seqRunIn_handler(FwIndexType portNum, const Fw::StringBase& filename, const Svc::SeqArgs& args) override;
523
524 //! Handler implementation for seqCancelIn
525 //!
526 //! port for requesting to cancel the currently running sequence
527 void seqCancelIn_handler(FwIndexType portNum //!< The port number
528 ) override;
529
530 //! Handler for input port pingIn
531 void pingIn_handler(FwIndexType portNum, //!< The port number
532 U32 key //!< Value to return to pinger
533 ) override;
534
535 //! Handler for input port tlmWrite
536 void tlmWrite_handler(FwIndexType portNum, //!< The port number
537 U32 context //!< The call order
538 ) override;
539
540 //! Internal interface handler for directive_waitAbs
541 void directive_waitAbs_internalInterfaceHandler(const FpySequencer_WaitAbsDirective& directive) override;
542
543 //! Internal interface handler for directive_waitRel
544 void directive_waitRel_internalInterfaceHandler(const FpySequencer_WaitRelDirective& directive) override;
545
546 //! Internal interface handler for directive_goto
547 void directive_goto_internalInterfaceHandler(const Svc::FpySequencer_GotoDirective& directive) override;
548
549 //! Internal interface handler for directive_if
550 void directive_if_internalInterfaceHandler(const Svc::FpySequencer_IfDirective& directive) override;
551
552 //! Internal interface handler for directive_noOp
553 void directive_noOp_internalInterfaceHandler(const Svc::FpySequencer_NoOpDirective& directive) override;
554
555 //! Internal interface handler for directive_pushTlmVal
556 void directive_pushTlmVal_internalInterfaceHandler(const Svc::FpySequencer_PushTlmValDirective& directive) override;
557
558 //! Internal interface handler for directive_pushTlmValAndTime
559 void directive_pushTlmValAndTime_internalInterfaceHandler(
560 const Svc::FpySequencer_PushTlmValAndTimeDirective& directive) override;
561
562 //! Internal interface handler for directive_pushPrm
563 void directive_pushPrm_internalInterfaceHandler(const Svc::FpySequencer_PushPrmDirective& directive) override;
564
565 //! Internal interface handler for directive_constCmd
566 void directive_constCmd_internalInterfaceHandler(const Svc::FpySequencer_ConstCmdDirective& directive) override;
567
568 //! Internal interface handler for directive_stackOp
569 void directive_stackOp_internalInterfaceHandler(const Svc::FpySequencer_StackOpDirective& directive) override;
570
571 //! Internal interface handler for directive_exit
572 void directive_exit_internalInterfaceHandler(const Svc::FpySequencer_ExitDirective& directive) override;
573
574 //! Internal interface handler for directive_allocate
575 void directive_allocate_internalInterfaceHandler(const Svc::FpySequencer_AllocateDirective& directive) override;
576
577 //! Internal interface handler for directive_storeRelConstOffset
578 void directive_storeRelConstOffset_internalInterfaceHandler(
579 const Svc::FpySequencer_StoreRelConstOffsetDirective& directive) override;
580
581 //! Internal interface handler for directive_loadRel
582 void directive_loadRel_internalInterfaceHandler(const Svc::FpySequencer_LoadRelDirective& directive) override;
583
584 //! Internal interface handler for directive_pushVal
585 void directive_pushVal_internalInterfaceHandler(const Svc::FpySequencer_PushValDirective& directive) override;
586
587 //! Internal interface handler for directive_discard
588 void directive_discard_internalInterfaceHandler(const Svc::FpySequencer_DiscardDirective& directive) override;
589
590 //! Internal interface handler for directive_memCmp
591 void directive_memCmp_internalInterfaceHandler(const Svc::FpySequencer_MemCmpDirective& directive) override;
592
593 //! Internal interface handler for directive_stackCmd
594 void directive_stackCmd_internalInterfaceHandler(const Svc::FpySequencer_StackCmdDirective& directive) override;
595
596 //! Internal interface handler for directive_pushTime
597 void directive_pushTime_internalInterfaceHandler(const Svc::FpySequencer_PushTimeDirective& directive) override;
598
599 //! Internal interface handler for directive_setSeed
600 void directive_setSeed_internalInterfaceHandler(const Svc::FpySequencer_SetSeedDirective& directive) override;
601
602 //! Internal interface handler for directive_pushRand
603 void directive_pushRand_internalInterfaceHandler(const Svc::FpySequencer_PushRandDirective& directive) override;
604
605 //! Internal interface handler for directive_getField
606 void directive_getField_internalInterfaceHandler(const Svc::FpySequencer_GetFieldDirective& directive) override;
607
608 //! Internal interface handler for directive_peek
609 void directive_peek_internalInterfaceHandler(const Svc::FpySequencer_PeekDirective& directive) override;
610
611 //! Internal interface handler for directive_storeRel
612 void directive_storeRel_internalInterfaceHandler(const Svc::FpySequencer_StoreRelDirective& directive) override;
613
614 //! Internal interface handler for directive_call
615 void directive_call_internalInterfaceHandler(const Svc::FpySequencer_CallDirective& directive) override;
616
617 //! Internal interface handler for directive_return
618 void directive_return_internalInterfaceHandler(const Svc::FpySequencer_ReturnDirective& directive) override;
619
620 //! Internal interface handler for directive_loadAbs
621 void directive_loadAbs_internalInterfaceHandler(const Svc::FpySequencer_LoadAbsDirective& directive) override;
622
623 //! Internal interface handler for directive_storeAbs
624 void directive_storeAbs_internalInterfaceHandler(const Svc::FpySequencer_StoreAbsDirective& directive) override;
625
626 //! Internal interface handler for directive_storeAbsConstOffset
627 void directive_storeAbsConstOffset_internalInterfaceHandler(
628 const Svc::FpySequencer_StoreAbsConstOffsetDirective& directive) override;
629
630 //! Internal interface handler for directive_popEvent
631 void directive_popEvent_internalInterfaceHandler(const Svc::FpySequencer_PopEventDirective& directive) override;
632
633 //! Internal interface handler for directive_popSerializable
634 void directive_popSerializable_internalInterfaceHandler(
635 const Svc::FpySequencer_PopSerializableDirective& directive) override;
636
637 void parametersLoaded() override;
638 void parameterUpdated(FwPrmIdType id) override;
639
640 public:
641 void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes);
642
643 void deallocateBuffer(Fw::MemAllocator& allocator);
644
645 private:
646 static constexpr U32 CRC_INITIAL_VALUE = 0xFFFFFFFFU;
647
648 // allocated at startup
649 Fw::ExternalSerializeBuffer m_sequenceBuffer;
650 // id of allocator that gave us m_sequenceBuffer
651 FwEnumStoreType m_allocatorId;
652
653 // assigned by the user via cmd
654 // length is FileNameStringSize
655 Fw::FileNameString m_sequenceFilePath;
656 // the sequence, loaded in memory
657 Fpy::Sequence m_sequenceObj;
658 // live running computation of CRC (updated as we read)
659 Utils::Hash m_computedCRC;
660
661 // Size of arguments read in current sequence. Used for validation between
662 // User provided arguments and what is requested of the sequence.
663 Fpy::StackSizeType m_totalExpectedArgSize;
664
665 // whether or not the sequence we're about to run should return immediately or
666 // block on completion
667 Svc::BlockState m_sequenceBlockState;
668 // if we are to block on completion, save the opCode and cmdSeq we should
669 // return
670 FwOpcodeType m_savedOpCode;
671 U32 m_savedCmdSeq;
672
673 // sequence arguments to push to stack when entering RUNNING state
674 Svc::SeqArgs m_sequenceArgs{};
675
676 // the goal state is the state that we're trying to reach in the sequencer
677 // if it's RUNNING, then we should promptly go to RUNNING once we validate the
678 // sequence. if it's VALID, we should wait after VALIDATING
679 FpySequencer_GoalState m_goalState;
680
681 // the total number of sequences this sequencer has started since construction
682 U64 m_sequencesStarted;
683 // the total number of statements this sequencer has dispatched, successfully or
684 // otherwise, since construction
685 U64 m_statementsDispatched;
686
687 const Fw::String NO_SEQ{"<no seq>"};
688
689 // the runtime state of the sequence. encapsulates all state
690 // needed to run the sequence.
691 // this is distinct from the state of the sequencer. the
692 // sequencer and all its state is really just a shell to load
693 // and execute this runtime.
694 struct Runtime {
695 // the index of the next statement to be executed
696 U32 nextStatementIndex = 0;
697
698 // the opcode of the statement that is currently executing
699 U8 currentStatementOpcode = Fpy::DirectiveId::INVALID;
700 // the opcode of the command that we are currently awaiting, or 0 if we are executing a directive
701 FwOpcodeType currentCmdOpcode = 0;
702 // the time we dispatched the statement that is currently executing
703 Fw::Time currentStatementDispatchTime = Fw::Time();
704
705 // the absolute time we should wait for until returning
706 // a statement response
707 Fw::Time wakeupTime = Fw::Time();
708
709 // RNG state used by PUSH_RAND and SET_SEED directives during this run
710 std::mt19937 rng;
711 bool rngSeeded = false;
712
713 Stack stack = Stack();
714 } m_runtime;
715
716 // the state of the debugger. debugger is separate from runtime
717 // because it can be set up before running the sequence.
718 struct BreakpointInfo {
719 // whether or not to break at the debug breakpoint index
720 bool breakpointInUse = false;
721 // whether or not to remove the breakpoint after breaking on it
722 bool breakOnlyOnceOnBreakpoint = false;
723 // the statement index at which to break, before dispatching
724 U32 breakpointIndex = 0;
725 // whether or not to break before dispatching the next line,
726 // independent of what line it is.
727 // can be used in combination with breakpointIndex
728 bool breakBeforeNextLine = false;
729 } m_breakpoint;
730
731 // debug information about the sequence. only valid in the PAUSED state
732 // which you can access via BREAK or SET_BREAKPOINT cmds
733 struct DebugInfo {
734 // true if there are no statements remaining in the sequence file
735 bool reachedEndOfFile = false;
736 // true if we were able to deserialize the next statement successfully
737 bool nextStatementReadSuccess = false;
738 // the opcode of the next statement to dispatch.
739 U8 nextStatementOpcode = 0;
740 // if the next statement is a cmd directive, the opcode of that cmd
741 FwOpcodeType nextCmdOpcode = 0;
742 // the index of the next statement we're going to execute
743 U32 nextStatementIndex = 0;
744 // the size of the stack. store this separately from the real stack size
745 // so we can avoid changing this during runtime, only modify it during
746 // debug
747 Fpy::StackSizeType stackSize = 0;
748 } m_debug;
749
750 struct Telemetry {
751 // the number of statements that failed to execute
752 U64 statementsFailed = 0;
753 // the number of sequences successfully completed
754 U64 sequencesSucceeded = 0;
755 // the number of sequences that failed to validate or execute
756 U64 sequencesFailed = 0;
757 // the number of sequences that have been cancelled
758 U64 sequencesCancelled = 0;
759
760 // the error code of the last directive that ran
761 DirectiveError lastDirectiveError = DirectiveError::NO_ERROR;
762 // the index of the last directive that errored
763 U64 directiveErrorIndex = 0;
764 // the opcode of the last directive that errored
765 Fpy::DirectiveId directiveErrorId = Fpy::DirectiveId::INVALID;
766 } m_tlm;
767
768 // ----------------------------------------------------------------------
769 // Validation state
770 // ----------------------------------------------------------------------
771
772 // loads the sequence in memory, and does header/crc/integrity checks.
773 // return SUCCESS if sequence is valid, FAILURE otherwise
774 Fw::Success validate();
775 // reads and validates the header from the m_sequenceBuffer
776 // return SUCCESS if sequence is valid, FAILURE otherwise
777 Fw::Success readHeader();
778 // reads and validates the body from the m_sequenceBuffer
779 // return SUCCESS if sequence is valid, FAILURE otherwise
780 Fw::Success readBody();
781 // reads and validates the footer from the m_sequenceBuffer
782 // return SUCCESS if sequence is valid, FAILURE otherwise
783 Fw::Success readFooter();
784
785 // reads some bytes from the open file into the m_sequenceBuffer.
786 // updates the CRC by default, but can be turned off if the contents
787 // aren't included in CRC.
788 // return success if successful
789 Fw::Success readBytes(Os::File& file,
790 FwSizeType readLen,
791 const FpySequencer_FileReadStage& readStage,
792 bool updateCrc = true);
793
794 // ----------------------------------------------------------------------
795 // Run state
796 // ----------------------------------------------------------------------
797
798 // utility method for updating telemetry based on a directive error code
799 void handleDirectiveErrorCode(Fpy::DirectiveId id, DirectiveError err);
800
801 // dispatches the next statement
802 Signal dispatchStatement();
803
804 // deserializes a directive from bytes into the Fpy type
805 // returns success if able to deserialize, and returns the Fpy type object
806 // as a reference, in a union of all the possible directive type objects
807 Fw::Success deserializeDirective(const Fpy::Statement& stmt, DirectiveUnion& deserializedDirective);
808
809 // dispatches a deserialized sequencer directive to the right handler.
810 void dispatchDirective(const DirectiveUnion& directive, const Fpy::DirectiveId& id);
811
812 // checks whether the currently executing statement timed out
813 Signal checkStatementTimeout();
814
815 // checks whether the sequencer should wake from sleeping
816 Signal checkShouldWake();
817
818 // return true if state is a substate of RUNNING
819 bool isRunningState(State state);
820
821 // update a struct containing debug telemetry, or defaults if not in debug break
822 void updateDebugTelemetryStruct();
823
824 // ----------------------------------------------------------------------
825 // Directives
826 // ----------------------------------------------------------------------
827
828 // sends a signal based on a signal id
829 void sendSignal(Signal signal);
830
831 // dispatches a command, returns whether successful or not
832 Fw::Success sendCmd(FwOpcodeType opcode, const U8* argBuf, FwSizeType argBufSize);
833
834 // returns the index of the current statement
835 U32 currentStatementIdx();
836
837 // we split these functions up into the internalInterfaceInvoke and these custom member funcs
838 // so that we can unit test them easier
839 Signal waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& error);
840 Signal waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive, DirectiveError& error);
841 Signal goto_directiveHandler(const FpySequencer_GotoDirective& directive, DirectiveError& error);
842 Signal if_directiveHandler(const FpySequencer_IfDirective& directive, DirectiveError& error);
843 Signal noOp_directiveHandler(const FpySequencer_NoOpDirective& directive, DirectiveError& error);
844 Signal pushTlmVal_directiveHandler(const FpySequencer_PushTlmValDirective& directive, DirectiveError& error);
845 Signal pushTlmValAndTime_directiveHandler(const FpySequencer_PushTlmValAndTimeDirective& directive,
846 DirectiveError& error);
847 Signal pushPrm_directiveHandler(const FpySequencer_PushPrmDirective& directive, DirectiveError& error);
848 Signal constCmd_directiveHandler(const FpySequencer_ConstCmdDirective& directive, DirectiveError& error);
849 Signal stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive, DirectiveError& error);
850
851 DirectiveError op_or();
852 DirectiveError op_and();
853 DirectiveError op_ieq();
854 DirectiveError op_ine();
855 DirectiveError op_ult();
856 DirectiveError op_ule();
857 DirectiveError op_ugt();
858 DirectiveError op_uge();
859 DirectiveError op_slt();
860 DirectiveError op_sle();
861 DirectiveError op_sgt();
862 DirectiveError op_sge();
863 DirectiveError op_feq();
864 DirectiveError op_fne();
865 DirectiveError op_flt();
866 DirectiveError op_fle();
867 DirectiveError op_fgt();
868 DirectiveError op_fge();
869 DirectiveError op_not();
870 DirectiveError op_fpext();
871 DirectiveError op_fptrunc();
872 DirectiveError op_fptoui();
873 DirectiveError op_fptosi();
874 DirectiveError op_sitofp();
875 DirectiveError op_uitofp();
876 DirectiveError op_add();
877 DirectiveError op_sub();
878 DirectiveError op_mul();
879 DirectiveError op_udiv();
880 DirectiveError op_sdiv();
881 DirectiveError op_umod();
882 DirectiveError op_smod();
883 DirectiveError op_fadd();
884 DirectiveError op_fsub();
885 DirectiveError op_fmul();
886 DirectiveError op_fdiv();
887 DirectiveError op_fpow();
888 DirectiveError op_flog();
889 DirectiveError op_fmod();
890 DirectiveError op_siext_8_64();
891 DirectiveError op_siext_16_64();
892 DirectiveError op_siext_32_64();
893 DirectiveError op_ziext_8_64();
894 DirectiveError op_ziext_16_64();
895 DirectiveError op_ziext_32_64();
896 DirectiveError op_itrunc_64_8();
897 DirectiveError op_itrunc_64_16();
898 DirectiveError op_itrunc_64_32();
899 DirectiveError op_ffloor();
900 DirectiveError op_iabs();
901 DirectiveError op_fabs();
902
903 Signal exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& error);
904 Signal allocate_directiveHandler(const FpySequencer_AllocateDirective& directive, DirectiveError& error);
905 //! Helper to pop value from stack top and store at destOffset
906 Signal storeHelper(Fpy::StackSizeType destOffset, Fpy::StackSizeType size, DirectiveError& error);
907 //! Helper to load value from srcOffset and push to stack top
908 Signal loadHelper(Fpy::StackSizeType srcOffset, Fpy::StackSizeType size, DirectiveError& error);
909 Signal storeRelConstOffset_directiveHandler(const FpySequencer_StoreRelConstOffsetDirective& directive,
910 DirectiveError& error);
911 Signal loadRel_directiveHandler(const FpySequencer_LoadRelDirective& directive, DirectiveError& error);
912 Signal pushVal_directiveHandler(const FpySequencer_PushValDirective& directive, DirectiveError& error);
913 Signal discard_directiveHandler(const FpySequencer_DiscardDirective& directive, DirectiveError& error);
914 Signal memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive, DirectiveError& error);
915 Signal stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& error);
916 Signal pushTime_directiveHandler(const FpySequencer_PushTimeDirective& directive, DirectiveError& error);
917 Signal setSeed_directiveHandler(const FpySequencer_SetSeedDirective& directive, DirectiveError& error);
918 Signal pushRand_directiveHandler(const FpySequencer_PushRandDirective& directive, DirectiveError& error);
919 Signal getField_directiveHandler(const FpySequencer_GetFieldDirective& directive, DirectiveError& error);
920 Signal peek_directiveHandler(const FpySequencer_PeekDirective& directive, DirectiveError& error);
921 Signal storeRel_directiveHandler(const FpySequencer_StoreRelDirective& directive, DirectiveError& error);
922 Signal call_directiveHandler(const FpySequencer_CallDirective& directive, DirectiveError& error);
923 Signal return_directiveHandler(const FpySequencer_ReturnDirective& directive, DirectiveError& error);
924 Signal loadAbs_directiveHandler(const FpySequencer_LoadAbsDirective& directive, DirectiveError& error);
925 Signal storeAbs_directiveHandler(const FpySequencer_StoreAbsDirective& directive, DirectiveError& error);
926 Signal storeAbsConstOffset_directiveHandler(const FpySequencer_StoreAbsConstOffsetDirective& directive,
927 DirectiveError& error);
928 Signal popEvent_directiveHandler(const FpySequencer_PopEventDirective& directive, DirectiveError& error);
929 Signal popSerializable_directiveHandler(const FpySequencer_PopSerializableDirective& directive,
930 DirectiveError& error);
931 };
932
933 } // namespace Svc
934
935 #endif
936