GCC Code Coverage Report


Directory: ./
File: FpySequencerRunState.cpp
Date: 2026-09-23 22:13:04
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