diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 06fa884bad..50e9ebd16f 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -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 diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index d537a91c54..c159b7ed63 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -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 diff --git a/Svc/FpySequencer/FpySequencer.cpp b/Svc/FpySequencer/FpySequencer.cpp index 24fe2b54ce..c91c6ffa62 100644 --- a/Svc/FpySequencer/FpySequencer.cpp +++ b/Svc/FpySequencer/FpySequencer.cpp @@ -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(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(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); diff --git a/Svc/FpySequencer/FpySequencer.hpp b/Svc/FpySequencer/FpySequencer.hpp index cabe094713..c61989db7b 100644 --- a/Svc/FpySequencer/FpySequencer.hpp +++ b/Svc/FpySequencer/FpySequencer.hpp @@ -25,8 +25,7 @@ static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits::max() "Sequence arg count must be below U8 max"); static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits::max(), "Sequence statement count must be below U16 max"); -static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits::max(), - "Max stack size must be below U16 max"); +static_assert(Svc::Fpy::MAX_STACK_SIZE <= std::numeric_limits::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 diff --git a/Svc/FpySequencer/FpySequencerDirectives.cpp b/Svc/FpySequencer/FpySequencerDirectives.cpp index 3f1d835ff7..e11a184f90 100644 --- a/Svc/FpySequencer/FpySequencerDirectives.cpp +++ b/Svc/FpySequencer/FpySequencerDirectives.cpp @@ -1,5 +1,5 @@ -#include #include +#include #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(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(((this->m_sequencesStarted & 0xFFFF) << 16) | (this->m_statementsDispatched & 0xFFFF)); + + this->cmdOut_out(0, cmdBuf, cmdUid); + + return Fw::Success::SUCCESS; +} + template 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(this->m_runtime.stackSize), static_cast(sizeof(T))); + FW_ASSERT(this->m_runtime.stackSize >= sizeof(T), static_cast(this->m_runtime.stackSize), + static_cast(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( - (static_cast(valBytes[7]) << 0) | - (static_cast(valBytes[6]) << 8) | - (static_cast(valBytes[5]) << 16) | - (static_cast(valBytes[4]) << 24) | - (static_cast(valBytes[3]) << 32) | - (static_cast(valBytes[2]) << 40) | - (static_cast(valBytes[1]) << 48) | - (static_cast(valBytes[0]) << 56)); + return static_cast((static_cast(valBytes[7]) << 0) | (static_cast(valBytes[6]) << 8) | + (static_cast(valBytes[5]) << 16) | (static_cast(valBytes[4]) << 24) | + (static_cast(valBytes[3]) << 32) | (static_cast(valBytes[2]) << 40) | + (static_cast(valBytes[1]) << 48) | (static_cast(valBytes[0]) << 56)); } else if (sizeof(T) == 4) { - return static_cast( - (static_cast(valBytes[3]) << 0) | - (static_cast(valBytes[2]) << 8) | - (static_cast(valBytes[1]) << 16) | - (static_cast(valBytes[0]) << 24)); + return static_cast((static_cast(valBytes[3]) << 0) | (static_cast(valBytes[2]) << 8) | + (static_cast(valBytes[1]) << 16) | (static_cast(valBytes[0]) << 24)); } else if (sizeof(T) == 2) { - return static_cast( - (static_cast(valBytes[1]) << 0) | - (static_cast(valBytes[0]) << 8)); + return static_cast((static_cast(valBytes[1]) << 0) | (static_cast(valBytes[0]) << 8)); } else { return static_cast(valBytes[0]); } @@ -74,14 +98,16 @@ template I16 FpySequencer::pop(); template I32 FpySequencer::pop(); template I64 FpySequencer::pop(); -template <> F32 FpySequencer::pop() { +template <> +F32 FpySequencer::pop() { U32 endianness = this->pop(); F32 val; memcpy(&val, &endianness, sizeof(val)); return val; } -template <> F64 FpySequencer::pop() { +template <> +F64 FpySequencer::pop() { U64 endianness = this->pop(); F64 val; memcpy(&val, &endianness, sizeof(val)); @@ -91,7 +117,8 @@ template <> F64 FpySequencer::pop() { template 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(this->m_runtime.stackSize), static_cast(sizeof(T))); + FW_ASSERT(this->m_runtime.stackSize + sizeof(val) < Fpy::MAX_STACK_SIZE, + static_cast(this->m_runtime.stackSize), static_cast(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 val) { +template <> +void FpySequencer::push(F32 val) { U32 endianness; memcpy(&endianness, &val, sizeof(val)); this->push(endianness); } -template <> void FpySequencer::push(F64 val) { +template <> +void FpySequencer::push(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(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(((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(this->pop() | this->pop())); 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(this->pop() & this->pop())); 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(this->pop() == this->pop())); 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(this->pop() != this->pop())); 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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(); @@ -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(this->pop() == 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(this->pop())); @@ -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(this->pop())); 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(this->pop())); 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(this->pop())); 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(this->pop())); 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(this->pop())); 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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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(); + if (rhs == 0) { + return DirectiveError::DOMAIN_ERROR; + } + U64 lhs = this->pop(); + this->push(static_cast(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(); + if (rhs == 0) { + return DirectiveError::DOMAIN_ERROR; + } + I64 lhs = this->pop(); + I64 res = static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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 lhs = this->pop(); + this->push(static_cast(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(); + this->push(static_cast(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(); + if (rhs == 0.0) { + return DirectiveError::DOMAIN_ERROR; + } + F64 lhs = this->pop(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(); + this->push(static_cast(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(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(1); + } else { + this->push(0); + } + return Signal::stmtResponse_success; +} + +Signal FpySequencer::stackCmd_directiveHandler(const FpySequencer_StackCmdDirective& directive, DirectiveError& error) { + if (this->m_runtime.stackSize < static_cast(directive.get_argsSize() + sizeof(FwOpcodeType))) { + error = DirectiveError::STACK_ACCESS_OUT_OF_BOUNDS; + return Signal::stmtResponse_failure; + } + + FwOpcodeType opcode = this->pop(); + 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 diff --git a/Svc/FpySequencer/FpySequencerDirectives.fppi b/Svc/FpySequencer/FpySequencerDirectives.fppi index f09315b1a5..4e0f07db70 100644 --- a/Svc/FpySequencer/FpySequencerDirectives.fppi +++ b/Svc/FpySequencer/FpySequencerDirectives.fppi @@ -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 } \ No newline at end of file diff --git a/Svc/FpySequencer/FpySequencerRunState.cpp b/Svc/FpySequencer/FpySequencerRunState.cpp index f5421447ac..e703767032 100644 --- a/Svc/FpySequencer/FpySequencerRunState.cpp +++ b/Svc/FpySequencer/FpySequencerRunState.cpp @@ -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(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(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; diff --git a/Svc/FpySequencer/FpySequencerStateMachine.cpp b/Svc/FpySequencer/FpySequencerStateMachine.cpp index 0668c307a7..05fe54c9dd 100644 --- a/Svc/FpySequencer/FpySequencerStateMachine.cpp +++ b/Svc/FpySequencer/FpySequencerStateMachine.cpp @@ -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 diff --git a/Svc/FpySequencer/FpySequencerTypes.fpp b/Svc/FpySequencer/FpySequencerTypes.fpp index d0b6df32b7..591efbe5eb 100644 --- a/Svc/FpySequencer/FpySequencerTypes.fpp +++ b/Svc/FpySequencer/FpySequencerTypes.fpp @@ -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 { diff --git a/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp b/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp index 89fe35ce55..7b647f1111 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTestMain.cpp @@ -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(true); ASSERT_EQ(tester_op_not(), DirectiveError::NO_ERROR); @@ -771,6 +771,108 @@ TEST_F(FpySequencerTester, uitofp) { ASSERT_EQ(expected, tester_pop()); } +TEST_F(FpySequencerTester, iadd) { + tester_push(100); + tester_push(23); + ASSERT_EQ(tester_op_iadd(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123); +} + +TEST_F(FpySequencerTester, isub) { + tester_push(150); + tester_push(27); + ASSERT_EQ(tester_op_isub(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123); +} + +TEST_F(FpySequencerTester, imul) { + tester_push(41); + tester_push(3); + ASSERT_EQ(tester_op_imul(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123); +} + +TEST_F(FpySequencerTester, udiv) { + tester_push(246); + tester_push(2); + ASSERT_EQ(tester_op_udiv(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123); +} + +TEST_F(FpySequencerTester, sdiv) { + tester_push(-246); + tester_push(-2); + ASSERT_EQ(tester_op_sdiv(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123); +} + +TEST_F(FpySequencerTester, umod) { + tester_push(123); + tester_push(10); + ASSERT_EQ(tester_op_umod(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 3); +} + +TEST_F(FpySequencerTester, smod) { + tester_push(-7); + tester_push(-3); + ASSERT_EQ(tester_op_smod(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), -1); +} + +TEST_F(FpySequencerTester, fadd) { + tester_push(100.5); + tester_push(22.5); + ASSERT_EQ(tester_op_fadd(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123.0); +} + +TEST_F(FpySequencerTester, fsub) { + tester_push(150.5); + tester_push(27.5); + ASSERT_EQ(tester_op_fsub(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123.0); +} + +TEST_F(FpySequencerTester, fmul) { + tester_push(41.0); + tester_push(3.0); + ASSERT_EQ(tester_op_fmul(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123.0); +} + +TEST_F(FpySequencerTester, fdiv) { + tester_push(246.0); + tester_push(2.0); + ASSERT_EQ(tester_op_fdiv(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123.0); +} + +TEST_F(FpySequencerTester, float_floor_div) { + tester_push(246.8); + tester_push(2.0); + ASSERT_EQ(tester_op_float_floor_div(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 123.0); +} + +TEST_F(FpySequencerTester, fpow) { + tester_push(3.0); + tester_push(2.0); + ASSERT_EQ(tester_op_fpow(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 9.0); +} + +TEST_F(FpySequencerTester, flog) { + tester_push(2.718281828459045); // e + ASSERT_EQ(tester_op_flog(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 1.0); +} +TEST_F(FpySequencerTester, fmod) { + tester_push(-8.5); + tester_push(-2.5); + ASSERT_EQ(tester_op_fmod(), DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), -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(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(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(0x12345678); // Args + tester_push(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(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(0x12345678); + tester_push(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(), 1); // Should be true + + // Test unequal memory blocks + tester_push(0x12345678); + tester_push(0x87654321); + result = tester_memCmp_directiveHandler(directive, err); + ASSERT_EQ(result, Signal::stmtResponse_success); + ASSERT_EQ(err, DirectiveError::NO_ERROR); + ASSERT_EQ(tester_pop(), 0); // Should be false + + // test not enough bytes on stack + tester_push(0x12345678); + tester_push(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(); diff --git a/Svc/FpySequencer/test/ut/FpySequencerTestSequences.cpp b/Svc/FpySequencer/test/ut/FpySequencerTestSequences.cpp index b5f5c58210..a54754692a 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTestSequences.cpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTestSequences.cpp @@ -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); } -} \ No newline at end of file +} // namespace Svc \ No newline at end of file diff --git a/Svc/FpySequencer/test/ut/FpySequencerTester.cpp b/Svc/FpySequencer/test/ut/FpySequencerTester.cpp index ef9a6324f7..2fba88730f 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTester.cpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTester.cpp @@ -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 void FpySequencerTester::add_PUSH_VAL(T val) { +template +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 void FpySequencerTester::tester_push(T val) { +template +void FpySequencerTester::tester_push(T val) { cmp.push(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 T FpySequencerTester::tester_pop() { +template +T FpySequencerTester::tester_pop() { return cmp.pop(); } template U8 FpySequencerTester::tester_pop(); diff --git a/Svc/FpySequencer/test/ut/FpySequencerTester.hpp b/Svc/FpySequencer/test/ut/FpySequencerTester.hpp index 3456700981..e4138a6ee7 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTester.hpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTester.hpp @@ -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 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 + 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 void tester_push(T val); - template T tester_pop(); + template + void tester_push(T val); + template + 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