GCC Code Coverage Report


Directory: ./
File: Svc/FpySequencer/FpySequencerRunState.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 0 394 0.0%
Functions: 0 6 0.0%
Branches: 0 596 0.0%

Line Branch Exec Source
1 #include <config/CommandDispatcherImplCfg.hpp>
2 #include <new>
3 #include "Fw/Com/ComPacket.hpp"
4 #include "Fw/Time/Time.hpp"
5 #include "Svc/FpySequencer/FpySequencer.hpp"
6
7 namespace Svc {
8
9 // returns the index of the current statement
10 U32 FpySequencer::currentStatementIdx() {
11 if (this->m_runtime.nextStatementIndex == 0) {
12 // haven't started executing the sequence yet
13 return 0;
14 }
15 return this->m_runtime.nextStatementIndex - 1;
16 }
17
18 Signal FpySequencer::dispatchStatement() {
19 // check to make sure no array out of bounds, or if it is out of bounds it's only 1 out of bound
20 // as that indicates eof
21 FW_ASSERT(this->m_runtime.nextStatementIndex <= this->m_sequenceObj.get_header().get_statementCount());
22
23 if (this->m_runtime.nextStatementIndex == this->m_sequenceObj.get_header().get_statementCount()) {
24 return Signal::result_dispatchStatement_noMoreStatements;
25 }
26
27 const Fpy::Statement& nextStatement = this->m_sequenceObj.get_statements()[this->m_runtime.nextStatementIndex];
28 this->m_runtime.nextStatementIndex++;
29 this->m_runtime.currentStatementOpcode = nextStatement.get_opCode();
30 this->m_runtime.currentCmdOpcode = 0; // we haven't deserialized the directive yet, so we don't know if it's a cmd
31
32 Fw::Success result;
33 DirectiveUnion directiveUnion;
34
35 result = this->deserializeDirective(nextStatement, directiveUnion);
36
37 if (!result) {
38 return Signal::result_dispatchStatement_failure;
39 }
40
41 if (this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::CONST_CMD) {
42 // update the opcode of the cmd we will await
43 this->m_runtime.currentCmdOpcode = directiveUnion.constCmd.get_opCode();
44 }
45
46 this->dispatchDirective(directiveUnion,
47 Fpy::DirectiveId(static_cast<Fpy::DirectiveId::T>(nextStatement.get_opCode())));
48 this->m_runtime.currentStatementDispatchTime =
49 getTime(); // set dispatch time right after we have successfully dispatched
50
51 this->m_statementsDispatched++;
52
53 return Signal::result_dispatchStatement_success;
54 }
55
56 // deserializes a directive from bytes into the Fpy type
57 // returns success if able to deserialize, and returns the Fpy type object
58 // as a reference, in a union of all the possible directive type objects
59 Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, DirectiveUnion& deserializedDirective) {
60 Fw::SerializeStatus status;
61 // make our own esb so we can deser from stmt without breaking its constness
62 Fw::ExternalSerializeBuffer argBuf(const_cast<U8*>(stmt.get_argBuf().getBuffAddr()), stmt.get_argBuf().getSize());
63 status = argBuf.setBuffLen(stmt.get_argBuf().getSize());
64 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
65
66 switch (stmt.get_opCode()) {
67 case Fpy::DirectiveId::WAIT_REL: {
68 // in order to use a type with non trivial ctor in cpp union, have to manually construct and destruct it
69 new (&deserializedDirective.waitRel) FpySequencer_WaitRelDirective();
70 // wait rel does not need deser
71 if (argBuf.getDeserializeSizeLeft() != 0) {
72 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
73 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
74 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
75 return Fw::Success::FAILURE;
76 }
77 return Fw::Success::SUCCESS;
78 }
79 case Fpy::DirectiveId::WAIT_ABS: {
80 new (&deserializedDirective.waitAbs) FpySequencer_WaitAbsDirective();
81 // wait abs does not need deser
82 if (argBuf.getDeserializeSizeLeft() != 0) {
83 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
84 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
85 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
86 return Fw::Success::FAILURE;
87 }
88 return Fw::Success::SUCCESS;
89 }
90 case Fpy::DirectiveId::GOTO: {
91 new (&deserializedDirective.gotoDirective) FpySequencer_GotoDirective();
92 status = argBuf.deserializeTo(deserializedDirective.gotoDirective);
93 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
94 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
95 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
96 return Fw::Success::FAILURE;
97 }
98 return Fw::Success::SUCCESS;
99 }
100 case Fpy::DirectiveId::IF: {
101 new (&deserializedDirective.ifDirective) FpySequencer_IfDirective();
102 status = argBuf.deserializeTo(deserializedDirective.ifDirective);
103 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
104 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
105 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
106 return Fw::Success::FAILURE;
107 }
108 return Fw::Success::SUCCESS;
109 }
110 case Fpy::DirectiveId::NO_OP: {
111 new (&deserializedDirective.noOp) FpySequencer_NoOpDirective();
112 // no op does not need deser
113 if (argBuf.getDeserializeSizeLeft() != 0) {
114 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
115 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
116 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
117 return Fw::Success::FAILURE;
118 }
119 return Fw::Success::SUCCESS;
120 }
121 case Fpy::DirectiveId::PUSH_TLM_VAL: {
122 new (&deserializedDirective.pushTlmVal) FpySequencer_PushTlmValDirective();
123 status = argBuf.deserializeTo(deserializedDirective.pushTlmVal);
124 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
125 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
126 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
127 return Fw::Success::FAILURE;
128 }
129 return Fw::Success::SUCCESS;
130 }
131 case Fpy::DirectiveId::PUSH_TLM_VAL_AND_TIME: {
132 new (&deserializedDirective.pushTlmValAndTime) FpySequencer_PushTlmValAndTimeDirective();
133 status = argBuf.deserializeTo(deserializedDirective.pushTlmValAndTime);
134 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
135 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
136 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
137 return Fw::Success::FAILURE;
138 }
139 return Fw::Success::SUCCESS;
140 }
141 case Fpy::DirectiveId::PUSH_PRM: {
142 new (&deserializedDirective.pushPrm) FpySequencer_PushPrmDirective();
143 status = argBuf.deserializeTo(deserializedDirective.pushPrm);
144 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
145 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
146 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
147 return Fw::Success::FAILURE;
148 }
149 return Fw::Success::SUCCESS;
150 }
151 case Fpy::DirectiveId::CONST_CMD: {
152 new (&deserializedDirective.constCmd) FpySequencer_ConstCmdDirective();
153
154 // first deserialize the opcode
155 FwOpcodeType opcode;
156 status = argBuf.deserializeTo(opcode);
157 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
158 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
159 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
160 return Fw::Success::FAILURE;
161 }
162
163 deserializedDirective.constCmd.set_opCode(opcode);
164 // how many bytes are left?
165 FwSizeType cmdArgBufSize = argBuf.getDeserializeSizeLeft();
166
167 // check to make sure the value will fit in the FpySequencer_ConstCmdDirective::argBuf
168 if (cmdArgBufSize > Fpy::MAX_DIRECTIVE_SIZE) {
169 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
170 Fw::SerializeStatus::FW_DESERIALIZE_FORMAT_ERROR,
171 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
172 return Fw::Success::FAILURE;
173 }
174
175 // okay, it will fit. put it in
176 status = argBuf.deserializeTo(deserializedDirective.constCmd.get_argBuf(), cmdArgBufSize,
177 Fw::Serialization::OMIT_LENGTH);
178
179 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
180 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
181 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
182 return Fw::Success::FAILURE;
183 }
184
185 // now there should be nothing left, otherwise coding err
186 FW_ASSERT(argBuf.getDeserializeSizeLeft() == 0,
187 static_cast<FwAssertArgType>(argBuf.getDeserializeSizeLeft()));
188
189 // and set the buf size now that we know it
190 deserializedDirective.constCmd.set__argBufSize(cmdArgBufSize);
191 return Fw::Success::SUCCESS;
192 }
193 // fallthrough on purpose
194 case Fpy::DirectiveId::OR:
195 case Fpy::DirectiveId::AND:
196 case Fpy::DirectiveId::IEQ:
197 case Fpy::DirectiveId::INE:
198 case Fpy::DirectiveId::UGT:
199 case Fpy::DirectiveId::ULT:
200 case Fpy::DirectiveId::ULE:
201 case Fpy::DirectiveId::UGE:
202 case Fpy::DirectiveId::SGT:
203 case Fpy::DirectiveId::SLT:
204 case Fpy::DirectiveId::SLE:
205 case Fpy::DirectiveId::SGE:
206 case Fpy::DirectiveId::FEQ:
207 case Fpy::DirectiveId::FNE:
208 case Fpy::DirectiveId::FLT:
209 case Fpy::DirectiveId::FLE:
210 case Fpy::DirectiveId::FGT:
211 case Fpy::DirectiveId::FGE:
212 case Fpy::DirectiveId::NOT:
213 case Fpy::DirectiveId::FPEXT:
214 case Fpy::DirectiveId::FPTRUNC:
215 case Fpy::DirectiveId::FPTOSI:
216 case Fpy::DirectiveId::FPTOUI:
217 case Fpy::DirectiveId::SITOFP:
218 case Fpy::DirectiveId::UITOFP:
219 case Fpy::DirectiveId::ADD:
220 case Fpy::DirectiveId::SUB:
221 case Fpy::DirectiveId::MUL:
222 case Fpy::DirectiveId::UDIV:
223 case Fpy::DirectiveId::SDIV:
224 case Fpy::DirectiveId::UMOD:
225 case Fpy::DirectiveId::SMOD:
226 case Fpy::DirectiveId::FADD:
227 case Fpy::DirectiveId::FSUB:
228 case Fpy::DirectiveId::FMUL:
229 case Fpy::DirectiveId::FDIV:
230 case Fpy::DirectiveId::FPOW:
231 case Fpy::DirectiveId::FLOG:
232 case Fpy::DirectiveId::FMOD:
233 case Fpy::DirectiveId::SIEXT_8_64:
234 case Fpy::DirectiveId::SIEXT_16_64:
235 case Fpy::DirectiveId::SIEXT_32_64:
236 case Fpy::DirectiveId::ZIEXT_8_64:
237 case Fpy::DirectiveId::ZIEXT_16_64:
238 case Fpy::DirectiveId::ZIEXT_32_64:
239 case Fpy::DirectiveId::ITRUNC_64_8:
240 case Fpy::DirectiveId::ITRUNC_64_16:
241 case Fpy::DirectiveId::ITRUNC_64_32:
242 case Fpy::DirectiveId::FFLOOR:
243 case Fpy::DirectiveId::IABS:
244 case Fpy::DirectiveId::FABS: {
245 new (&deserializedDirective.stackOp) FpySequencer_StackOpDirective();
246 if (argBuf.getDeserializeSizeLeft() != 0) {
247 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
248 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
249 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
250 return Fw::Success::FAILURE;
251 }
252 deserializedDirective.stackOp.set__op(stmt.get_opCode());
253 return Fw::Success::SUCCESS;
254 }
255 case Fpy::DirectiveId::EXIT: {
256 new (&deserializedDirective.exit) FpySequencer_ExitDirective();
257 if (argBuf.getDeserializeSizeLeft() != 0) {
258 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
259 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
260 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
261 return Fw::Success::FAILURE;
262 }
263 return Fw::Success::SUCCESS;
264 }
265 case Fpy::DirectiveId::ALLOCATE: {
266 new (&deserializedDirective.allocate) FpySequencer_AllocateDirective();
267 status = argBuf.deserializeTo(deserializedDirective.allocate);
268 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
269 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
270 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
271 return Fw::Success::FAILURE;
272 }
273 return Fw::Success::SUCCESS;
274 }
275 case Fpy::DirectiveId::STORE_REL_CONST_OFFSET: {
276 new (&deserializedDirective.storeRelConstOffset) FpySequencer_StoreRelConstOffsetDirective();
277 status = argBuf.deserializeTo(deserializedDirective.storeRelConstOffset);
278 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
279 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
280 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
281 return Fw::Success::FAILURE;
282 }
283 return Fw::Success::SUCCESS;
284 }
285 case Fpy::DirectiveId::LOAD_REL: {
286 new (&deserializedDirective.loadRel) FpySequencer_LoadRelDirective();
287 status = argBuf.deserializeTo(deserializedDirective.loadRel);
288 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
289 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
290 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
291 return Fw::Success::FAILURE;
292 }
293 return Fw::Success::SUCCESS;
294 }
295 case Fpy::DirectiveId::PUSH_VAL: {
296 new (&deserializedDirective.pushVal) FpySequencer_PushValDirective();
297
298 // how many bytes are left?
299 FwSizeType bufSize = argBuf.getDeserializeSizeLeft();
300
301 // check to make sure the value will fit in the FpySequencer_PushValDirective::val buf
302 if (bufSize > Fpy::MAX_DIRECTIVE_SIZE) {
303 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
304 Fw::SerializeStatus::FW_DESERIALIZE_FORMAT_ERROR,
305 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
306 return Fw::Success::FAILURE;
307 }
308
309 // okay, it will fit. put it in
310 status =
311 argBuf.deserializeTo(deserializedDirective.pushVal.get_val(), bufSize, Fw::Serialization::OMIT_LENGTH);
312
313 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
314 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
315 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
316 return Fw::Success::FAILURE;
317 }
318
319 // now there should be nothing left, otherwise coding err
320 FW_ASSERT(argBuf.getDeserializeSizeLeft() == 0,
321 static_cast<FwAssertArgType>(argBuf.getDeserializeSizeLeft()));
322
323 // and set the buf size now that we know it
324 deserializedDirective.pushVal.set__valSize(bufSize);
325 return Fw::Success::SUCCESS;
326 }
327 case Fpy::DirectiveId::DISCARD: {
328 new (&deserializedDirective.discard) FpySequencer_DiscardDirective();
329 status = argBuf.deserializeTo(deserializedDirective.discard);
330 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
331 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
332 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
333 return Fw::Success::FAILURE;
334 }
335 return Fw::Success::SUCCESS;
336 }
337 case Fpy::DirectiveId::MEMCMP: {
338 new (&deserializedDirective.memCmp) FpySequencer_MemCmpDirective();
339 status = argBuf.deserializeTo(deserializedDirective.memCmp);
340 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
341 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
342 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
343 return Fw::Success::FAILURE;
344 }
345 return Fw::Success::SUCCESS;
346 }
347 case Fpy::DirectiveId::STACK_CMD: {
348 new (&deserializedDirective.stackCmd) FpySequencer_StackCmdDirective();
349 status = argBuf.deserializeTo(deserializedDirective.stackCmd);
350 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
351 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
352 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
353 return Fw::Success::FAILURE;
354 }
355 return Fw::Success::SUCCESS;
356 }
357 case Fpy::DirectiveId::PUSH_TIME: {
358 new (&deserializedDirective.pushTime) FpySequencer_PushTimeDirective();
359 if (argBuf.getDeserializeSizeLeft() != 0) {
360 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
361 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
362 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
363 return Fw::Success::FAILURE;
364 }
365 return Fw::Success::SUCCESS;
366 }
367 case Fpy::DirectiveId::SET_SEED: {
368 new (&deserializedDirective.setSeed) FpySequencer_SetSeedDirective();
369 if (argBuf.getDeserializeSizeLeft() != 0) {
370 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
371 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
372 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
373 return Fw::Success::FAILURE;
374 }
375 return Fw::Success::SUCCESS;
376 }
377 case Fpy::DirectiveId::PUSH_RAND: {
378 new (&deserializedDirective.pushRand) FpySequencer_PushRandDirective();
379 if (argBuf.getDeserializeSizeLeft() != 0) {
380 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
381 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
382 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
383 return Fw::Success::FAILURE;
384 }
385 return Fw::Success::SUCCESS;
386 }
387 case Fpy::DirectiveId::GET_FIELD: {
388 new (&deserializedDirective.getField) FpySequencer_GetFieldDirective();
389 status = argBuf.deserializeTo(deserializedDirective.getField);
390 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
391 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
392 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
393 return Fw::Success::FAILURE;
394 }
395 return Fw::Success::SUCCESS;
396 }
397 case Fpy::DirectiveId::PEEK: {
398 new (&deserializedDirective.peek) FpySequencer_PeekDirective();
399 if (argBuf.getDeserializeSizeLeft() != 0) {
400 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
401 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
402 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
403 return Fw::Success::FAILURE;
404 }
405 return Fw::Success::SUCCESS;
406 }
407 case Fpy::DirectiveId::STORE_REL: {
408 new (&deserializedDirective.storeRel) FpySequencer_StoreRelDirective();
409 status = argBuf.deserializeTo(deserializedDirective.storeRel);
410 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
411 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
412 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
413 return Fw::Success::FAILURE;
414 }
415 return Fw::Success::SUCCESS;
416 }
417 case Fpy::DirectiveId::CALL: {
418 new (&deserializedDirective.call) FpySequencer_CallDirective();
419 if (argBuf.getDeserializeSizeLeft() != 0) {
420 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
421 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
422 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
423 return Fw::Success::FAILURE;
424 }
425 return Fw::Success::SUCCESS;
426 }
427 case Fpy::DirectiveId::RETURN: {
428 new (&deserializedDirective.returnDirective) FpySequencer_ReturnDirective();
429 status = argBuf.deserializeTo(deserializedDirective.returnDirective);
430 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
431 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
432 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
433 return Fw::Success::FAILURE;
434 }
435 return Fw::Success::SUCCESS;
436 }
437 case Fpy::DirectiveId::LOAD_ABS: {
438 new (&deserializedDirective.loadAbs) FpySequencer_LoadAbsDirective();
439 status = argBuf.deserializeTo(deserializedDirective.loadAbs);
440 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
441 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
442 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
443 return Fw::Success::FAILURE;
444 }
445 return Fw::Success::SUCCESS;
446 }
447 case Fpy::DirectiveId::STORE_ABS: {
448 new (&deserializedDirective.storeAbs) FpySequencer_StoreAbsDirective();
449 status = argBuf.deserializeTo(deserializedDirective.storeAbs);
450 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
451 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
452 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
453 return Fw::Success::FAILURE;
454 }
455 return Fw::Success::SUCCESS;
456 }
457 case Fpy::DirectiveId::STORE_ABS_CONST_OFFSET: {
458 new (&deserializedDirective.storeAbsConstOffset) FpySequencer_StoreAbsConstOffsetDirective();
459 status = argBuf.deserializeTo(deserializedDirective.storeAbsConstOffset);
460 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
461 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
462 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
463 return Fw::Success::FAILURE;
464 }
465 return Fw::Success::SUCCESS;
466 }
467 case Fpy::DirectiveId::POP_EVENT: {
468 new (&deserializedDirective.popEvent) FpySequencer_PopEventDirective();
469 // pop event has no hardcoded args
470 if (argBuf.getDeserializeSizeLeft() != 0) {
471 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
472 Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
473 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
474 return Fw::Success::FAILURE;
475 }
476 return Fw::Success::SUCCESS;
477 }
478 case Fpy::DirectiveId::POP_SERIALIZABLE: {
479 new (&deserializedDirective.popSerializable) FpySequencer_PopSerializableDirective();
480 status = argBuf.deserializeTo(deserializedDirective.popSerializable);
481 if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getDeserializeSizeLeft() != 0) {
482 this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
483 argBuf.getDeserializeSizeLeft(), argBuf.getSize());
484 return Fw::Success::FAILURE;
485 }
486 return Fw::Success::SUCCESS;
487 }
488 case Fpy::DirectiveId::INVALID: {
489 // unsure what this opcode is. check compiler version matches sequencer
490 break;
491 }
492 // ommited default case to throw compile error on unhandled directives.
493 }
494 this->log_WARNING_HI_UnknownSequencerDirective(stmt.get_opCode(), this->currentStatementIdx(),
495 this->m_sequenceFilePath);
496 return Fw::Success::FAILURE;
497 }
498
499 // dispatches a deserialized sequencer directive to the right handler.
500 void FpySequencer::dispatchDirective(const DirectiveUnion& directive, const Fpy::DirectiveId& id) {
501 switch (id) {
502 case Fpy::DirectiveId::INVALID: {
503 // coding err
504 FW_ASSERT(false);
505 return;
506 }
507 case Fpy::DirectiveId::WAIT_REL: {
508 this->directive_waitRel_internalInterfaceInvoke(directive.waitRel);
509 return;
510 }
511 case Fpy::DirectiveId::WAIT_ABS: {
512 this->directive_waitAbs_internalInterfaceInvoke(directive.waitAbs);
513 return;
514 }
515 case Fpy::DirectiveId::GOTO: {
516 this->directive_goto_internalInterfaceInvoke(directive.gotoDirective);
517 return;
518 }
519 case Fpy::DirectiveId::IF: {
520 this->directive_if_internalInterfaceInvoke(directive.ifDirective);
521 return;
522 }
523 case Fpy::DirectiveId::NO_OP: {
524 this->directive_noOp_internalInterfaceInvoke(directive.noOp);
525 return;
526 }
527 case Fpy::DirectiveId::PUSH_TLM_VAL: {
528 this->directive_pushTlmVal_internalInterfaceInvoke(directive.pushTlmVal);
529 return;
530 }
531 case Fpy::DirectiveId::PUSH_TLM_VAL_AND_TIME: {
532 this->directive_pushTlmValAndTime_internalInterfaceInvoke(directive.pushTlmValAndTime);
533 return;
534 }
535 case Fpy::DirectiveId::PUSH_PRM: {
536 this->directive_pushPrm_internalInterfaceInvoke(directive.pushPrm);
537 return;
538 }
539 case Fpy::DirectiveId::CONST_CMD: {
540 this->directive_constCmd_internalInterfaceInvoke(directive.constCmd);
541 return;
542 }
543 // fallthrough on purpose
544 case Fpy::DirectiveId::OR:
545 case Fpy::DirectiveId::AND:
546 case Fpy::DirectiveId::IEQ:
547 case Fpy::DirectiveId::INE:
548 case Fpy::DirectiveId::UGT:
549 case Fpy::DirectiveId::ULT:
550 case Fpy::DirectiveId::ULE:
551 case Fpy::DirectiveId::UGE:
552 case Fpy::DirectiveId::SGT:
553 case Fpy::DirectiveId::SLT:
554 case Fpy::DirectiveId::SLE:
555 case Fpy::DirectiveId::SGE:
556 case Fpy::DirectiveId::FEQ:
557 case Fpy::DirectiveId::FNE:
558 case Fpy::DirectiveId::FLT:
559 case Fpy::DirectiveId::FLE:
560 case Fpy::DirectiveId::FGT:
561 case Fpy::DirectiveId::FGE:
562 case Fpy::DirectiveId::NOT:
563 case Fpy::DirectiveId::FPEXT:
564 case Fpy::DirectiveId::FPTRUNC:
565 case Fpy::DirectiveId::FPTOSI:
566 case Fpy::DirectiveId::FPTOUI:
567 case Fpy::DirectiveId::SITOFP:
568 case Fpy::DirectiveId::UITOFP:
569 case Fpy::DirectiveId::ADD:
570 case Fpy::DirectiveId::SUB:
571 case Fpy::DirectiveId::MUL:
572 case Fpy::DirectiveId::UDIV:
573 case Fpy::DirectiveId::SDIV:
574 case Fpy::DirectiveId::UMOD:
575 case Fpy::DirectiveId::SMOD:
576 case Fpy::DirectiveId::FADD:
577 case Fpy::DirectiveId::FSUB:
578 case Fpy::DirectiveId::FMUL:
579 case Fpy::DirectiveId::FDIV:
580 case Fpy::DirectiveId::FPOW:
581 case Fpy::DirectiveId::FLOG:
582 case Fpy::DirectiveId::FMOD:
583 case Fpy::DirectiveId::SIEXT_8_64:
584 case Fpy::DirectiveId::SIEXT_16_64:
585 case Fpy::DirectiveId::SIEXT_32_64:
586 case Fpy::DirectiveId::ZIEXT_8_64:
587 case Fpy::DirectiveId::ZIEXT_16_64:
588 case Fpy::DirectiveId::ZIEXT_32_64:
589 case Fpy::DirectiveId::ITRUNC_64_8:
590 case Fpy::DirectiveId::ITRUNC_64_16:
591 case Fpy::DirectiveId::ITRUNC_64_32:
592 case Fpy::DirectiveId::FFLOOR:
593 case Fpy::DirectiveId::IABS:
594 case Fpy::DirectiveId::FABS: {
595 this->directive_stackOp_internalInterfaceInvoke(directive.stackOp);
596 return;
597 }
598 case Fpy::DirectiveId::EXIT: {
599 this->directive_exit_internalInterfaceInvoke(directive.exit);
600 return;
601 }
602 case Fpy::DirectiveId::ALLOCATE: {
603 this->directive_allocate_internalInterfaceInvoke(directive.allocate);
604 return;
605 }
606 case Fpy::DirectiveId::STORE_REL_CONST_OFFSET: {
607 this->directive_storeRelConstOffset_internalInterfaceInvoke(directive.storeRelConstOffset);
608 return;
609 }
610 case Fpy::DirectiveId::LOAD_REL: {
611 this->directive_loadRel_internalInterfaceInvoke(directive.loadRel);
612 return;
613 }
614 case Fpy::DirectiveId::PUSH_VAL: {
615 this->directive_pushVal_internalInterfaceInvoke(directive.pushVal);
616 return;
617 }
618 case Fpy::DirectiveId::DISCARD: {
619 this->directive_discard_internalInterfaceInvoke(directive.discard);
620 return;
621 }
622 case Fpy::DirectiveId::MEMCMP: {
623 this->directive_memCmp_internalInterfaceInvoke(directive.memCmp);
624 return;
625 }
626 case Fpy::DirectiveId::STACK_CMD: {
627 this->directive_stackCmd_internalInterfaceInvoke(directive.stackCmd);
628 return;
629 }
630 case Fpy::DirectiveId::PUSH_TIME: {
631 this->directive_pushTime_internalInterfaceInvoke(directive.pushTime);
632 return;
633 }
634 case Fpy::DirectiveId::SET_SEED: {
635 this->directive_setSeed_internalInterfaceInvoke(directive.setSeed);
636 return;
637 }
638 case Fpy::DirectiveId::PUSH_RAND: {
639 this->directive_pushRand_internalInterfaceInvoke(directive.pushRand);
640 return;
641 }
642 case Fpy::DirectiveId::GET_FIELD: {
643 this->directive_getField_internalInterfaceInvoke(directive.getField);
644 return;
645 }
646 case Fpy::DirectiveId::PEEK: {
647 this->directive_peek_internalInterfaceInvoke(directive.peek);
648 return;
649 }
650 case Fpy::DirectiveId::STORE_REL: {
651 this->directive_storeRel_internalInterfaceInvoke(directive.storeRel);
652 return;
653 }
654 case Fpy::DirectiveId::CALL: {
655 this->directive_call_internalInterfaceInvoke(directive.call);
656 return;
657 }
658 case Fpy::DirectiveId::RETURN: {
659 this->directive_return_internalInterfaceInvoke(directive.returnDirective);
660 return;
661 }
662 case Fpy::DirectiveId::LOAD_ABS: {
663 this->directive_loadAbs_internalInterfaceInvoke(directive.loadAbs);
664 return;
665 }
666 case Fpy::DirectiveId::STORE_ABS: {
667 this->directive_storeAbs_internalInterfaceInvoke(directive.storeAbs);
668 return;
669 }
670 case Fpy::DirectiveId::STORE_ABS_CONST_OFFSET: {
671 this->directive_storeAbsConstOffset_internalInterfaceInvoke(directive.storeAbsConstOffset);
672 return;
673 }
674 case Fpy::DirectiveId::POP_EVENT: {
675 this->directive_popEvent_internalInterfaceInvoke(directive.popEvent);
676 return;
677 }
678 case Fpy::DirectiveId::POP_SERIALIZABLE: {
679 this->directive_popSerializable_internalInterfaceInvoke(directive.popSerializable);
680 return;
681 }
682 }
683 // coding err
684 FW_ASSERT(false, static_cast<FwAssertArgType>(id));
685 }
686
687 Signal FpySequencer::checkShouldWake() {
688 Fw::Time currentTime = this->getTime();
689
690 if (currentTime.getTimeBase() != this->m_runtime.wakeupTime.getTimeBase()) {
691 // cannot compare these times.
692 this->log_WARNING_HI_MismatchedTimeBase(currentTime.getTimeBase(), this->m_runtime.wakeupTime.getTimeBase());
693
694 return Signal::result_timeOpFailed;
695 }
696
697 // Do not compare time context
698
699 if (currentTime < this->m_runtime.wakeupTime) {
700 // not time to wake up!
701 return Signal::result_checkShouldWake_keepSleeping;
702 }
703
704 // say we've finished our sleep
705 return Signal::result_checkShouldWake_wakeup;
706 }
707
708 // checks whether the currently executing statement timed out
709 Signal FpySequencer::checkStatementTimeout() {
710 Fw::ParamValid valid;
711 F32 timeout = this->paramGet_STATEMENT_TIMEOUT_SECS(valid);
712 if (timeout <= 0 || timeout > static_cast<F32>(std::numeric_limits<U32>::max())) {
713 // no timeout
714 return Signal::result_checkStatementTimeout_noTimeout;
715 }
716
717 Fw::Time currentTime = getTime();
718
719 if (currentTime.getTimeBase() != this->m_runtime.currentStatementDispatchTime.getTimeBase()) {
720 // can't compare time base. must have changed
721 this->log_WARNING_HI_MismatchedTimeBase(currentTime.getTimeBase(),
722 this->m_runtime.currentStatementDispatchTime.getTimeBase());
723 return Signal::result_timeOpFailed;
724 }
725
726 // Do not compare time context
727
728 if (this->m_runtime.currentStatementDispatchTime.getSeconds() > currentTime.getSeconds()) {
729 // somehow we've gone back in time... just ignore it and move on. should get fixed
730 // if we wait I guess
731 return Signal::result_checkStatementTimeout_noTimeout;
732 }
733
734 if (this->m_runtime.currentStatementDispatchTime.getSeconds() == currentTime.getSeconds() &&
735 this->m_runtime.currentStatementDispatchTime.getUSeconds() > currentTime.getUSeconds()) {
736 // same as above
737 return Signal::result_checkStatementTimeout_noTimeout;
738 }
739
740 U64 currentUSeconds = static_cast<U64>(currentTime.getSeconds()) * 1000000 + currentTime.getUSeconds();
741 U64 dispatchUSeconds = static_cast<U64>(this->m_runtime.currentStatementDispatchTime.getSeconds()) * 1000000 +
742 this->m_runtime.currentStatementDispatchTime.getUSeconds();
743
744 U64 timeoutUSeconds = static_cast<U64>(timeout * 1000000.0f);
745
746 if (currentUSeconds - dispatchUSeconds < timeoutUSeconds) {
747 // not over timeout
748 return Signal::result_checkStatementTimeout_noTimeout;
749 }
750
751 // we timed out
752 if (this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::CONST_CMD ||
753 this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::STACK_CMD) {
754 // if we were executing a command, warn that the cmd timed out with its opcode
755 this->log_WARNING_HI_CommandTimedOut(CmdDispatcherCfg::getEventOpcode(this->m_runtime.currentCmdOpcode),
756 this->currentStatementIdx(), this->m_sequenceFilePath);
757 } else {
758 this->log_WARNING_HI_DirectiveTimedOut(this->m_runtime.currentStatementOpcode, this->currentStatementIdx(),
759 this->m_sequenceFilePath);
760 }
761
762 return Signal::result_checkStatementTimeout_statementTimeout;
763 }
764
765 } // namespace Svc
766