GCC Code Coverage Report


Directory: ./
File: Svc/FpySequencer/FpySequencerRunState.cpp
Date: 2026-11-03 22:10:14
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, this->m_sequencesStarted);
509 ✗ return;
510 }
511 ✗ case Fpy::DirectiveId::WAIT_ABS: {
512 ✗ this->directive_waitAbs_internalInterfaceInvoke(directive.waitAbs, this->m_sequencesStarted);
513 ✗ return;
514 }
515 ✗ case Fpy::DirectiveId::GOTO: {
516 ✗ this->directive_goto_internalInterfaceInvoke(directive.gotoDirective, this->m_sequencesStarted);
517 ✗ return;
518 }
519 ✗ case Fpy::DirectiveId::IF: {
520 ✗ this->directive_if_internalInterfaceInvoke(directive.ifDirective, this->m_sequencesStarted);
521 ✗ return;
522 }
523 ✗ case Fpy::DirectiveId::NO_OP: {
524 ✗ this->directive_noOp_internalInterfaceInvoke(directive.noOp, this->m_sequencesStarted);
525 ✗ return;
526 }
527 ✗ case Fpy::DirectiveId::PUSH_TLM_VAL: {
528 ✗ this->directive_pushTlmVal_internalInterfaceInvoke(directive.pushTlmVal, this->m_sequencesStarted);
529 ✗ return;
530 }
531 ✗ case Fpy::DirectiveId::PUSH_TLM_VAL_AND_TIME: {
532 ✗ this->directive_pushTlmValAndTime_internalInterfaceInvoke(directive.pushTlmValAndTime,
533 this->m_sequencesStarted);
534 ✗ return;
535 }
536 ✗ case Fpy::DirectiveId::PUSH_PRM: {
537 ✗ this->directive_pushPrm_internalInterfaceInvoke(directive.pushPrm, this->m_sequencesStarted);
538 ✗ return;
539 }
540 ✗ case Fpy::DirectiveId::CONST_CMD: {
541 ✗ this->directive_constCmd_internalInterfaceInvoke(directive.constCmd, this->m_sequencesStarted);
542 ✗ return;
543 }
544 // fallthrough on purpose
545 ✗ case Fpy::DirectiveId::OR:
546 case Fpy::DirectiveId::AND:
547 case Fpy::DirectiveId::IEQ:
548 case Fpy::DirectiveId::INE:
549 case Fpy::DirectiveId::UGT:
550 case Fpy::DirectiveId::ULT:
551 case Fpy::DirectiveId::ULE:
552 case Fpy::DirectiveId::UGE:
553 case Fpy::DirectiveId::SGT:
554 case Fpy::DirectiveId::SLT:
555 case Fpy::DirectiveId::SLE:
556 case Fpy::DirectiveId::SGE:
557 case Fpy::DirectiveId::FEQ:
558 case Fpy::DirectiveId::FNE:
559 case Fpy::DirectiveId::FLT:
560 case Fpy::DirectiveId::FLE:
561 case Fpy::DirectiveId::FGT:
562 case Fpy::DirectiveId::FGE:
563 case Fpy::DirectiveId::NOT:
564 case Fpy::DirectiveId::FPEXT:
565 case Fpy::DirectiveId::FPTRUNC:
566 case Fpy::DirectiveId::FPTOSI:
567 case Fpy::DirectiveId::FPTOUI:
568 case Fpy::DirectiveId::SITOFP:
569 case Fpy::DirectiveId::UITOFP:
570 case Fpy::DirectiveId::ADD:
571 case Fpy::DirectiveId::SUB:
572 case Fpy::DirectiveId::MUL:
573 case Fpy::DirectiveId::UDIV:
574 case Fpy::DirectiveId::SDIV:
575 case Fpy::DirectiveId::UMOD:
576 case Fpy::DirectiveId::SMOD:
577 case Fpy::DirectiveId::FADD:
578 case Fpy::DirectiveId::FSUB:
579 case Fpy::DirectiveId::FMUL:
580 case Fpy::DirectiveId::FDIV:
581 case Fpy::DirectiveId::FPOW:
582 case Fpy::DirectiveId::FLOG:
583 case Fpy::DirectiveId::FMOD:
584 case Fpy::DirectiveId::SIEXT_8_64:
585 case Fpy::DirectiveId::SIEXT_16_64:
586 case Fpy::DirectiveId::SIEXT_32_64:
587 case Fpy::DirectiveId::ZIEXT_8_64:
588 case Fpy::DirectiveId::ZIEXT_16_64:
589 case Fpy::DirectiveId::ZIEXT_32_64:
590 case Fpy::DirectiveId::ITRUNC_64_8:
591 case Fpy::DirectiveId::ITRUNC_64_16:
592 case Fpy::DirectiveId::ITRUNC_64_32:
593 case Fpy::DirectiveId::FFLOOR:
594 case Fpy::DirectiveId::IABS:
595 case Fpy::DirectiveId::FABS: {
596 ✗ this->directive_stackOp_internalInterfaceInvoke(directive.stackOp, this->m_sequencesStarted);
597 ✗ return;
598 }
599 ✗ case Fpy::DirectiveId::EXIT: {
600 ✗ this->directive_exit_internalInterfaceInvoke(directive.exit, this->m_sequencesStarted);
601 ✗ return;
602 }
603 ✗ case Fpy::DirectiveId::ALLOCATE: {
604 ✗ this->directive_allocate_internalInterfaceInvoke(directive.allocate, this->m_sequencesStarted);
605 ✗ return;
606 }
607 ✗ case Fpy::DirectiveId::STORE_REL_CONST_OFFSET: {
608 ✗ this->directive_storeRelConstOffset_internalInterfaceInvoke(directive.storeRelConstOffset,
609 this->m_sequencesStarted);
610 ✗ return;
611 }
612 ✗ case Fpy::DirectiveId::LOAD_REL: {
613 ✗ this->directive_loadRel_internalInterfaceInvoke(directive.loadRel, this->m_sequencesStarted);
614 ✗ return;
615 }
616 ✗ case Fpy::DirectiveId::PUSH_VAL: {
617 ✗ this->directive_pushVal_internalInterfaceInvoke(directive.pushVal, this->m_sequencesStarted);
618 ✗ return;
619 }
620 ✗ case Fpy::DirectiveId::DISCARD: {
621 ✗ this->directive_discard_internalInterfaceInvoke(directive.discard, this->m_sequencesStarted);
622 ✗ return;
623 }
624 ✗ case Fpy::DirectiveId::MEMCMP: {
625 ✗ this->directive_memCmp_internalInterfaceInvoke(directive.memCmp, this->m_sequencesStarted);
626 ✗ return;
627 }
628 ✗ case Fpy::DirectiveId::STACK_CMD: {
629 ✗ this->directive_stackCmd_internalInterfaceInvoke(directive.stackCmd, this->m_sequencesStarted);
630 ✗ return;
631 }
632 ✗ case Fpy::DirectiveId::PUSH_TIME: {
633 ✗ this->directive_pushTime_internalInterfaceInvoke(directive.pushTime, this->m_sequencesStarted);
634 ✗ return;
635 }
636 ✗ case Fpy::DirectiveId::SET_SEED: {
637 ✗ this->directive_setSeed_internalInterfaceInvoke(directive.setSeed, this->m_sequencesStarted);
638 ✗ return;
639 }
640 ✗ case Fpy::DirectiveId::PUSH_RAND: {
641 ✗ this->directive_pushRand_internalInterfaceInvoke(directive.pushRand, this->m_sequencesStarted);
642 ✗ return;
643 }
644 ✗ case Fpy::DirectiveId::GET_FIELD: {
645 ✗ this->directive_getField_internalInterfaceInvoke(directive.getField, this->m_sequencesStarted);
646 ✗ return;
647 }
648 ✗ case Fpy::DirectiveId::PEEK: {
649 ✗ this->directive_peek_internalInterfaceInvoke(directive.peek, this->m_sequencesStarted);
650 ✗ return;
651 }
652 ✗ case Fpy::DirectiveId::STORE_REL: {
653 ✗ this->directive_storeRel_internalInterfaceInvoke(directive.storeRel, this->m_sequencesStarted);
654 ✗ return;
655 }
656 ✗ case Fpy::DirectiveId::CALL: {
657 ✗ this->directive_call_internalInterfaceInvoke(directive.call, this->m_sequencesStarted);
658 ✗ return;
659 }
660 ✗ case Fpy::DirectiveId::RETURN: {
661 ✗ this->directive_return_internalInterfaceInvoke(directive.returnDirective, this->m_sequencesStarted);
662 ✗ return;
663 }
664 ✗ case Fpy::DirectiveId::LOAD_ABS: {
665 ✗ this->directive_loadAbs_internalInterfaceInvoke(directive.loadAbs, this->m_sequencesStarted);
666 ✗ return;
667 }
668 ✗ case Fpy::DirectiveId::STORE_ABS: {
669 ✗ this->directive_storeAbs_internalInterfaceInvoke(directive.storeAbs, this->m_sequencesStarted);
670 ✗ return;
671 }
672 ✗ case Fpy::DirectiveId::STORE_ABS_CONST_OFFSET: {
673 ✗ this->directive_storeAbsConstOffset_internalInterfaceInvoke(directive.storeAbsConstOffset,
674 this->m_sequencesStarted);
675 ✗ return;
676 }
677 ✗ case Fpy::DirectiveId::POP_EVENT: {
678 ✗ this->directive_popEvent_internalInterfaceInvoke(directive.popEvent, this->m_sequencesStarted);
679 ✗ return;
680 }
681 ✗ case Fpy::DirectiveId::POP_SERIALIZABLE: {
682 ✗ this->directive_popSerializable_internalInterfaceInvoke(directive.popSerializable,
683 this->m_sequencesStarted);
684 ✗ return;
685 }
686 }
687 // coding err
688 ✗ FW_ASSERT(false, static_cast<FwAssertArgType>(id));
689 }
690
691 ✗ Signal FpySequencer::checkShouldWake() {
692 ✗ Fw::Time currentTime = this->getTime();
693
694 ✗ if (currentTime.getTimeBase() != this->m_runtime.wakeupTime.getTimeBase()) {
695 // cannot compare these times.
696 ✗ this->log_WARNING_HI_MismatchedTimeBase(currentTime.getTimeBase(), this->m_runtime.wakeupTime.getTimeBase());
697
698 ✗ return Signal::result_timeOpFailed;
699 }
700
701 // Do not compare time context
702
703 ✗ if (currentTime < this->m_runtime.wakeupTime) {
704 // not time to wake up!
705 ✗ return Signal::result_checkShouldWake_keepSleeping;
706 }
707
708 // say we've finished our sleep
709 ✗ return Signal::result_checkShouldWake_wakeup;
710 ✗ }
711
712 // checks whether the currently executing statement timed out
713 ✗ Signal FpySequencer::checkStatementTimeout() {
714 ✗ Fw::ParamValid valid;
715 ✗ F32 timeout = this->paramGet_STATEMENT_TIMEOUT_SECS(valid);
716 ✗ if (timeout <= 0 || timeout > static_cast<F32>(std::numeric_limits<U32>::max())) {
717 // no timeout
718 ✗ return Signal::result_checkStatementTimeout_noTimeout;
719 }
720
721 ✗ Fw::Time currentTime = getTime();
722
723 ✗ if (currentTime.getTimeBase() != this->m_runtime.currentStatementDispatchTime.getTimeBase()) {
724 // can't compare time base. must have changed
725 ✗ this->log_WARNING_HI_MismatchedTimeBase(currentTime.getTimeBase(),
726 ✗ this->m_runtime.currentStatementDispatchTime.getTimeBase());
727 ✗ return Signal::result_timeOpFailed;
728 }
729
730 // Do not compare time context
731
732 ✗ if (this->m_runtime.currentStatementDispatchTime.getSeconds() > currentTime.getSeconds()) {
733 // somehow we've gone back in time... just ignore it and move on. should get fixed
734 // if we wait I guess
735 ✗ return Signal::result_checkStatementTimeout_noTimeout;
736 }
737
738 ✗ if (this->m_runtime.currentStatementDispatchTime.getSeconds() == currentTime.getSeconds() &&
739 ✗ this->m_runtime.currentStatementDispatchTime.getUSeconds() > currentTime.getUSeconds()) {
740 // same as above
741 ✗ return Signal::result_checkStatementTimeout_noTimeout;
742 }
743
744 ✗ U64 currentUSeconds = static_cast<U64>(currentTime.getSeconds()) * 1000000 + currentTime.getUSeconds();
745 ✗ U64 dispatchUSeconds = static_cast<U64>(this->m_runtime.currentStatementDispatchTime.getSeconds()) * 1000000 +
746 ✗ this->m_runtime.currentStatementDispatchTime.getUSeconds();
747
748 ✗ U64 timeoutUSeconds = static_cast<U64>(timeout * 1000000.0f);
749
750 ✗ if (currentUSeconds - dispatchUSeconds < timeoutUSeconds) {
751 // not over timeout
752 ✗ return Signal::result_checkStatementTimeout_noTimeout;
753 }
754
755 // we timed out
756 ✗ if (this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::CONST_CMD ||
757 ✗ this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::STACK_CMD) {
758 // if we were executing a command, warn that the cmd timed out with its opcode
759 ✗ this->log_WARNING_HI_CommandTimedOut(CmdDispatcherCfg::getEventOpcode(this->m_runtime.currentCmdOpcode),
760 this->currentStatementIdx(), this->m_sequenceFilePath);
761 } else {
762 ✗ this->log_WARNING_HI_DirectiveTimedOut(this->m_runtime.currentStatementOpcode, this->currentStatementIdx(),
763 this->m_sequenceFilePath);
764 }
765
766 ✗ return Signal::result_checkStatementTimeout_statementTimeout;
767 ✗ }
768
769 } // namespace Svc
770