FpySequencer arithmetic (#4025)

* Some work towards stack based arch

* Bring fp/int conv up to date

* Get compiling with stack based arch

* Start trying to fix UTs

* Start adding store/load dirs

* Add push val dir

* UTs are running

* UTs passing

* Make exit stack based

* Fix more uts

* Fix final UTs

* sp

* Fix overflow potential err

* Fix another overflow

* same error fix

* Format

* Also add to format checker

* Add math directives

* Add integer extension and truncation

* Also check correct size on stack

* Fix comment

* Push cmd response to stack

* Cast cmd response code to i32

* Add stack cmd, memcmp, discard dirs

* Fix some bugs with stack cmd

* Fix lil bug in sgtack cmd

* same bug

* Fix another bug sry

* Update sdd

* sp

* Fix undefined behavior with bitshift of signed integer

* sp

* Fix lil bug in timeout detection of stack cmd

* Switch format check to do all Svc dirs

* Reformat, and fix packet descriptor serialize bug

* Add UTs for all of arith ops

* Add tests for disc, memcmp, stack cmd

* Add deser tests for those three dirs

* sp

* Format

* Replace magic numbers with sizeofs

* Add currentStatementIdx helper function

* Format

* Split imod into smod and umod

* sp

* Add fmod, copy python behavior for fmod and smod

---------

Co-authored-by: Zimri Leisher <zimri.leisher@fireflyspace.com>
This commit is contained in:
Zimri Leisher 2025-08-21 16:08:40 -05:00 committed by GitHub
parent bdade025d0
commit f4439a8cc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1183 additions and 288 deletions

View File

@ -37,6 +37,7 @@ Bies
BINDIR
bitmaps
bitshifts
bitwidth
bocchino
boolt
bsd
@ -234,6 +235,7 @@ foodoodie
foodoodiehoo
FPCONFIG
fpext
fpow
fpp
fppi
fpptest
@ -331,6 +333,7 @@ isr
isunordered
itimerspec
itr
itrunc
itval
janamian
jawest
@ -559,6 +562,7 @@ sbom
scid
scm
sdd
sdiv
searchdata
SENDPARTIAL
seqgen
@ -580,11 +584,13 @@ SHAREDSTATEDIR
SHELLCOMMAND
showinitializer
sideeffect
siext
Signedness
Silveira
sitofp
sle
sloc
smod
socio
SOCKETHELPER
SOCKETIPDRIVER
@ -678,10 +684,12 @@ tts
typedef'ed
typedef
uart
udiv
UDPSOCKET
uge
uitofp
UML
umod
UNEXP
unistd
UNITTESTASSERT
@ -713,4 +721,5 @@ xdffe
xsltproc
xxxx
XXYY
ziext
zimri

View File

@ -35,64 +35,7 @@ jobs:
FppTestProject
Fw
Os
Svc/ActiveRateGroup
Svc/ActiveTextLogger
Svc/AssertFatalAdapter
Svc/BufferAccumulator
Svc/BufferLogger
Svc/BufferManager
Svc/BufferRepeater
Svc/Ccsds
Svc/ChronoTime
Svc/CmdDispatcher
Svc/CmdSequencer
Svc/CmdSplitter
Svc/ComLogger
Svc/ComQueue
Svc/ComSplitter
Svc/ComStub
Svc/Cycle
Svc/DpCatalog
Svc/DpManager
Svc/DpPorts
Svc/DpWriter
Svc/EventManager
Svc/Fatal
Svc/FatalHandler
Svc/FileDownlink
Svc/FileDownlinkPorts
Svc/FileManager
Svc/FileUplink
Svc/FprimeDeframer
Svc/FprimeFramer
Svc/FprimeProtocol
Svc/FprimeRouter
Svc/FrameAccumulator
Svc/FramingProtocol
Svc/GenericHub
Svc/Health
Svc/Interfaces
Svc/LinuxTimer
Svc/OsTime
Svc/PassiveConsoleTextLogger
Svc/PassiveRateGroup
Svc/Ping
Svc/PolyDb
Svc/PolyIf
Svc/Ports
Svc/PosixTime
Svc/PrmDb
Svc/RateGroupDriver
Svc/Sched
Svc/Seq
Svc/SeqDispatcher
Svc/StaticMemory
Svc/Subtopologies
Svc/SystemResources
Svc/TlmChan
Svc/TlmPacketizer
Svc/Version
Svc/WatchDog
Svc
run: |
fprime-util format --check --dirs $CHECKED_DIRS

View File

@ -261,9 +261,11 @@ void FpySequencer::cmdResponseIn_handler(FwIndexType portNum, //!< T
return;
}
if (this->m_runtime.currentStatementOpcode != Fpy::DirectiveId::CONST_CMD) {
if (this->m_runtime.currentStatementOpcode != Fpy::DirectiveId::CONST_CMD &&
this->m_runtime.currentStatementOpcode != Fpy::DirectiveId::STACK_CMD) {
// we were not awaiting a cmd response, we were waiting for a directive
this->log_WARNING_HI_CmdResponseWhileAwaitingDirective(opCode, response, this->m_runtime.currentStatementOpcode);
this->log_WARNING_HI_CmdResponseWhileAwaitingDirective(opCode, response,
this->m_runtime.currentStatementOpcode);
this->sequencer_sendSignal_stmtResponse_unexpected();
return;
}
@ -303,17 +305,15 @@ void FpySequencer::cmdResponseIn_handler(FwIndexType portNum, //!< T
if (response == Fw::CmdResponse::OK) {
this->sequencer_sendSignal_stmtResponse_success();
} else {
this->log_WARNING_HI_CommandFailed(opCode,
this->m_runtime.nextStatementIndex - 1, this->m_sequenceFilePath,
response);
this->log_WARNING_HI_CommandFailed(opCode, this->currentStatementIdx(), this->m_sequenceFilePath, response);
this->sequencer_sendSignal_stmtResponse_failure();
}
// push the cmd response to the stack so we can branch off of it
this->push(static_cast<I32>(response.e));
}
//! Handler for input port seqRunIn
void FpySequencer::seqRunIn_handler(FwIndexType portNum,
const Fw::StringBase& filename
) {
void FpySequencer::seqRunIn_handler(FwIndexType portNum, const Fw::StringBase& filename) {
// can only run a seq while in idle
if (sequencer_getState() != State::IDLE) {
this->log_WARNING_HI_InvalidSeqRunCall(static_cast<I32>(sequencer_getState()));
@ -356,7 +356,8 @@ FpySequencer_DebugTelemetry FpySequencer::getDebugTelemetry() {
}
if (nextStmt.get_opCode() == Fpy::DirectiveId::CONST_CMD) {
// send opcode of the cmd to the ground
return FpySequencer_DebugTelemetry(false, true, nextStmt.get_opCode(), directiveUnion.constCmd.get_opCode());
return FpySequencer_DebugTelemetry(false, true, nextStmt.get_opCode(),
directiveUnion.constCmd.get_opCode());
}
return FpySequencer_DebugTelemetry(false, true, nextStmt.get_opCode(), 0);

View File

@ -25,8 +25,7 @@ static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits<U8>::max()
"Sequence arg count must be below U8 max");
static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(),
"Sequence statement count must be below U16 max");
static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits<U16>::max(),
"Max stack size must be below U16 max");
static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits<U16>::max(), "Max stack size must be below U16 max");
static_assert(Svc::Fpy::MAX_STACK_SIZE >= FW_TLM_BUFFER_MAX_SIZE,
"Max stack size must be greater than max tlm buffer size");
static_assert(Svc::Fpy::MAX_STACK_SIZE >= FW_PARAM_BUFFER_MAX_SIZE,
@ -57,6 +56,9 @@ class FpySequencer : public FpySequencerComponentBase {
FpySequencer_StoreDirective store;
FpySequencer_LoadDirective load;
FpySequencer_PushValDirective pushVal;
FpySequencer_DiscardDirective discard;
FpySequencer_MemCmpDirective memCmp;
FpySequencer_StackCmdDirective stackCmd;
DirectiveUnion() {}
~DirectiveUnion() {}
@ -405,7 +407,8 @@ class FpySequencer : public FpySequencerComponentBase {
void directive_noOp_internalInterfaceHandler(const Svc::FpySequencer_NoOpDirective& directive) override;
//! Internal interface handler for directive_storeTlmVal
void directive_storeTlmVal_internalInterfaceHandler(const Svc::FpySequencer_StoreTlmValDirective& directive) override;
void directive_storeTlmVal_internalInterfaceHandler(
const Svc::FpySequencer_StoreTlmValDirective& directive) override;
//! Internal interface handler for directive_storePrm
void directive_storePrm_internalInterfaceHandler(const Svc::FpySequencer_StorePrmDirective& directive) override;
@ -431,6 +434,15 @@ class FpySequencer : public FpySequencerComponentBase {
//! Internal interface handler for directive_pushVal
void directive_pushVal_internalInterfaceHandler(const Svc::FpySequencer_PushValDirective& directive) override;
//! Internal interface handler for directive_discard
void directive_discard_internalInterfaceHandler(const Svc::FpySequencer_DiscardDirective& directive) override;
//! Internal interface handler for directive_memCmp
void directive_memCmp_internalInterfaceHandler(const Svc::FpySequencer_MemCmpDirective& directive) override;
//! Internal interface handler for directive_stackCmd
void directive_stackCmd_internalInterfaceHandler(const Svc::FpySequencer_StackCmdDirective& directive) override;
void parametersLoaded() override;
void parameterUpdated(FwPrmIdType id) override;
@ -589,6 +601,7 @@ class FpySequencer : public FpySequencerComponentBase {
// sends a signal based on a signal id
void sendSignal(Signal signal);
Fw::Success sendCmd(FwOpcodeType opcode, const U8* argBuf, FwSizeType argBufSize);
// pops a value off of the top of the stack
// converts it from big endian
@ -606,6 +619,8 @@ class FpySequencer : public FpySequencerComponentBase {
U8* lvars();
// returns the stack height at which the lvar array begins
U16 lvarOffset();
// returns the index of the current statement
U32 currentStatementIdx();
// we split these functions up into the internalInterfaceInvoke and these custom member funcs
// so that we can unit test them easier
@ -644,12 +659,39 @@ class FpySequencer : public FpySequencerComponentBase {
DirectiveError op_fptosi();
DirectiveError op_sitofp();
DirectiveError op_uitofp();
DirectiveError op_iadd();
DirectiveError op_isub();
DirectiveError op_imul();
DirectiveError op_udiv();
DirectiveError op_sdiv();
DirectiveError op_umod();
DirectiveError op_smod();
DirectiveError op_fadd();
DirectiveError op_fsub();
DirectiveError op_fmul();
DirectiveError op_fdiv();
DirectiveError op_float_floor_div();
DirectiveError op_fpow();
DirectiveError op_flog();
DirectiveError op_fmod();
DirectiveError op_siext_8_64();
DirectiveError op_siext_16_64();
DirectiveError op_siext_32_64();
DirectiveError op_ziext_8_64();
DirectiveError op_ziext_16_64();
DirectiveError op_ziext_32_64();
DirectiveError op_itrunc_64_8();
DirectiveError op_itrunc_64_16();
DirectiveError op_itrunc_64_32();
Signal exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& error);
Signal allocate_directiveHandler(const FpySequencer_AllocateDirective& directive, DirectiveError& error);
Signal store_directiveHandler(const FpySequencer_StoreDirective& directive, DirectiveError& error);
Signal load_directiveHandler(const FpySequencer_LoadDirective& directive, DirectiveError& error);
Signal pushVal_directiveHandler(const FpySequencer_PushValDirective& directive, DirectiveError& error);
Signal discard_directiveHandler(const FpySequencer_DiscardDirective& directive, DirectiveError& error);
Signal memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive, DirectiveError& error);
Signal stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& error);
};
} // namespace Svc

View File

@ -1,5 +1,5 @@
#include <type_traits>
#include <cmath>
#include <type_traits>
#include "Fw/Com/ComPacket.hpp"
#include "Svc/FpySequencer/FpySequencer.hpp"
@ -29,10 +29,44 @@ void FpySequencer::sendSignal(Signal signal) {
}
}
Fw::Success FpySequencer::sendCmd(FwOpcodeType opcode, const U8* argBuf, FwSizeType argBufSize) {
Fw::ComBuffer cmdBuf;
Fw::SerializeStatus stat =
cmdBuf.serialize(static_cast<FwPacketDescriptorType>(Fw::ComPacketType::FW_PACKET_COMMAND));
// TODO should I assert here? this really shouldn't fail, I should just add a static assert
// on com buf size and then assert here
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
return Fw::Success::FAILURE;
}
stat = cmdBuf.serialize(opcode);
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
return Fw::Success::FAILURE;
}
stat = cmdBuf.serialize(argBuf, argBufSize, Fw::Serialization::OMIT_LENGTH);
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
return Fw::Success::FAILURE;
}
// calculate the unique command identifier:
// cmd UID is formatted like XXYY, where XX are the first two bytes of the m_sequencesStarted counter
// and YY are the first two bytes of the m_statementsDispatched counter.
// this way, we know when we get a cmd back A) whether or not it's from this sequence (modulo 2^16) and B)
// whether or not it's this specific instance of the cmd in the sequence, and not another one with the same opcode
// somewhere else in the file.
// if we put this uid in the context we send to the cmdDisp, we will get it back when the cmd returns
U32 cmdUid =
static_cast<U32>(((this->m_sequencesStarted & 0xFFFF) << 16) | (this->m_statementsDispatched & 0xFFFF));
this->cmdOut_out(0, cmdBuf, cmdUid);
return Fw::Success::SUCCESS;
}
template <typename T>
T FpySequencer::pop() {
static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
FW_ASSERT(this->m_runtime.stackSize >= sizeof(T), static_cast<FwAssertArgType>(this->m_runtime.stackSize), static_cast<FwAssertArgType>(sizeof(T)));
FW_ASSERT(this->m_runtime.stackSize >= sizeof(T), static_cast<FwAssertArgType>(this->m_runtime.stackSize),
static_cast<FwAssertArgType>(sizeof(T)));
// first make a byte array which can definitely store our val
U8 valBytes[8] = {0};
// now move top of stack into byte array and shrink stack
@ -41,25 +75,15 @@ T FpySequencer::pop() {
// now do appropriate byteswap on byte array
if (sizeof(T) == 8) {
return static_cast<T>(
(static_cast<T>(valBytes[7]) << 0) |
(static_cast<T>(valBytes[6]) << 8) |
(static_cast<T>(valBytes[5]) << 16) |
(static_cast<T>(valBytes[4]) << 24) |
(static_cast<T>(valBytes[3]) << 32) |
(static_cast<T>(valBytes[2]) << 40) |
(static_cast<T>(valBytes[1]) << 48) |
(static_cast<T>(valBytes[0]) << 56));
return static_cast<T>((static_cast<T>(valBytes[7]) << 0) | (static_cast<T>(valBytes[6]) << 8) |
(static_cast<T>(valBytes[5]) << 16) | (static_cast<T>(valBytes[4]) << 24) |
(static_cast<T>(valBytes[3]) << 32) | (static_cast<T>(valBytes[2]) << 40) |
(static_cast<T>(valBytes[1]) << 48) | (static_cast<T>(valBytes[0]) << 56));
} else if (sizeof(T) == 4) {
return static_cast<T>(
(static_cast<T>(valBytes[3]) << 0) |
(static_cast<T>(valBytes[2]) << 8) |
(static_cast<T>(valBytes[1]) << 16) |
(static_cast<T>(valBytes[0]) << 24));
return static_cast<T>((static_cast<T>(valBytes[3]) << 0) | (static_cast<T>(valBytes[2]) << 8) |
(static_cast<T>(valBytes[1]) << 16) | (static_cast<T>(valBytes[0]) << 24));
} else if (sizeof(T) == 2) {
return static_cast<T>(
(static_cast<T>(valBytes[1]) << 0) |
(static_cast<T>(valBytes[0]) << 8));
return static_cast<T>((static_cast<T>(valBytes[1]) << 0) | (static_cast<T>(valBytes[0]) << 8));
} else {
return static_cast<T>(valBytes[0]);
}
@ -74,14 +98,16 @@ template I16 FpySequencer::pop();
template I32 FpySequencer::pop();
template I64 FpySequencer::pop();
template <> F32 FpySequencer::pop<F32>() {
template <>
F32 FpySequencer::pop<F32>() {
U32 endianness = this->pop<U32>();
F32 val;
memcpy(&val, &endianness, sizeof(val));
return val;
}
template <> F64 FpySequencer::pop<F64>() {
template <>
F64 FpySequencer::pop<F64>() {
U64 endianness = this->pop<U64>();
F64 val;
memcpy(&val, &endianness, sizeof(val));
@ -91,7 +117,8 @@ template <> F64 FpySequencer::pop<F64>() {
template <typename T>
void FpySequencer::push(T val) {
static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
FW_ASSERT(this->m_runtime.stackSize + sizeof(val) < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->m_runtime.stackSize), static_cast<FwAssertArgType>(sizeof(T)));
FW_ASSERT(this->m_runtime.stackSize + sizeof(val) < Fpy::MAX_STACK_SIZE,
static_cast<FwAssertArgType>(this->m_runtime.stackSize), static_cast<FwAssertArgType>(sizeof(T)));
// first make a byte array which can definitely store our val
U8 valBytes[8] = {0};
// convert val to unsigned to avoid undefined behavior for bitshifts of signed types
@ -130,13 +157,15 @@ template void FpySequencer::push(I16);
template void FpySequencer::push(I32);
template void FpySequencer::push(I64);
template <> void FpySequencer::push<F32>(F32 val) {
template <>
void FpySequencer::push<F32>(F32 val) {
U32 endianness;
memcpy(&endianness, &val, sizeof(val));
this->push(endianness);
}
template <> void FpySequencer::push<F64>(F64 val) {
template <>
void FpySequencer::push<F64>(F64 val) {
U64 endianness;
memcpy(&endianness, &val, sizeof(val));
this->push(endianness);
@ -192,7 +221,8 @@ void FpySequencer::directive_noOp_internalInterfaceHandler(const Svc::FpySequenc
}
//! Internal interface handler for directive_storeTlmVal
void FpySequencer::directive_storeTlmVal_internalInterfaceHandler(const Svc::FpySequencer_StoreTlmValDirective& directive) {
void FpySequencer::directive_storeTlmVal_internalInterfaceHandler(
const Svc::FpySequencer_StoreTlmValDirective& directive) {
DirectiveError error = DirectiveError::NO_ERROR;
this->sendSignal(this->storeTlmVal_directiveHandler(directive, error));
this->m_tlm.lastDirectiveError = error;
@ -254,6 +284,27 @@ void FpySequencer::directive_load_internalInterfaceHandler(const Svc::FpySequenc
this->m_tlm.lastDirectiveError = error;
}
//! Internal interface handler for directive_discard
void FpySequencer::directive_discard_internalInterfaceHandler(const Svc::FpySequencer_DiscardDirective& directive) {
DirectiveError error = DirectiveError::NO_ERROR;
this->sendSignal(this->discard_directiveHandler(directive, error));
this->m_tlm.lastDirectiveError = error;
}
//! Internal interface handler for directive_memCmp
void FpySequencer::directive_memCmp_internalInterfaceHandler(const Svc::FpySequencer_MemCmpDirective& directive) {
DirectiveError error = DirectiveError::NO_ERROR;
this->sendSignal(this->memCmp_directiveHandler(directive, error));
this->m_tlm.lastDirectiveError = error;
}
//! Internal interface handler for directive_stackCmd
void FpySequencer::directive_stackCmd_internalInterfaceHandler(const Svc::FpySequencer_StackCmdDirective& directive) {
DirectiveError error = DirectiveError::NO_ERROR;
this->sendSignal(this->stackCmd_directiveHandler(directive, error));
this->m_tlm.lastDirectiveError = error;
}
//! Internal interface handler for directive_waitRel
Signal FpySequencer::waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& error) {
if (this->m_runtime.stackSize < 8) {
@ -324,7 +375,8 @@ Signal FpySequencer::noOp_directiveHandler(const FpySequencer_NoOpDirective& dir
return Signal::stmtResponse_success;
}
Signal FpySequencer::storeTlmVal_directiveHandler(const FpySequencer_StoreTlmValDirective& directive, DirectiveError& error) {
Signal FpySequencer::storeTlmVal_directiveHandler(const FpySequencer_StoreTlmValDirective& directive,
DirectiveError& error) {
if (!this->isConnected_getTlmChan_OutputPort(0)) {
error = DirectiveError::TLM_GET_NOT_CONNECTED;
return Signal::stmtResponse_failure;
@ -390,40 +442,14 @@ Signal FpySequencer::storePrm_directiveHandler(const FpySequencer_StorePrmDirect
}
Signal FpySequencer::constCmd_directiveHandler(const FpySequencer_ConstCmdDirective& directive, DirectiveError& error) {
Fw::ComBuffer cmdBuf;
Fw::SerializeStatus stat = cmdBuf.serialize(static_cast<FwPacketDescriptorType>(Fw::ComPacketType::FW_PACKET_COMMAND));
// TODO should I assert here? this really shouldn't fail, I should just add a static assert
// on com buf size and then assert here
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
error = DirectiveError::CMD_SERIALIZE_FAILURE;
if (this->sendCmd(directive.get_opCode(), directive.get_argBuf(), directive.get__argBufSize()) ==
Fw::Success::FAILURE) {
return Signal::stmtResponse_failure;
} else {
// now tell the SM to wait some more until we get the cmd response back
// if we've already got the response back this should be harmless
return Signal::stmtResponse_keepWaiting;
}
stat = cmdBuf.serialize(directive.get_opCode());
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
error = DirectiveError::CMD_SERIALIZE_FAILURE;
return Signal::stmtResponse_failure;
}
stat = cmdBuf.serialize(directive.get_argBuf(), directive.get__argBufSize(), Fw::Serialization::OMIT_LENGTH);
if (stat != Fw::SerializeStatus::FW_SERIALIZE_OK) {
error = DirectiveError::CMD_SERIALIZE_FAILURE;
return Signal::stmtResponse_failure;
}
// calculate the unique command identifier:
// cmd UID is formatted like XXYY, where XX are the first two bytes of the m_sequencesStarted counter
// and YY are the first two bytes of the m_statementsDispatched counter.
// this way, we know when we get a cmd back A) whether or not it's from this sequence (modulo 2^16) and B)
// whether or not it's this specific instance of the cmd in the sequence, and not another one with the same opcode
// somewhere else in the file.
// if we put this uid in the context we send to the cmdDisp, we will get it back when the cmd returns
U32 cmdUid =
static_cast<U32>(((this->m_sequencesStarted & 0xFFFF) << 16) | (this->m_statementsDispatched & 0xFFFF));
this->cmdOut_out(0, cmdBuf, cmdUid);
// now tell the SM to wait some more until we get the cmd response back
// if we've already got the response back this should be harmless
return Signal::stmtResponse_keepWaiting;
}
I8 floatCmp(F64 lhs, F64 rhs) {
@ -440,35 +466,35 @@ I8 floatCmp(F64 lhs, F64 rhs) {
}
DirectiveError FpySequencer::op_or() {
if (this->m_runtime.stackSize < 2) {
if (this->m_runtime.stackSize < sizeof(U8) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U8>(this->pop<U8>() | this->pop<U8>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_and() {
if (this->m_runtime.stackSize < 2) {
if (this->m_runtime.stackSize < sizeof(U8) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U8>(this->pop<U8>() & this->pop<U8>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ieq() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U8>(this->pop<I64>() == this->pop<I64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ine() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U8>(this->pop<I64>() != this->pop<I64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ult() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
@ -477,7 +503,7 @@ DirectiveError FpySequencer::op_ult() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ule() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
@ -486,7 +512,7 @@ DirectiveError FpySequencer::op_ule() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ugt() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
@ -495,7 +521,7 @@ DirectiveError FpySequencer::op_ugt() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_uge() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
@ -504,7 +530,7 @@ DirectiveError FpySequencer::op_uge() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_slt() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
@ -513,7 +539,7 @@ DirectiveError FpySequencer::op_slt() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_sle() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
@ -522,7 +548,7 @@ DirectiveError FpySequencer::op_sle() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_sgt() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
@ -531,7 +557,7 @@ DirectiveError FpySequencer::op_sgt() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_sge() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
@ -540,7 +566,7 @@ DirectiveError FpySequencer::op_sge() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_feq() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -550,7 +576,7 @@ DirectiveError FpySequencer::op_feq() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fne() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -561,7 +587,7 @@ DirectiveError FpySequencer::op_fne() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_flt() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -570,7 +596,7 @@ DirectiveError FpySequencer::op_flt() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fle() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -580,7 +606,7 @@ DirectiveError FpySequencer::op_fle() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fgt() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -589,7 +615,7 @@ DirectiveError FpySequencer::op_fgt() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fge() {
if (this->m_runtime.stackSize < 16) {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
@ -599,7 +625,7 @@ DirectiveError FpySequencer::op_fge() {
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_not() {
if (this->m_runtime.stackSize < 1) {
if (this->m_runtime.stackSize < sizeof(U8)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U8>(this->pop<U8>() == 0));
@ -607,7 +633,7 @@ DirectiveError FpySequencer::op_not() {
}
DirectiveError FpySequencer::op_fpext() {
// convert F32 to F64
if (this->m_runtime.stackSize < 4) {
if (this->m_runtime.stackSize < sizeof(F32)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<F64>(this->pop<F32>()));
@ -615,44 +641,266 @@ DirectiveError FpySequencer::op_fpext() {
}
DirectiveError FpySequencer::op_fptrunc() {
// convert F64 to F32
if (this->m_runtime.stackSize < 8) {
if (this->m_runtime.stackSize < sizeof(F64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<F32>(this->pop<F64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fptosi() {
if (this->m_runtime.stackSize < 8) {
if (this->m_runtime.stackSize < sizeof(F64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<I64>(this->pop<F64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_sitofp() {
if (this->m_runtime.stackSize < 8) {
if (this->m_runtime.stackSize < sizeof(I64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<F64>(this->pop<I64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fptoui() {
if (this->m_runtime.stackSize < 8) {
if (this->m_runtime.stackSize < sizeof(F64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<U64>(this->pop<F64>()));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_uitofp() {
if (this->m_runtime.stackSize < 8) {
if (this->m_runtime.stackSize < sizeof(U64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
this->push(static_cast<F64>(this->pop<U64>()));
return DirectiveError::NO_ERROR;
}
Signal FpySequencer::stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive,
DirectiveError& error) {
// coding error, should not have gotten to this binary reg op handler
FW_ASSERT(directive.get__op() >= Fpy::DirectiveId::OR && directive.get__op() <= Fpy::DirectiveId::UITOFP,
DirectiveError FpySequencer::op_iadd() {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
I64 lhs = this->pop<I64>();
this->push(static_cast<I64>(lhs + rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_isub() {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
I64 lhs = this->pop<I64>();
this->push(static_cast<I64>(lhs - rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_imul() {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
I64 lhs = this->pop<I64>();
this->push(static_cast<I64>(lhs * rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_udiv() {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
U64 lhs = this->pop<U64>();
this->push(static_cast<U64>(lhs / rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_sdiv() {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
I64 lhs = this->pop<I64>();
this->push(static_cast<I64>(lhs / rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_umod() {
if (this->m_runtime.stackSize < sizeof(U64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 rhs = this->pop<U64>();
if (rhs == 0) {
return DirectiveError::DOMAIN_ERROR;
}
U64 lhs = this->pop<U64>();
this->push(static_cast<U64>(lhs % rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_smod() {
if (this->m_runtime.stackSize < sizeof(I64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I64 rhs = this->pop<I64>();
if (rhs == 0) {
return DirectiveError::DOMAIN_ERROR;
}
I64 lhs = this->pop<I64>();
I64 res = static_cast<I64>(lhs % rhs);
// in order to match Python's behavior,
// if the signs of the remainder and divisor differ, adjust the result.
// this happens when the result should be positive but is negative, or vice-versa.
// credit Gemini 2.5 pro
if ((res > 0 && rhs < 0) || (res < 0 && rhs > 0)) {
res += rhs;
}
this->push(res);
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fadd() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(lhs + rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fsub() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(lhs - rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fmul() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(lhs * rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fdiv() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(lhs / rhs));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_float_floor_div() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(floor(lhs / rhs)));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fpow() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(pow(lhs, rhs)));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_flog() {
if (this->m_runtime.stackSize < sizeof(F64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 val = this->pop<F64>();
this->push(static_cast<F64>(log(val)));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_fmod() {
if (this->m_runtime.stackSize < sizeof(F64) * 2) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
F64 rhs = this->pop<F64>();
if (rhs == 0.0) {
return DirectiveError::DOMAIN_ERROR;
}
F64 lhs = this->pop<F64>();
this->push(static_cast<F64>(lhs - rhs * std::floor(lhs / rhs)));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_siext_8_64() {
if (this->m_runtime.stackSize < sizeof(I8)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I8 src = this->pop<I8>();
this->push(static_cast<I64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_siext_16_64() {
if (this->m_runtime.stackSize < sizeof(I16)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I16 src = this->pop<I16>();
this->push(static_cast<I64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_siext_32_64() {
if (this->m_runtime.stackSize < sizeof(I32)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
I32 src = this->pop<I32>();
this->push(static_cast<I64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ziext_8_64() {
if (this->m_runtime.stackSize < sizeof(U8)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U8 src = this->pop<U8>();
this->push(static_cast<U64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ziext_16_64() {
if (this->m_runtime.stackSize < sizeof(U16)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U16 src = this->pop<U16>();
this->push(static_cast<U64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_ziext_32_64() {
if (this->m_runtime.stackSize < sizeof(U32)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U32 src = this->pop<U32>();
this->push(static_cast<U64>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_itrunc_64_8() {
if (this->m_runtime.stackSize < sizeof(U64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 src = this->pop<U64>();
this->push(static_cast<U8>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_itrunc_64_16() {
if (this->m_runtime.stackSize < sizeof(U64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 src = this->pop<U64>();
this->push(static_cast<U16>(src));
return DirectiveError::NO_ERROR;
}
DirectiveError FpySequencer::op_itrunc_64_32() {
if (this->m_runtime.stackSize < sizeof(U64)) {
return DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
}
U64 src = this->pop<U64>();
this->push(static_cast<U32>(src));
return DirectiveError::NO_ERROR;
}
Signal FpySequencer::stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive, DirectiveError& error) {
// coding error, should not have gotten to this stack op handler
FW_ASSERT(directive.get__op() >= Fpy::DirectiveId::OR && directive.get__op() <= Fpy::DirectiveId::ITRUNC_64_32,
static_cast<FwAssertArgType>(directive.get__op()));
switch (directive.get__op()) {
@ -731,6 +979,78 @@ Signal FpySequencer::stackOp_directiveHandler(const FpySequencer_StackOpDirectiv
case Fpy::DirectiveId::UITOFP:
error = this->op_uitofp();
break;
case Fpy::DirectiveId::IADD:
error = this->op_iadd();
break;
case Fpy::DirectiveId::ISUB:
error = this->op_isub();
break;
case Fpy::DirectiveId::IMUL:
error = this->op_imul();
break;
case Fpy::DirectiveId::UDIV:
error = this->op_udiv();
break;
case Fpy::DirectiveId::SDIV:
error = this->op_sdiv();
break;
case Fpy::DirectiveId::UMOD:
error = this->op_umod();
break;
case Fpy::DirectiveId::SMOD:
error = this->op_smod();
break;
case Fpy::DirectiveId::FADD:
error = this->op_fadd();
break;
case Fpy::DirectiveId::FSUB:
error = this->op_fsub();
break;
case Fpy::DirectiveId::FMUL:
error = this->op_fmul();
break;
case Fpy::DirectiveId::FDIV:
error = this->op_fdiv();
break;
case Fpy::DirectiveId::FLOAT_FLOOR_DIV:
error = this->op_float_floor_div();
break;
case Fpy::DirectiveId::FPOW:
error = this->op_fpow();
break;
case Fpy::DirectiveId::FLOG:
error = this->op_flog();
break;
case Fpy::DirectiveId::FMOD:
error = this->op_fmod();
break;
case Fpy::DirectiveId::SIEXT_8_64:
error = this->op_siext_8_64();
break;
case Fpy::DirectiveId::SIEXT_16_64:
error = this->op_siext_16_64();
break;
case Fpy::DirectiveId::SIEXT_32_64:
error = this->op_siext_32_64();
break;
case Fpy::DirectiveId::ZIEXT_8_64:
error = this->op_ziext_8_64();
break;
case Fpy::DirectiveId::ZIEXT_16_64:
error = this->op_ziext_16_64();
break;
case Fpy::DirectiveId::ZIEXT_32_64:
error = this->op_ziext_32_64();
break;
case Fpy::DirectiveId::ITRUNC_64_8:
error = this->op_itrunc_64_8();
break;
case Fpy::DirectiveId::ITRUNC_64_16:
error = this->op_itrunc_64_16();
break;
case Fpy::DirectiveId::ITRUNC_64_32:
error = this->op_itrunc_64_32();
break;
default:
FW_ASSERT(0, directive.get__op());
break;
@ -811,4 +1131,57 @@ Signal FpySequencer::pushVal_directiveHandler(const FpySequencer_PushValDirectiv
this->m_runtime.stackSize += directive.get__valSize();
return Signal::stmtResponse_success;
}
Signal FpySequencer::discard_directiveHandler(const FpySequencer_DiscardDirective& directive, DirectiveError& error) {
if (this->m_runtime.stackSize < directive.get_size()) {
error = DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
return Signal::stmtResponse_failure;
}
this->m_runtime.stackSize -= directive.get_size();
return Signal::stmtResponse_success;
}
Signal FpySequencer::memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive, DirectiveError& error) {
if (this->m_runtime.stackSize < directive.get_size() * 2) {
error = DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
return Signal::stmtResponse_failure;
}
U64 lhsOffset = this->m_runtime.stackSize - directive.get_size() * 2;
U64 rhsOffset = this->m_runtime.stackSize - directive.get_size();
this->m_runtime.stackSize -= directive.get_size() * 2;
if (memcmp(this->m_runtime.stack + lhsOffset, this->m_runtime.stack + rhsOffset, directive.get_size()) == 0) {
this->push<U8>(1);
} else {
this->push<U8>(0);
}
return Signal::stmtResponse_success;
}
Signal FpySequencer::stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& error) {
if (this->m_runtime.stackSize < static_cast<U64>(directive.get_argsSize() + sizeof(FwOpcodeType))) {
error = DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS;
return Signal::stmtResponse_failure;
}
FwOpcodeType opcode = this->pop<FwOpcodeType>();
U64 argBufOffset = this->m_runtime.stackSize - directive.get_argsSize();
// update the opcode of the cmd we will await
this->m_runtime.currentCmdOpcode = opcode;
// also pop the args off the stack
this->m_runtime.stackSize -= directive.get_argsSize();
if (this->sendCmd(opcode, this->m_runtime.stack + argBufOffset, directive.get_argsSize()) == Fw::Success::FAILURE) {
return Signal::stmtResponse_failure;
} else {
// now tell the SM to wait some more until we get the cmd response back
// if we've already got the response back this should be harmless
return Signal::stmtResponse_keepWaiting;
}
return Signal::stmtResponse_success;
}
} // namespace Svc

View File

@ -94,6 +94,18 @@ struct PushValDirective {
_valSize: FwSizeType
}
struct DiscardDirective {
$size: U16
}
struct MemCmpDirective {
$size: U16
}
struct StackCmdDirective {
argsSize: U16
}
internal port directive_waitRel(directive: WaitRelDirective) priority 6 assert
internal port directive_waitAbs(directive: WaitAbsDirective) priority 6 assert
@ -122,6 +134,12 @@ internal port directive_load(directive: LoadDirective) priority 6 assert
internal port directive_pushVal(directive: PushValDirective) priority 6 assert
internal port directive_discard(directive: DiscardDirective) priority 6 assert
internal port directive_memCmp(directive: MemCmpDirective) priority 6 assert
internal port directive_stackCmd(directive: StackCmdDirective) priority 6 assert
enum DirectiveErrorCode {
NO_ERROR
STMT_OUT_OF_BOUNDS
@ -133,4 +151,5 @@ enum DirectiveErrorCode {
DELIBERATE_FAILURE
STACK_ACCESS_OUT_OF_BOUNDS
STACK_OVERFLOW
DOMAIN_ERROR
}

View File

@ -4,6 +4,15 @@
#include "Svc/FpySequencer/FpySequencer.hpp"
namespace Svc {
// returns the index of the current statement
U32 FpySequencer::currentStatementIdx() {
if (this->m_runtime.nextStatementIndex == 0) {
// haven't started executing the sequence yet
return 0;
}
return this->m_runtime.nextStatementIndex - 1;
}
Signal FpySequencer::dispatchStatement() {
// check to make sure no array out of bounds, or if it is out of bounds it's only 1 out of bound
// as that indicates eof
@ -16,7 +25,7 @@ Signal FpySequencer::dispatchStatement() {
const Fpy::Statement& nextStatement = this->m_sequenceObj.get_statements()[this->m_runtime.nextStatementIndex];
this->m_runtime.nextStatementIndex++;
this->m_runtime.currentStatementOpcode = nextStatement.get_opCode();
this->m_runtime.currentCmdOpcode = 0; // we haven't deserialized the directive yet, so we don't know if it's a cmd
this->m_runtime.currentCmdOpcode = 0; // we haven't deserialized the directive yet, so we don't know if it's a cmd
Fw::Success result;
DirectiveUnion directiveUnion;
@ -34,7 +43,8 @@ Signal FpySequencer::dispatchStatement() {
this->dispatchDirective(directiveUnion,
Fpy::DirectiveId(static_cast<Fpy::DirectiveId::T>(nextStatement.get_opCode())));
this->m_runtime.currentStatementDispatchTime = getTime(); // set dispatch time right after we have successfully dispatched
this->m_runtime.currentStatementDispatchTime =
getTime(); // set dispatch time right after we have successfully dispatched
this->m_statementsDispatched++;
@ -57,7 +67,7 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.waitRel) FpySequencer_WaitRelDirective();
// wait rel does not need deser
if (argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
@ -68,7 +78,7 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.waitAbs) FpySequencer_WaitAbsDirective();
// wait abs does not need deser
if (argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
@ -79,8 +89,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.gotoDirective) FpySequencer_GotoDirective();
status = argBuf.deserialize(deserializedDirective.gotoDirective);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -89,8 +99,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.ifDirective) FpySequencer_IfDirective();
status = argBuf.deserialize(deserializedDirective.ifDirective);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -99,7 +109,7 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.noOp) FpySequencer_NoOpDirective();
// no op does not need deser
if (argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
@ -110,8 +120,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.storeTlmVal) FpySequencer_StoreTlmValDirective();
status = argBuf.deserialize(deserializedDirective.storeTlmVal);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -120,8 +130,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.storePrm) FpySequencer_StorePrmDirective();
status = argBuf.deserialize(deserializedDirective.storePrm);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -133,8 +143,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
FwOpcodeType opcode;
status = argBuf.deserialize(opcode);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
@ -144,18 +154,19 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
// check to make sure the value will fit in the FpySequencer_ConstCmdDirective::argBuf
if (cmdArgBufSize > Fpy::MAX_DIRECTIVE_SIZE) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_FORMAT_ERROR,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
// okay, it will fit. put it in
status = argBuf.deserialize(deserializedDirective.constCmd.get_argBuf(), cmdArgBufSize, Fw::Serialization::OMIT_LENGTH);
status = argBuf.deserialize(deserializedDirective.constCmd.get_argBuf(), cmdArgBufSize,
Fw::Serialization::OMIT_LENGTH);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
@ -174,11 +185,11 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
case Fpy::DirectiveId::UGT:
case Fpy::DirectiveId::ULT:
case Fpy::DirectiveId::ULE:
case Fpy::DirectiveId::UGE:
case Fpy::DirectiveId::UGE:
case Fpy::DirectiveId::SGT:
case Fpy::DirectiveId::SLT:
case Fpy::DirectiveId::SLE:
case Fpy::DirectiveId::SGE:
case Fpy::DirectiveId::SGE:
case Fpy::DirectiveId::FEQ:
case Fpy::DirectiveId::FNE:
case Fpy::DirectiveId::FLT:
@ -191,10 +202,34 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
case Fpy::DirectiveId::FPTOSI:
case Fpy::DirectiveId::FPTOUI:
case Fpy::DirectiveId::SITOFP:
case Fpy::DirectiveId::UITOFP: {
case Fpy::DirectiveId::UITOFP:
case Fpy::DirectiveId::IADD:
case Fpy::DirectiveId::ISUB:
case Fpy::DirectiveId::IMUL:
case Fpy::DirectiveId::UDIV:
case Fpy::DirectiveId::SDIV:
case Fpy::DirectiveId::UMOD:
case Fpy::DirectiveId::SMOD:
case Fpy::DirectiveId::FADD:
case Fpy::DirectiveId::FSUB:
case Fpy::DirectiveId::FMUL:
case Fpy::DirectiveId::FDIV:
case Fpy::DirectiveId::FLOAT_FLOOR_DIV:
case Fpy::DirectiveId::FPOW:
case Fpy::DirectiveId::FLOG:
case Fpy::DirectiveId::FMOD:
case Fpy::DirectiveId::SIEXT_8_64:
case Fpy::DirectiveId::SIEXT_16_64:
case Fpy::DirectiveId::SIEXT_32_64:
case Fpy::DirectiveId::ZIEXT_8_64:
case Fpy::DirectiveId::ZIEXT_16_64:
case Fpy::DirectiveId::ZIEXT_32_64:
case Fpy::DirectiveId::ITRUNC_64_8:
case Fpy::DirectiveId::ITRUNC_64_16:
case Fpy::DirectiveId::ITRUNC_64_32: {
new (&deserializedDirective.stackOp) FpySequencer_StackOpDirective();
if (argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
@ -205,7 +240,7 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
case Fpy::DirectiveId::EXIT: {
new (&deserializedDirective.exit) FpySequencer_ExitDirective();
if (argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_SIZE_MISMATCH,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
@ -216,8 +251,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.allocate) FpySequencer_AllocateDirective();
status = argBuf.deserialize(deserializedDirective.allocate);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -226,8 +261,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.store) FpySequencer_StoreDirective();
status = argBuf.deserialize(deserializedDirective.store);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -236,8 +271,8 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
new (&deserializedDirective.load) FpySequencer_LoadDirective();
status = argBuf.deserialize(deserializedDirective.load);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
@ -250,18 +285,19 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
// check to make sure the value will fit in the FpySequencer_PushValDirective::val buf
if (bufSize > Fpy::MAX_DIRECTIVE_SIZE) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(),
Fw::SerializeStatus::FW_DESERIALIZE_FORMAT_ERROR,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
// okay, it will fit. put it in
status = argBuf.deserialize(deserializedDirective.pushVal.get_val(), bufSize, Fw::Serialization::OMIT_LENGTH);
status =
argBuf.deserialize(deserializedDirective.pushVal.get_val(), bufSize, Fw::Serialization::OMIT_LENGTH);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
status, argBuf.getBuffLeft(), argBuf.getBuffLength());
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
@ -272,9 +308,39 @@ Fw::Success FpySequencer::deserializeDirective(const Fpy::Statement& stmt, Direc
deserializedDirective.pushVal.set__valSize(bufSize);
break;
}
case Fpy::DirectiveId::DISCARD: {
new (&deserializedDirective.discard) FpySequencer_DiscardDirective();
status = argBuf.deserialize(deserializedDirective.discard);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
}
case Fpy::DirectiveId::MEMCMP: {
new (&deserializedDirective.memCmp) FpySequencer_MemCmpDirective();
status = argBuf.deserialize(deserializedDirective.memCmp);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
}
case Fpy::DirectiveId::STACK_CMD: {
new (&deserializedDirective.stackCmd) FpySequencer_StackCmdDirective();
status = argBuf.deserialize(deserializedDirective.stackCmd);
if (status != Fw::SerializeStatus::FW_SERIALIZE_OK || argBuf.getBuffLeft() != 0) {
this->log_WARNING_HI_DirectiveDeserializeError(stmt.get_opCode(), this->currentStatementIdx(), status,
argBuf.getBuffLeft(), argBuf.getBuffLength());
return Fw::Success::FAILURE;
}
break;
}
default: {
// unsure what this opcode is. check compiler version matches sequencer
this->log_WARNING_HI_UnknownSequencerDirective(stmt.get_opCode(), this->m_runtime.nextStatementIndex - 1,
this->log_WARNING_HI_UnknownSequencerDirective(stmt.get_opCode(), this->currentStatementIdx(),
this->m_sequenceFilePath);
return Fw::Success::FAILURE;
}
@ -330,7 +396,7 @@ void FpySequencer::dispatchDirective(const DirectiveUnion& directive, const Fpy:
case Fpy::DirectiveId::UGT:
case Fpy::DirectiveId::ULT:
case Fpy::DirectiveId::ULE:
case Fpy::DirectiveId::UGE:
case Fpy::DirectiveId::UGE:
case Fpy::DirectiveId::SGT:
case Fpy::DirectiveId::SLT:
case Fpy::DirectiveId::SLE:
@ -347,7 +413,31 @@ void FpySequencer::dispatchDirective(const DirectiveUnion& directive, const Fpy:
case Fpy::DirectiveId::FPTOSI:
case Fpy::DirectiveId::FPTOUI:
case Fpy::DirectiveId::SITOFP:
case Fpy::DirectiveId::UITOFP: {
case Fpy::DirectiveId::UITOFP:
case Fpy::DirectiveId::IADD:
case Fpy::DirectiveId::ISUB:
case Fpy::DirectiveId::IMUL:
case Fpy::DirectiveId::UDIV:
case Fpy::DirectiveId::SDIV:
case Fpy::DirectiveId::UMOD:
case Fpy::DirectiveId::SMOD:
case Fpy::DirectiveId::FADD:
case Fpy::DirectiveId::FSUB:
case Fpy::DirectiveId::FMUL:
case Fpy::DirectiveId::FDIV:
case Fpy::DirectiveId::FLOAT_FLOOR_DIV:
case Fpy::DirectiveId::FPOW:
case Fpy::DirectiveId::FLOG:
case Fpy::DirectiveId::FMOD:
case Fpy::DirectiveId::SIEXT_8_64:
case Fpy::DirectiveId::SIEXT_16_64:
case Fpy::DirectiveId::SIEXT_32_64:
case Fpy::DirectiveId::ZIEXT_8_64:
case Fpy::DirectiveId::ZIEXT_16_64:
case Fpy::DirectiveId::ZIEXT_32_64:
case Fpy::DirectiveId::ITRUNC_64_8:
case Fpy::DirectiveId::ITRUNC_64_16:
case Fpy::DirectiveId::ITRUNC_64_32: {
this->directive_stackOp_internalInterfaceInvoke(directive.stackOp);
return;
}
@ -371,6 +461,18 @@ void FpySequencer::dispatchDirective(const DirectiveUnion& directive, const Fpy:
this->directive_pushVal_internalInterfaceInvoke(directive.pushVal);
return;
}
case Fpy::DirectiveId::DISCARD: {
this->directive_discard_internalInterfaceInvoke(directive.discard);
return;
}
case Fpy::DirectiveId::MEMCMP: {
this->directive_memCmp_internalInterfaceInvoke(directive.memCmp);
return;
}
case Fpy::DirectiveId::STACK_CMD: {
this->directive_stackCmd_internalInterfaceInvoke(directive.stackCmd);
return;
}
}
// coding err
FW_ASSERT(0, static_cast<FwAssertArgType>(id));
@ -441,13 +543,14 @@ Signal FpySequencer::checkStatementTimeout() {
}
// we timed out
if (this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::CONST_CMD) {
if (this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::CONST_CMD ||
this->m_runtime.currentStatementOpcode == Fpy::DirectiveId::STACK_CMD) {
// if we were executing a command, warn that the cmd timed out with its opcode
this->log_WARNING_HI_CommandTimedOut(this->m_runtime.currentCmdOpcode,
this->m_runtime.nextStatementIndex - 1, this->m_sequenceFilePath);
this->log_WARNING_HI_CommandTimedOut(this->m_runtime.currentCmdOpcode, this->currentStatementIdx(),
this->m_sequenceFilePath);
} else {
this->log_WARNING_HI_DirectiveTimedOut(this->m_runtime.currentStatementOpcode,
this->m_runtime.nextStatementIndex - 1, this->m_sequenceFilePath);
this->log_WARNING_HI_DirectiveTimedOut(this->m_runtime.currentStatementOpcode, this->currentStatementIdx(),
this->m_sequenceFilePath);
}
return Signal::result_checkStatementTimeout_statementTimeout;

View File

@ -305,8 +305,8 @@ void FpySequencer::Svc_FpySequencer_SequencerStateMachine_action_setDebugBreakpo
//!
//! called when a sequence failed to execute successfully
void FpySequencer::Svc_FpySequencer_SequencerStateMachine_action_report_seqFailed(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) {
if (this->isConnected_seqDoneOut_OutputPort(0)) {
// report that the sequence failed to internal callers
@ -318,8 +318,8 @@ void FpySequencer::Svc_FpySequencer_SequencerStateMachine_action_report_seqFaile
//!
//! reports that a sequence was started
void FpySequencer::Svc_FpySequencer_SequencerStateMachine_action_report_seqStarted(
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
SmId smId, //!< The state machine id
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
) {
if (this->isConnected_seqDoneOut_OutputPort(0)) {
// report that the sequence started to internal callers

View File

@ -16,46 +16,79 @@ module Svc {
# stack op directives
# all of these are handled at the CPP level by one StackOpDirective
# boolean ops
OR = 15
AND = 16
OR = 10
AND = 11
# integer equalities
IEQ = 17
INE = 18
IEQ = 12
INE = 13
# unsigned integer inequalities
ULT = 19
ULE = 20
UGT = 21
UGE = 22
ULT = 14
ULE = 15
UGT = 16
UGE = 17
# signed integer inequalities
SLT = 23
SLE = 24
SGT = 25
SGE = 26
SLT = 18
SLE = 19
SGT = 20
SGE = 21
# floating point equalities
FEQ = 27
FNE = 28
FEQ = 22
FNE = 23
# floating point inequalities
FLT = 29
FLE = 30
FGT = 31
FGE = 32
NOT = 33
# floating point extension and truncation
FPEXT = 34
FPTRUNC = 35
FLT = 24
FLE = 25
FGT = 26
FGE = 27
NOT = 28
# floating point conversion to signed/unsigned integer,
# and vice versa
FPTOSI = 36
FPTOUI = 37
SITOFP = 38
UITOFP = 39
FPTOSI = 29
FPTOUI = 30
SITOFP = 31
UITOFP = 32
# integer arithmetic
IADD = 33
ISUB = 34
IMUL = 35
UDIV = 36
SDIV = 37
UMOD = 38
SMOD = 39
# float arithmetic
FADD = 40
FSUB = 41
FMUL = 42
FDIV = 43
FLOAT_FLOOR_DIV = 44
FPOW = 45
FLOG = 46
FMOD = 47
# floating point bitwidth conversions
FPEXT = 48
FPTRUNC = 49
# integer bitwidth conversions
# signed integer extend
SIEXT_8_64 = 50
SIEXT_16_64 = 51
SIEXT_32_64 = 52
# zero (unsigned) integer extend
ZIEXT_8_64 = 53
ZIEXT_16_64 = 54
ZIEXT_32_64 = 55
# integer truncate
ITRUNC_64_8 = 56
ITRUNC_64_16 = 57
ITRUNC_64_32 = 58
# end stack op dirs
EXIT = 40
ALLOCATE = 41
STORE = 42
LOAD = 43
PUSH_VAL = 44
EXIT = 59
ALLOCATE = 60
STORE = 61
LOAD = 62
PUSH_VAL = 63
DISCARD = 64
MEMCMP = 65
STACK_CMD = 66
}
struct Header {

View File

@ -203,7 +203,8 @@ TEST_F(FpySequencerTester, cmd) {
Fw::ComBuffer expected;
ASSERT_EQ(expected.serialize(Fw::ComPacketType::FW_PACKET_COMMAND), Fw::SerializeStatus::FW_SERIALIZE_OK);
ASSERT_EQ(expected.serialize(directive.get_opCode()), Fw::SerializeStatus::FW_SERIALIZE_OK);
ASSERT_EQ(expected.serialize(data, sizeof(data), Fw::Serialization::OMIT_LENGTH), Fw::SerializeStatus::FW_SERIALIZE_OK);
ASSERT_EQ(expected.serialize(data, sizeof(data), Fw::Serialization::OMIT_LENGTH),
Fw::SerializeStatus::FW_SERIALIZE_OK);
ASSERT_from_cmdOut_SIZE(1);
ASSERT_from_cmdOut(0, expected, 0);
this->clearHistory();
@ -268,7 +269,7 @@ TEST_F(FpySequencerTester, stackOp) {
result = tester_stackOp_directiveHandler(directiveAND, err);
ASSERT_EQ(result, Signal::stmtResponse_success);
ASSERT_EQ(err, DirectiveError::NO_ERROR);
ASSERT_EQ(tester_get_m_runtime_ptr()->stack[0], 8); // 0b1111
ASSERT_EQ(tester_get_m_runtime_ptr()->stack[0], 8); // 0b1111
ASSERT_EQ(tester_get_m_runtime_ptr()->stackSize, 1); // 0b1111
tester_get_m_runtime_ptr()->stackSize = 0;
@ -710,7 +711,6 @@ TEST_F(FpySequencerTester, fne) {
ASSERT_EQ(tester_get_m_runtime_ptr()->stack[0], 0);
}
TEST_F(FpySequencerTester, not) {
tester_push<U8>(true);
ASSERT_EQ(tester_op_not(), DirectiveError::NO_ERROR);
@ -771,6 +771,108 @@ TEST_F(FpySequencerTester, uitofp) {
ASSERT_EQ(expected, tester_pop<F64>());
}
TEST_F(FpySequencerTester, iadd) {
tester_push<I64>(100);
tester_push<I64>(23);
ASSERT_EQ(tester_op_iadd(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<I64>(), 123);
}
TEST_F(FpySequencerTester, isub) {
tester_push<I64>(150);
tester_push<I64>(27);
ASSERT_EQ(tester_op_isub(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<I64>(), 123);
}
TEST_F(FpySequencerTester, imul) {
tester_push<I64>(41);
tester_push<I64>(3);
ASSERT_EQ(tester_op_imul(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<I64>(), 123);
}
TEST_F(FpySequencerTester, udiv) {
tester_push<U64>(246);
tester_push<U64>(2);
ASSERT_EQ(tester_op_udiv(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<U64>(), 123);
}
TEST_F(FpySequencerTester, sdiv) {
tester_push<I64>(-246);
tester_push<I64>(-2);
ASSERT_EQ(tester_op_sdiv(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<I64>(), 123);
}
TEST_F(FpySequencerTester, umod) {
tester_push<U64>(123);
tester_push<U64>(10);
ASSERT_EQ(tester_op_umod(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<U64>(), 3);
}
TEST_F(FpySequencerTester, smod) {
tester_push<I64>(-7);
tester_push<I64>(-3);
ASSERT_EQ(tester_op_smod(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<I64>(), -1);
}
TEST_F(FpySequencerTester, fadd) {
tester_push<F64>(100.5);
tester_push<F64>(22.5);
ASSERT_EQ(tester_op_fadd(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 123.0);
}
TEST_F(FpySequencerTester, fsub) {
tester_push<F64>(150.5);
tester_push<F64>(27.5);
ASSERT_EQ(tester_op_fsub(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 123.0);
}
TEST_F(FpySequencerTester, fmul) {
tester_push<F64>(41.0);
tester_push<F64>(3.0);
ASSERT_EQ(tester_op_fmul(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 123.0);
}
TEST_F(FpySequencerTester, fdiv) {
tester_push<F64>(246.0);
tester_push<F64>(2.0);
ASSERT_EQ(tester_op_fdiv(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 123.0);
}
TEST_F(FpySequencerTester, float_floor_div) {
tester_push<F64>(246.8);
tester_push<F64>(2.0);
ASSERT_EQ(tester_op_float_floor_div(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 123.0);
}
TEST_F(FpySequencerTester, fpow) {
tester_push<F64>(3.0);
tester_push<F64>(2.0);
ASSERT_EQ(tester_op_fpow(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 9.0);
}
TEST_F(FpySequencerTester, flog) {
tester_push<F64>(2.718281828459045); // e
ASSERT_EQ(tester_op_flog(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), 1.0);
}
TEST_F(FpySequencerTester, fmod) {
tester_push<F64>(-8.5);
tester_push<F64>(-2.5);
ASSERT_EQ(tester_op_fmod(), DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<F64>(), -1.0);
}
TEST_F(FpySequencerTester, exit) {
FpySequencer_ExitDirective directive;
DirectiveError err = DirectiveError::NO_ERROR;
@ -787,6 +889,73 @@ TEST_F(FpySequencerTester, exit) {
ASSERT_EQ(err, DirectiveError::DELIBERATE_FAILURE);
}
TEST_F(FpySequencerTester, discard) {
// Test discarding 4 bytes
tester_push<U32>(0x12345678);
FpySequencer_DiscardDirective directive(4);
DirectiveError err = DirectiveError::NO_ERROR;
Signal result = tester_discard_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_success);
ASSERT_EQ(err, DirectiveError::NO_ERROR);
ASSERT_EQ(tester_get_m_runtime_ptr()->stackSize, 0);
// Test error case - try to discard more bytes than available
tester_push<U8>(0x12);
directive.set_size(2);
result = tester_discard_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_failure);
ASSERT_EQ(err, DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS);
}
TEST_F(FpySequencerTester, stackCmd) {
// Test valid command
tester_push<U32>(0x12345678); // Args
tester_push<FwOpcodeType>(123); // Opcode
FpySequencer_StackCmdDirective directive(4); // 4 bytes of args
DirectiveError err = DirectiveError::NO_ERROR;
Signal result = tester_stackCmd_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_keepWaiting);
ASSERT_EQ(err, DirectiveError::NO_ERROR);
ASSERT_from_cmdOut_SIZE(1);
ASSERT_EQ(tester_get_m_runtime_ptr()->stackSize, 0);
// Test error case - not enough bytes on stack
tester_push<U8>(0x12);
result = tester_stackCmd_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_failure);
ASSERT_EQ(err, DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS);
}
TEST_F(FpySequencerTester, memCmp) {
// Test equal memory blocks
tester_push<U32>(0x12345678);
tester_push<U32>(0x12345678);
FpySequencer_MemCmpDirective directive(4);
DirectiveError err = DirectiveError::NO_ERROR;
Signal result = tester_memCmp_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_success);
ASSERT_EQ(err, DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<U8>(), 1); // Should be true
// Test unequal memory blocks
tester_push<U32>(0x12345678);
tester_push<U32>(0x87654321);
result = tester_memCmp_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_success);
ASSERT_EQ(err, DirectiveError::NO_ERROR);
ASSERT_EQ(tester_pop<U8>(), 0); // Should be false
// test not enough bytes on stack
tester_push<U32>(0x12345678);
tester_push<U8>(0x11);
directive.set_size(3);
result = tester_memCmp_directiveHandler(directive, err);
ASSERT_EQ(result, Signal::stmtResponse_failure);
ASSERT_EQ(err, DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS);
}
TEST_F(FpySequencerTester, checkShouldWakeMismatchBase) {
Fw::Time testTime(TimeBase::TB_WORKSTATION_TIME, 0, 100, 100);
setTestTime(testTime);
@ -1226,28 +1395,32 @@ TEST_F(FpySequencerTester, readBytes) {
tester_get_m_sequenceBuffer_ptr()->setExtBuffer(data, sizeof(data));
Os::File seqFile;
ASSERT_EQ(seqFile.open("test.bin", Os::File::OPEN_READ), Os::File::OP_OK);
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE, FpySequencer_FileReadStage::HEADER, true), Fw::Success::SUCCESS);
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE, FpySequencer_FileReadStage::HEADER, true),
Fw::Success::SUCCESS);
seqFile.close();
// check capacity too low
tester_get_m_sequenceBuffer_ptr()->setExtBuffer(data, Fpy::Header::SERIALIZED_SIZE - 1);
ASSERT_EQ(seqFile.open("test.bin", Os::File::OPEN_READ), Os::File::OP_OK);
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE, FpySequencer_FileReadStage::HEADER, true), Fw::Success::FAILURE);
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE, FpySequencer_FileReadStage::HEADER, true),
Fw::Success::FAILURE);
seqFile.close();
// check not enough bytes
tester_get_m_sequenceBuffer_ptr()->setExtBuffer(data,
Fpy::Header::SERIALIZED_SIZE + Fpy::Footer::SERIALIZED_SIZE + 1);
ASSERT_EQ(seqFile.open("test.bin", Os::File::OPEN_READ), Os::File::OP_OK);
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE + Fpy::Footer::SERIALIZED_SIZE + 1, FpySequencer_FileReadStage::HEADER, true),
ASSERT_EQ(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE + Fpy::Footer::SERIALIZED_SIZE + 1,
FpySequencer_FileReadStage::HEADER, true),
Fw::Success::FAILURE);
seqFile.close();
removeFile("test.bin");
// read after close
ASSERT_DEATH_IF_SUPPORTED(
tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE + Fpy::Footer::SERIALIZED_SIZE, FpySequencer_FileReadStage::HEADER, true), "Assert: ");
ASSERT_DEATH_IF_SUPPORTED(tester_readBytes(seqFile, Fpy::Header::SERIALIZED_SIZE + Fpy::Footer::SERIALIZED_SIZE,
FpySequencer_FileReadStage::HEADER, true),
"Assert: ");
}
TEST_F(FpySequencerTester, validate) {
@ -1543,6 +1716,65 @@ TEST_F(FpySequencerTester, deserialize_exit) {
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(0);
}
TEST_F(FpySequencerTester, deserialize_discard) {
FpySequencer::DirectiveUnion actual;
FpySequencer_DiscardDirective dir(123);
add_DISCARD(dir);
Fw::Success result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::SUCCESS);
ASSERT_EQ(actual.discard, dir);
// write some junk after buf, make sure it fails
seq.get_statements()[0].get_argBuf().serialize(123);
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
this->clearHistory();
// clear args, make sure it fails
seq.get_statements()[0].get_argBuf().resetSer();
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
}
TEST_F(FpySequencerTester, deserialize_stackCmd) {
FpySequencer::DirectiveUnion actual;
FpySequencer_StackCmdDirective dir(123);
add_STACK_CMD(dir);
Fw::Success result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::SUCCESS);
ASSERT_EQ(actual.stackCmd, dir);
// write some junk after buf, make sure it fails
seq.get_statements()[0].get_argBuf().serialize(123);
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
this->clearHistory();
// clear args, make sure it fails
seq.get_statements()[0].get_argBuf().resetSer();
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
}
TEST_F(FpySequencerTester, deserialize_memCmp) {
FpySequencer::DirectiveUnion actual;
FpySequencer_MemCmpDirective dir(123);
add_MEMCMP(dir);
Fw::Success result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::SUCCESS);
ASSERT_EQ(actual.memCmp, dir);
// write some junk after buf, make sure it fails
seq.get_statements()[0].get_argBuf().serialize(123);
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
this->clearHistory();
// clear args, make sure it fails
seq.get_statements()[0].get_argBuf().resetSer();
result = tester_deserializeDirective(seq.get_statements()[0], actual);
ASSERT_EQ(result, Fw::Success::FAILURE);
ASSERT_EVENTS_DirectiveDeserializeError_SIZE(1);
}
// caught a bug
TEST_F(FpySequencerTester, checkTimers) {
allocMem();

View File

@ -32,13 +32,12 @@ TEST_F(FpySequencerTester, ComplexControlFlow) {
add_IF(6);
// if true
add_NO_OP();
add_GOTO(9); // goto end
add_GOTO(9); // goto end
// else
add_NO_OP();
add_NO_OP();
add_NO_OP();
writeAndRun();
dispatchUntilState(State::IDLE);
ASSERT_EQ(tester_get_m_tlm_ptr()->lastDirectiveError, DirectiveError::NO_ERROR);
@ -65,7 +64,7 @@ TEST_F(FpySequencerTester, OrOfTlmAndReg) {
add_IF(8);
// if true
add_NO_OP();
add_GOTO(11); // goto end
add_GOTO(11); // goto end
// else
add_NO_OP();
add_NO_OP();
@ -97,7 +96,7 @@ TEST_F(FpySequencerTester, CmpIntTlm) {
add_IF(8);
// if true
add_NO_OP();
add_GOTO(11); // goto end
add_GOTO(11); // goto end
// else
add_NO_OP();
add_NO_OP();
@ -135,4 +134,4 @@ TEST_F(FpySequencerTester, NotTrueSeq) {
ASSERT_EQ(tester_get_m_tlm_ptr()->lastDirectiveError, DirectiveError::NO_ERROR);
}
}
} // namespace Svc

View File

@ -189,7 +189,8 @@ void FpySequencerTester::add_CONST_CMD(FwOpcodeType opcode) {
void FpySequencerTester::add_CONST_CMD(FpySequencer_ConstCmdDirective dir) {
Fw::StatementArgBuffer buf;
FW_ASSERT(buf.serialize(dir.get_opCode()) == Fw::SerializeStatus::FW_SERIALIZE_OK);
FW_ASSERT(buf.serialize(dir.get_argBuf(), dir.get__argBufSize(), Fw::Serialization::OMIT_LENGTH) == Fw::SerializeStatus::FW_SERIALIZE_OK);
FW_ASSERT(buf.serialize(dir.get_argBuf(), dir.get__argBufSize(), Fw::Serialization::OMIT_LENGTH) ==
Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::CONST_CMD, buf);
}
@ -226,7 +227,8 @@ void FpySequencerTester::add_LOAD(FpySequencer_LoadDirective dir) {
FW_ASSERT(buf.serialize(dir) == Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::LOAD, buf);
}
template <typename T> void FpySequencerTester::add_PUSH_VAL(T val) {
template <typename T>
void FpySequencerTester::add_PUSH_VAL(T val) {
Fw::StatementArgBuffer buf;
FW_ASSERT(buf.serializeFrom(val) == Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::PUSH_VAL, buf);
@ -240,7 +242,30 @@ template void FpySequencerTester::add_PUSH_VAL(I8);
template void FpySequencerTester::add_PUSH_VAL(I16);
template void FpySequencerTester::add_PUSH_VAL(I32);
template void FpySequencerTester::add_PUSH_VAL(I64);
void FpySequencerTester::add_DISCARD(U16 size) {
add_DISCARD(FpySequencer_DiscardDirective(size));
}
void FpySequencerTester::add_DISCARD(FpySequencer_DiscardDirective dir) {
Fw::StatementArgBuffer buf;
FW_ASSERT(buf.serialize(dir) == Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::DISCARD, buf);
}
void FpySequencerTester::add_STACK_CMD(U16 size) {
add_STACK_CMD(FpySequencer_StackCmdDirective(size));
}
void FpySequencerTester::add_STACK_CMD(FpySequencer_StackCmdDirective dir) {
Fw::StatementArgBuffer buf;
FW_ASSERT(buf.serialize(dir) == Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::STACK_CMD, buf);
}
void FpySequencerTester::add_MEMCMP(U16 size) {
add_MEMCMP(FpySequencer_MemCmpDirective(size));
}
void FpySequencerTester::add_MEMCMP(FpySequencer_MemCmpDirective dir) {
Fw::StatementArgBuffer buf;
FW_ASSERT(buf.serialize(dir) == Fw::SerializeStatus::FW_SERIALIZE_OK);
addDirective(Fpy::DirectiveId::MEMCMP, buf);
}
//! Handle a text event
void FpySequencerTester::textLogIn(FwEventIdType id, //!< The event ID
const Fw::Time& timeTag, //!< The time
@ -321,12 +346,12 @@ Signal FpySequencerTester::tester_if_directiveHandler(const FpySequencer_IfDirec
}
Signal FpySequencerTester::tester_storePrm_directiveHandler(const FpySequencer_StorePrmDirective& directive,
DirectiveError& err) {
DirectiveError& err) {
return this->cmp.storePrm_directiveHandler(directive, err);
}
Signal FpySequencerTester::tester_storeTlmVal_directiveHandler(const FpySequencer_StoreTlmValDirective& directive,
DirectiveError& err) {
DirectiveError& err) {
return this->cmp.storeTlmVal_directiveHandler(directive, err);
}
@ -336,15 +361,30 @@ Signal FpySequencerTester::tester_exit_directiveHandler(const FpySequencer_ExitD
}
Signal FpySequencerTester::tester_constCmd_directiveHandler(const FpySequencer_ConstCmdDirective& directive,
DirectiveError& err) {
DirectiveError& err) {
return this->cmp.constCmd_directiveHandler(directive, err);
}
Signal FpySequencerTester::tester_stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive,
DirectiveError& err) {
DirectiveError& err) {
return this->cmp.stackOp_directiveHandler(directive, err);
}
Signal FpySequencerTester::tester_discard_directiveHandler(const FpySequencer_DiscardDirective& directive,
DirectiveError& err) {
return this->cmp.discard_directiveHandler(directive, err);
}
Signal FpySequencerTester::tester_stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive,
DirectiveError& err) {
return this->cmp.stackCmd_directiveHandler(directive, err);
}
Signal FpySequencerTester::tester_memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive,
DirectiveError& err) {
return this->cmp.memCmp_directiveHandler(directive, err);
}
Fw::Success FpySequencerTester::tester_deserializeDirective(const Fpy::Statement& stmt,
Svc::FpySequencer::DirectiveUnion& deserializedDirective) {
return this->cmp.deserializeDirective(stmt, deserializedDirective);
@ -370,7 +410,10 @@ Svc::FpySequencer::Telemetry* FpySequencerTester::tester_get_m_tlm_ptr() {
return &this->cmp.m_tlm;
}
Fw::Success FpySequencerTester::tester_readBytes(Os::File& file, FwSizeType readLen, FpySequencer_FileReadStage readStage, bool updateCrc) {
Fw::Success FpySequencerTester::tester_readBytes(Os::File& file,
FwSizeType readLen,
FpySequencer_FileReadStage readStage,
bool updateCrc) {
return this->cmp.readBytes(file, readLen, readStage, updateCrc);
}
@ -506,6 +549,78 @@ DirectiveError FpySequencerTester::tester_op_sitofp() {
DirectiveError FpySequencerTester::tester_op_uitofp() {
return this->cmp.op_uitofp();
}
DirectiveError FpySequencerTester::tester_op_iadd() {
return this->cmp.op_iadd();
}
DirectiveError FpySequencerTester::tester_op_isub() {
return this->cmp.op_isub();
}
DirectiveError FpySequencerTester::tester_op_imul() {
return this->cmp.op_imul();
}
DirectiveError FpySequencerTester::tester_op_udiv() {
return this->cmp.op_udiv();
}
DirectiveError FpySequencerTester::tester_op_sdiv() {
return this->cmp.op_sdiv();
}
DirectiveError FpySequencerTester::tester_op_umod() {
return this->cmp.op_umod();
}
DirectiveError FpySequencerTester::tester_op_smod() {
return this->cmp.op_smod();
}
DirectiveError FpySequencerTester::tester_op_fadd() {
return this->cmp.op_fadd();
}
DirectiveError FpySequencerTester::tester_op_fsub() {
return this->cmp.op_fsub();
}
DirectiveError FpySequencerTester::tester_op_fmul() {
return this->cmp.op_fmul();
}
DirectiveError FpySequencerTester::tester_op_fdiv() {
return this->cmp.op_fdiv();
}
DirectiveError FpySequencerTester::tester_op_float_floor_div() {
return this->cmp.op_float_floor_div();
}
DirectiveError FpySequencerTester::tester_op_fpow() {
return this->cmp.op_fpow();
}
DirectiveError FpySequencerTester::tester_op_flog() {
return this->cmp.op_flog();
}
DirectiveError FpySequencerTester::tester_op_fmod() {
return this->cmp.op_fmod();
}
DirectiveError FpySequencerTester::tester_op_siext_8_64() {
return this->cmp.op_siext_8_64();
}
DirectiveError FpySequencerTester::tester_op_siext_16_64() {
return this->cmp.op_siext_16_64();
}
DirectiveError FpySequencerTester::tester_op_siext_32_64() {
return this->cmp.op_siext_32_64();
}
DirectiveError FpySequencerTester::tester_op_ziext_8_64() {
return this->cmp.op_ziext_8_64();
}
DirectiveError FpySequencerTester::tester_op_ziext_16_64() {
return this->cmp.op_ziext_16_64();
}
DirectiveError FpySequencerTester::tester_op_ziext_32_64() {
return this->cmp.op_ziext_32_64();
}
DirectiveError FpySequencerTester::tester_op_itrunc_64_8() {
return this->cmp.op_itrunc_64_8();
}
DirectiveError FpySequencerTester::tester_op_itrunc_64_16() {
return this->cmp.op_itrunc_64_16();
}
DirectiveError FpySequencerTester::tester_op_itrunc_64_32() {
return this->cmp.op_itrunc_64_32();
}
void FpySequencerTester::tester_doDispatch() {
this->cmp.doDispatch();
}
@ -518,11 +633,13 @@ void FpySequencerTester::tester_setState(Svc::FpySequencer_SequencerStateMachine
FpySequencer_SequencerStateMachineTester::setState(this->cmp.m_stateMachine_sequencer, state);
}
void FpySequencerTester::tester_dispatchDirective(const FpySequencer::DirectiveUnion& directive, const Fpy::DirectiveId& id) {
void FpySequencerTester::tester_dispatchDirective(const FpySequencer::DirectiveUnion& directive,
const Fpy::DirectiveId& id) {
this->cmp.dispatchDirective(directive, id);
}
template <typename T> void FpySequencerTester::tester_push(T val) {
template <typename T>
void FpySequencerTester::tester_push(T val) {
cmp.push<T>(val);
}
template void FpySequencerTester::tester_push(U8);
@ -535,7 +652,8 @@ template void FpySequencerTester::tester_push(I32);
template void FpySequencerTester::tester_push(I64);
template void FpySequencerTester::tester_push(F32);
template void FpySequencerTester::tester_push(F64);
template <typename T> T FpySequencerTester::tester_pop() {
template <typename T>
T FpySequencerTester::tester_pop() {
return cmp.pop<T>();
}
template U8 FpySequencerTester::tester_pop();

View File

@ -103,7 +103,14 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
void add_STORE(FpySequencer_StoreDirective dir);
void add_LOAD(U16 lvarOffset, U16 size);
void add_LOAD(FpySequencer_LoadDirective dir);
template <typename T> void add_PUSH_VAL(T val);
void add_DISCARD(U16 size);
void add_DISCARD(FpySequencer_DiscardDirective dir);
void add_STACK_CMD(U16 size);
void add_STACK_CMD(FpySequencer_StackCmdDirective dir);
void add_MEMCMP(U16 size);
void add_MEMCMP(FpySequencer_MemCmpDirective dir);
template <typename T>
void add_PUSH_VAL(T val);
//! Handle a text event
void textLogIn(FwEventIdType id, //!< The event ID
const Fw::Time& timeTag, //!< The time
@ -132,13 +139,16 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
Signal tester_noOp_directiveHandler(const FpySequencer_NoOpDirective& directive, DirectiveError& err);
Signal tester_waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& err);
Signal tester_waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive, DirectiveError& err);
Signal tester_goto_directiveHandler(const Svc::FpySequencer_GotoDirective &directive, DirectiveError& err);
Signal tester_goto_directiveHandler(const Svc::FpySequencer_GotoDirective& directive, DirectiveError& err);
Signal tester_if_directiveHandler(const FpySequencer_IfDirective& directive, DirectiveError& err);
Signal tester_storePrm_directiveHandler(const FpySequencer_StorePrmDirective& directive, DirectiveError& err);
Signal tester_storeTlmVal_directiveHandler(const FpySequencer_StoreTlmValDirective& directive, DirectiveError& err);
Signal tester_exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& err);
Signal tester_constCmd_directiveHandler(const FpySequencer_ConstCmdDirective& directive, DirectiveError& err);
Signal tester_stackOp_directiveHandler(const FpySequencer_StackOpDirective& directive, DirectiveError& err);
Signal tester_discard_directiveHandler(const FpySequencer_DiscardDirective& directive, DirectiveError& err);
Signal tester_stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& err);
Signal tester_memCmp_directiveHandler(const FpySequencer_MemCmpDirective& directive, DirectiveError& err);
DirectiveError tester_op_or();
DirectiveError tester_op_and();
DirectiveError tester_op_ieq();
@ -164,19 +174,47 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
DirectiveError tester_op_fptosi();
DirectiveError tester_op_sitofp();
DirectiveError tester_op_uitofp();
DirectiveError tester_op_iadd();
DirectiveError tester_op_isub();
DirectiveError tester_op_imul();
DirectiveError tester_op_udiv();
DirectiveError tester_op_sdiv();
DirectiveError tester_op_umod();
DirectiveError tester_op_smod();
DirectiveError tester_op_fadd();
DirectiveError tester_op_fsub();
DirectiveError tester_op_fmul();
DirectiveError tester_op_fdiv();
DirectiveError tester_op_float_floor_div();
DirectiveError tester_op_fpow();
DirectiveError tester_op_flog();
DirectiveError tester_op_fmod();
DirectiveError tester_op_siext_8_64();
DirectiveError tester_op_siext_16_64();
DirectiveError tester_op_siext_32_64();
DirectiveError tester_op_ziext_8_64();
DirectiveError tester_op_ziext_16_64();
DirectiveError tester_op_ziext_32_64();
DirectiveError tester_op_itrunc_64_8();
DirectiveError tester_op_itrunc_64_16();
DirectiveError tester_op_itrunc_64_32();
FpySequencer::Runtime* tester_get_m_runtime_ptr();
Fw::ExternalSerializeBuffer* tester_get_m_sequenceBuffer_ptr();
void tester_set_m_sequencesStarted(U64 val);
void tester_set_m_statementsDispatched(U64 val);
U64 tester_get_m_sequencesStarted();
U64 tester_get_m_statementsDispatched();
Fw::Success tester_deserializeDirective(const Fpy::Statement& stmt, Svc::FpySequencer::DirectiveUnion& deserializedDirective);
Fw::Success tester_deserializeDirective(const Fpy::Statement& stmt,
Svc::FpySequencer::DirectiveUnion& deserializedDirective);
Fpy::Sequence* tester_get_m_sequenceObj_ptr();
Svc::Signal tester_dispatchStatement();
Fw::Success tester_validate();
Fw::String tester_get_m_sequenceFilePath();
void tester_set_m_sequenceFilePath(Fw::String str);
Fw::Success tester_readBytes(Os::File& file, FwSizeType readLen, FpySequencer_FileReadStage readStage, bool updateCrc = true);
Fw::Success tester_readBytes(Os::File& file,
FwSizeType readLen,
FpySequencer_FileReadStage readStage,
bool updateCrc = true);
Fw::Success tester_readFooter();
Fw::Success tester_readBody();
Fw::Success tester_readHeader();
@ -189,8 +227,10 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
void tester_setState(Svc::FpySequencer_SequencerStateMachineStateMachineBase::State state);
Svc::FpySequencer_SequencerStateMachineStateMachineBase::State tester_getState();
void tester_dispatchDirective(const FpySequencer::DirectiveUnion& directive, const Fpy::DirectiveId& id);
template <typename T> void tester_push(T val);
template <typename T> T tester_pop();
template <typename T>
void tester_push(T val);
template <typename T>
T tester_pop();
public:
// ----------------------------------------------------------------------
@ -198,24 +238,16 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
// ----------------------------------------------------------------------
//! Get the OPCODE_RUN value
static FwOpcodeType get_OPCODE_RUN() {
return FpySequencerComponentBase::OPCODE_RUN;
}
static FwOpcodeType get_OPCODE_RUN() { return FpySequencerComponentBase::OPCODE_RUN; }
//! Get the OPCODE_VALIDATE value
static FwOpcodeType get_OPCODE_VALIDATE() {
return FpySequencerComponentBase::OPCODE_VALIDATE;
}
static FwOpcodeType get_OPCODE_VALIDATE() { return FpySequencerComponentBase::OPCODE_VALIDATE; }
//! Get the OPCODE_RUN_VALIDATED value
static FwOpcodeType get_OPCODE_RUN_VALIDATED() {
return FpySequencerComponentBase::OPCODE_RUN_VALIDATED;
}
static FwOpcodeType get_OPCODE_RUN_VALIDATED() { return FpySequencerComponentBase::OPCODE_RUN_VALIDATED; }
//! Get the OPCODE_CANCEL value
static FwOpcodeType get_OPCODE_CANCEL() {
return FpySequencerComponentBase::OPCODE_CANCEL;
}
static FwOpcodeType get_OPCODE_CANCEL() { return FpySequencerComponentBase::OPCODE_CANCEL; }
//! Get the OPCODE_DEBUG_CLEAR_BREAKPOINT value
static FwOpcodeType get_OPCODE_DEBUG_CLEAR_BREAKPOINT() {
@ -228,16 +260,10 @@ class FpySequencerTester : public FpySequencerGTestBase, public ::testing::Test
}
//! Get the OPCODE_DEBUG_BREAK value
static FwOpcodeType get_OPCODE_DEBUG_BREAK() {
return FpySequencerComponentBase::OPCODE_DEBUG_BREAK;
}
static FwOpcodeType get_OPCODE_DEBUG_BREAK() { return FpySequencerComponentBase::OPCODE_DEBUG_BREAK; }
//! Get the OPCODE_DEBUG_CONTINUE value
static FwOpcodeType get_OPCODE_DEBUG_CONTINUE() {
return FpySequencerComponentBase::OPCODE_DEBUG_CONTINUE;
}
static FwOpcodeType get_OPCODE_DEBUG_CONTINUE() { return FpySequencerComponentBase::OPCODE_DEBUG_CONTINUE; }
};
class FpySequencer_SequencerStateMachineTester {
@ -257,10 +283,7 @@ class FpySequencer_SequencerStateMachineTester {
// ----------------------------------------------------------------------
// Test access to private and protected methods and members
// ----------------------------------------------------------------------
static void setState(FpySequencer_SequencerStateMachineStateMachineBase& sm, State s){
sm.m_state = s;
}
static void setState(FpySequencer_SequencerStateMachineStateMachineBase& sm, State s) { sm.m_state = s; }
};
} // namespace Svc