/*========================== begin_copyright_notice ============================
Copyright (C) 2021-2025 Intel Corporation

SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/

/*!
 * @file Abstract representation of the GEN instruction 
 */

#ifndef IGT_INS_H_
#define IGT_INS_H_

#include "ged.h"
#include "gt_basic_defs.h"
#include "igt_core.h"
#include "gt_ins_fields.h"
#include "gt_reg.h"

namespace gtpin
{
#pragma pack(push, 8)

/// @internal
class GtIns;                                    ///< Representation of GEN instruction in GTPin
/// @ingroup GTPIN_GEN_INSTRUCTION
using InsId = Uint32Validatable<struct _InsId>; ///< Identifier of the IGtIns instance

/* ===================================================================================================== */
// Class IGtIns
/* ===================================================================================================== */
/*! @ingroup GTPIN_GEN_INSTRUCTION
 * @brief Abstract representation of the GEN instruction.
 * 
 * This interface provides methods for inspection operands and other attributes of the original kernel's
 * instructions. It is also applicable to instructions in the instrumentation procedures.
 * 
 * @par Availability:
 * - IGtTool::OnKernelBuild
 */
class IGtIns
{
public:
    
    virtual InsId               Id()            const = 0; ///< Get unique identifier of this instruction, assigned by GTPin
    virtual const ged_ins_t&    GetGedIns()     const = 0; ///< Get representation of this instruction in GED
    virtual const GtIns&        GetGtIns()      const = 0; ///< @internal Get representation of this instruction in GTPin

    //----------------------------------------------------------------------------------------------------
    // Basic accessors
    //----------------------------------------------------------------------------------------------------
    virtual GtGenModelId    GenModelId()         const = 0; ///< Get identifier of the GEN model, this instruction is created for
    virtual GtOpcode        Opcode()             const = 0; ///< Get opcode of the instruction 
    virtual bool            IsCompact()          const = 0; ///< Return true/false for a compact/native GEN instruction
    virtual uint32_t        Size()               const = 0; ///< Get size of the encoded instruction in bytes
    virtual GtExecSize      ExecSize()           const = 0; ///< Get execution size of the instruction
    virtual GtExecMask      ExecMask()           const = 0; ///< Get execution mask of the instruction
    virtual GtPredicate     Predicate()          const = 0; ///< Get predicate of the instruction
    virtual bool            IsWriteMaskEnabled() const = 0; ///< Return true, if WrEn mask effects the operation
    virtual bool            IsAccWriteEnabled()  const = 0; ///< Return true, if instruction implicitly modifies acc register
    virtual bool            IsBreakpointSet()    const = 0; ///< Return true, if instruction breaks into debugger
    virtual GtThreadCtrl    ThreadCtrl()         const = 0; ///< Get thread control attribute of the instruction
    virtual GtCondModifier  CondModifier()       const = 0; ///< Get conditional modifier of the instruction
    virtual GtReg           CondFlagReg()        const = 0; ///< Get conditional flag of the instruction
    virtual GtSystolicInfo  SystolicInfo()       const = 0; ///< Get specific properties/attributes of the systolic instruction
    virtual GtMathFC        MathFC()             const = 0; ///< Get MathFC of the math instruction

   //----------------------------------------------------------------------------------------------------
    // Destination operand accessors
    //----------------------------------------------------------------------------------------------------
    virtual bool            HasDstOperand()     const = 0;  ///< Return true, if this instruction has a destination operand
    virtual GtRegFileType   DstRegFile()        const = 0;  ///< Get register file of the destination operand
    virtual GtDstRegion     DstOperand()        const = 0;  ///< Get register region of the destination operand
    virtual GtAddrMode      DstAddrMode()       const = 0;  ///< Get address mode of the destination operand

    //----------------------------------------------------------------------------------------------------
    // Source operand accessors
    //----------------------------------------------------------------------------------------------------
    virtual uint32_t        NumSources()                   const   = 0; ///< Get number of source operands
    virtual GtRegFileType   SrcRegFile(uint32_t srcNum)    const   = 0; ///< Get register file of the specified source operand
                                                                        ///< @pre srcNum < NumSources()
    virtual GtRegRegion     SrcRegOperand(uint32_t srcNum) const   = 0; ///< Get register region of the specified source operand
                                                                        ///< @pre SrcRegFile(srcNum).IsReg()
    virtual GtImm           SrcImmOperand(uint32_t srcNum) const   = 0; ///< Get immediate value of the specified source operand
                                                                        ///< @pre SrcRegFile(srcNum).IsImm()
    virtual GtAddrMode      SrcAddrMode(uint32_t srcNum)   const   = 0; ///< Get address mode of the specified source operand
                                                                        ///< @pre srcNum < NumSources()
    virtual GtSrcModifier   SrcModifier(uint32_t srcNum)   const   = 0; ///< Get modifier of the specified source operand
                                                                        ///< @pre srcNum < NumSources()
    //----------------------------------------------------------------------------------------------------
    // SendMessage operand accessors
    //----------------------------------------------------------------------------------------------------
    virtual GtSfid              Sfid()                        const = 0; ///< Get SFID of the SendMessage instruction
    virtual GtRegFileType       MsgDescRegFile()              const = 0; ///< Get register file of the SendMessage descriptor
    virtual GtRegFileType       ExMsgDescRegFile()            const = 0; ///< Get register file of the SendMessage extended descriptor
    virtual uint32_t            MsgDesc()                     const = 0; ///< Get the SendMessage descriptor immediate
                                                                         ///< @pre MsgDescRegFile().IsImm()
    virtual uint32_t            ExMsgDesc()                   const = 0; ///< Get the SendMessage extended descriptor immediate
                                                                         ///< @pre ExMsgDescRegFile().IsImm()
    virtual GtReg               MsgDescReg()                  const = 0; ///< Get the SendMessage descriptor register
                                                                         ///< @pre MsgDescRegFile().IsReg()
    virtual GtReg               ExMsgDescReg()                const = 0; ///< Get the SendMessage extended descriptor register
                                                                         ///< @pre ExMsgDescRegFile().IsReg()
    virtual Uint32Validatable<> MsgResponseLength()           const = 0; ///< Get the SendMessage response length, in registers
    virtual Uint32Validatable<> MsgSrcLength(uint32_t srcNum) const = 0; ///< Get length of the specified SendMessage source, in registers
                                                                         ///< @pre srcNum < NumSources()
    virtual uint32_t            NumAccesses()                 const = 0; ///< Get Number of elements in the address payload
    virtual uint32_t            DataSize()                    const = 0; ///< Get Size, in bytes, of the memory range referenced by a single address.
    virtual bool                IsBlock2DAccess()             const = 0; ///< True if the memory operation is block2d access
    virtual GtMemoryAddrModel   MemAddrModel()                const = 0; ///< Get Address Model of the memory surface access
    virtual GED_DP_OPCODE       DPOpCode()                    const = 0; ///< Get the data port (DP) opcode from the message descriptor;
    //----------------------------------------------------------------------------------------------------
    // Operation analysis methods
    //----------------------------------------------------------------------------------------------------
    virtual bool    IsIllegal()         const = 0; ///< Return true for an ILLEGAL instruction
    virtual bool    IsNop()             const = 0; ///< Return true for a NOP instruction
    virtual bool    IsSync()            const = 0; ///< Return true for a SYNC instruction
    virtual bool    IsFlowControl()     const = 0; ///< Return true for a flow control (branch) instruction
    virtual bool    IsChangingIP()      const = 0; ///< Return true for a branch, or an instruction that explicitly sets IP 
    virtual bool    IsSendMessage()     const = 0; ///< Return true for a SEND(S) instruction
    virtual bool    IsEot()             const = 0; ///< Return true for a SEND EOT instruction
    virtual bool    IsMemAccess()       const = 0; ///< Return true for an instruction that accesses memory
    virtual bool    IsMemRead()         const = 0; ///< Return true for an instruction that reads memory
    virtual bool    IsMemWrite()        const = 0; ///< Return true for an instruction that writes memory
    virtual bool    IsAtomic()          const = 0; ///< Return true for an instruction that accesses memory atomically
    virtual bool    IsPredicated()      const = 0; ///< Return true for a predicated instruction
    virtual bool    IsFlagModifier()    const = 0; ///< Return true, if instruction modifies flag register
    virtual bool    IsAccModifier()     const = 0; ///< Return true, if instruction modifies acc register

    //----------------------------------------------------------------------------------------------------
    // Basic instruction mutators
    //----------------------------------------------------------------------------------------------------
    virtual IGtIns& SetPredicate(const GtPredicate& predicate)  = 0; ///< Assign the specified predicate to the instruction
    virtual IGtIns& SetExecMask(GtExecMask execMask)            = 0; ///< Assign the specified execution mask to the instruction
    virtual IGtIns& SetWriteMaskCtrl(bool enable)               = 0; ///< Enable/disable the WrEn mask in the instruction
    virtual IGtIns& SetAccWriteCtrl(bool enable)                = 0; ///< Enable/disable the WrAcc mask in the instruction
    virtual IGtIns& SetBreakpoint(bool on)                      = 0; ///< Set the breakpoint at the instruction
    virtual IGtIns& SetThreadCtrl(GtThreadCtrl threadCtrl)      = 0; ///< Assign the specified thread control to the instruction
    virtual IGtIns& SetCondModifier(GtCondModifier condMod)     = 0; ///< Assign the specified conditional modifier to the instruction
    virtual IGtIns& SetCondFlagReg(const GtReg& flagReg)        = 0; ///< Assign the conditional flag to the instruction
                                                                     ///< @pre flagReg.IsFlagReg()
    //----------------------------------------------------------------------------------------------------
    // Operand setterts
    //----------------------------------------------------------------------------------------------------
    virtual IGtIns& SetDstOperand(const GtDstRegion& dstRegion)                     = 0; ///< Set the specified destination operand
    virtual IGtIns& SetSrcRegOperand(uint32_t srcNum, const GtRegRegion& regRegion) = 0; ///< Set the specified source register operand
                                                                                         ///< @pre srcNum < NumSources()
    virtual IGtIns& SetSrcImmOperand(uint32_t srcNum, GtImm imm)                    = 0; ///< Set the specified source immediate operand
                                                                                         ///< @pre srcNum < NumSources()
    virtual IGtIns& SetSrcModifier(uint32_t srcNum, GtSrcModifier modifier)         = 0; ///< Set the specified source modifier
                                                                                         ///< @pre srcNum < NumSources()
    //----------------------------------------------------------------------------------------------------
    // SendMessage operand setters
    //----------------------------------------------------------------------------------------------------
    virtual IGtIns& SetMsgDesc(uint32_t msgDesc)     = 0; ///< Set the specified SendMessage descriptor
    virtual IGtIns& SetExMsgDesc(uint32_t exMsgDesc) = 0; ///< Set the specified SendMessage extended descriptor
    virtual IGtIns& SetEot(bool isEot)               = 0; ///< Set the EOT attribute in this SendMessage instruction. @pre IsSendMessage()
    virtual IGtIns& SetSfid(GtSfid sfid)             = 0; ///< Set the specified SFID in this SendMessage instruction. @pre IsSendMessage()

    /// Attach the specified annotation to this instruction
    virtual IGtIns& AppendAnnotation(const char* annotation) = 0;

    /*!
     * Get the assembly text of this instruction
     * @param[in]   withAnnotations     Indicates whether the instruction's annotations are included (true) or not (false)
     * @return String with the assembly text of this instruction
     */
    virtual GtCoreString ToString(bool withAnnotations = true) const = 0;

protected:
    /// @internal Protected destructor
    virtual ~IGtIns() = default;
};
GTPIN_ASSERT_PURE_ABSTRACT(IGtIns);

#pragma pack(pop)
}
#endif

