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

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

/*!
 * @file A tool that profiles accessed cachelines
 */

#ifndef CACHELINEPROF_H_
#define CACHELINEPROF_H_

#include "hlif_basic_defs.h"
#include "block_2d.h"

#if defined(__cplusplus)
#include "gtpin_api.h"
using namespace gtpin;
#endif

#define MAX_SUPPORTED_CACHE_LINE_HISTOGRAM_SIZE 256

#pragma pack(push, 8)

/* ============================================================================================= */
// Struct CachelineProfArgs
/* ============================================================================================= */
/// Common arguments of HLI functions for computing cacheline accesses histogram
typedef struct CachelineProfArgs
{
    struct
    {
        uint32_t    numAccesses;       ///< Number of elements accessed by the instruction
        uint32_t    dataSize;          ///< Size, in bytes, of the memory element
        uint32_t    log2CachelineSize; ///< Log2(Cache-line-size)
    } in;
    struct
    {
        uint32_t    cachelineHistogram[MAX_SUPPORTED_CACHE_LINE_HISTOGRAM_SIZE]; ///< Histogram of the number of cachelines accessed by instruction
        uint32_t    outOfHistogramValues;
    } out;

    #if defined(__cplusplus)
    /// Constructor
    CachelineProfArgs() : in({0, 0, 0}), out({}) {}
    #endif
} CachelineProfArgs;

/// Common arguments of HLI functions for computing memory footprint
typedef struct MemoryFootprintArgs
{
    struct
    {
        uint32_t    log2CachelineSize;     ///< Log2(Cache-line-size)
        uint32_t    supportedAddressBits;  ///< Number of supported least significant bits of the addresses
        uint32_t    bitVectorSizeInBytes;  ///< The size of the bitvector in bytes
    } in;
    struct
    {
        uint64_t    upperAddressBits;
    } out;
} MemoryFootprintArgs;

typedef struct MemoryFootprintArgsCombo
{
    __global uint64_t*            addresses;
    uint32_t                      accessMask;
    uint32_t                      padding1;  // padding to 8 bytes
    uint32_t                      dataSize;
    uint32_t                      padding2;  // padding to 8 bytes
    uint32_t                      accessType;
    uint32_t                      padding3;  // padding to 8 bytes
    __global MemoryFootprintArgs* memoryFootprintArgs;
    __global uint8_t*             bitvector;
} MemoryFootprintArgsCombo;

/// Common arguments of HLI functions for cache modeling mode
typedef struct MemoryCacheModelArgs
{
    struct
    {
        uint32_t    log2CachelineSize;     ///< Log2(Cache-line-size)
        uint32_t    cacheSize;             ///< Cache size (assumed a power of 2)
        uint32_t    hashMaskShift;         ///< Number of bits to shift-left the hashMask before applying
    } in;
    struct
    {
        uint64_t    hits;
        uint64_t    misses;
    } out;
} MemoryCacheModelArgs;

enum MemoryAccessType
{
    Load,
    Store,
    ReadModifyWrite
};

typedef struct MemoryCacheModelArgsCombo
{
    __global uint64_t*             addresses;
    uint32_t                       accessMask;
    uint32_t                       padding1;  // padding to 8 bytes
    uint32_t                       dataSize;
    uint32_t                       padding2;  // padding to 8 bytes
    __global MemoryCacheModelArgs* memoryCacheModelArgs;
    __global uint64_t*             cacheTagsVector;
} MemoryCacheModelArgsCombo;

/// Common arguments of HLI functions for memory access analysis mode
typedef struct MemoryAccessAnalysisArgs
{
    struct
    {
        uint32_t         log2CachelineSize;    ///< Log2(Cache-line-size)
        uint32_t         supportedAddressBits; ///< Number of supported least significant bits of the addresses
        uint32_t         bitVectorSizeInBytes; ///< The size of the bitvector in bytes
    } in;
    struct
    {
        uint64_t         rarCount;
        uint64_t         rawCount;
        uint64_t         warCount;
        uint64_t         wawCount;
    } out;
} MemoryAccessAnalysisArgs;

typedef struct MemoryAccessAnalysisArgsCombo
{
    __global uint64_t*                 addresses;
    uint32_t                           accessMask;
    uint32_t                           padding1;  // padding to 8 bytes
    uint32_t                           dataSize;
    uint32_t                           padding2;  // padding to 8 bytes
    uint32_t                           accessType;
    uint32_t                           padding3;  // padding to 8 bytes
    __global MemoryAccessAnalysisArgs* memoryAccessAnalysisArgs;
    __global uint32_t*                 bitvector;
} MemoryAccessAnalysisArgsCombo;

/// Common arguments of HLI functions for memory race condition detection
typedef struct MemoryRaceDetectionArgs
{
    struct
    {
        uint32_t         log2CachelineSize;    ///< Log2(Cache-line-size)
        uint32_t         supportedAddressBits; ///< Number of supported least significant bits of the addresses
        uint32_t         bitVectorSizeInBytes; ///< The size of the bitvector in bytes
    } in;
    struct
    {
        uint64_t         upperAddressBits;
        uint64_t         raceCount;
        uint64_t         rarCount;
        uint64_t         rawCount;
        uint64_t         warCount;
        uint64_t         wawCount;
    } out;
} MemoryRaceDetectionArgs;

typedef struct MemoryRaceDetectionArgsCombo
{
    __global uint64_t*                         addresses;
    uint32_t                                   accessMask;
    uint32_t                                   padding1;  // padding to 8 bytes
    uint32_t                                   dataSize;
    uint32_t                                   padding2;  // padding to 8 bytes
    uint32_t                                   accessType;
    uint32_t                                   padding3;  // padding to 8 bytes
    uint32_t                                   hwThreadId;
    uint32_t                                   padding4;  // padding to 8 bytes
    __global MemoryRaceDetectionArgs*          memoryRaceDetectionArgs;
    __global uint32_t*                         raceDataVector;
    __global uint32_t*                         bitvector;
} MemoryRaceDetectionArgsCombo;

/*!
 * @brief HLI function that detects amount of cachelines accessed by a scatter SEND instruction to global or local memory done in A32 or BTS modes
 * @param[in]       addresses           Array of 32-bit addresses/offsets
 * @param[in]       accessMask          Per-channel mask of memory accesses
 * @param[in][out]  CachelineProfArgs   Information about memory access instruction and the resulting cachelines histogram
 */
IGC_STACK_CALL void CheckScatterA32Access(__global const uint32_t* addresses,
                                          uint32_t accessMask,
                                          __global CachelineProfArgs* CachelineProfArgs);

#if defined(__cplusplus)
    using CheckScatterA32AccessFunc = GtHliFunction<void, const uint32_t*, uint32_t, CachelineProfArgs*>;
#endif

/*!
 * @brief HLI function that detects amount of cachelines accessed by a scatter SEND instruction to global memory done in A64 mode
 * @param[in]       addresses           Array of 64-bit addresses
 * @param[in]       accessMask          Per-channel mask of memory accesses
 * @param[in][out]  CachelineProfArgs   Information about memory access instruction and the resulting cachelines histogram
 */
IGC_STACK_CALL void CheckScatterA64Access(__global const uint64_t* addresses,
                                          uint32_t accessMask,
                                          __global CachelineProfArgs* CachelineProfArgs);

#if defined(__cplusplus)
    using CheckScatterA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, CachelineProfArgs*>;
#endif

/*!
 * @brief HLI function sets bits within a bitvector that correspond to accessed cachelines
 * @param[in]       addresses            Array of 64-bit addresses
 * @param[in]       accessMask           Per-channel mask of memory accesses
 * @param[in]       dataSize             Data size per single access
 * @param[in,out]   memoryFootprintArgs  Information about memory access
 * @param[out]      bitvector            Resulting per-cacheline bitvector
 */
IGC_STACK_CALL void GlobalMemoryFootprintA64Access(__global MemoryFootprintArgsCombo* memoryFootprintArgsCombo);

#if defined(__cplusplus)
    using GlobalMemoryFootprintA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, MemoryFootprintArgs*, uint8_t*>;
#endif

/*!
 * @brief HLI function sets bits within a bitvector that correspond to accessed cachelines for Block2D accesses
 * @param[in]       addresses            Array of 64-bit addresses
 * @param[in]       accessMask           Per-channel mask of memory accesses
 * @param[in]       dataSize             Data size per single access
 * @param[in,out]   memoryFootprintArgs  Information about memory access
 * @param[out]      bitvector            Resulting per-cacheline bitvector
 */
IGC_STACK_CALL void GlobalMemoryFootprintBlock2DAccess(__global MemoryFootprintArgsCombo* memoryFootprintArgsCombo);

#if defined(__cplusplus)
    using GlobalMemoryFootprintBlock2DAccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, MemoryFootprintArgs*, uint8_t*>;
#endif


/*!
 * @brief HLI function that models cache and reports the number of hits and misses
 * @param[in]       addresses            Array of 64-bit addresses
 * @param[in]       accessMask           Per-channel mask of memory accesses
 * @param[in]       dataSize             Data size per single access
 * @param[in,out]   MemoryCacheModelArgs Information about cache model
 * @param[in]       cacheTagsVector      Vector of cache buckets tags
 */
IGC_STACK_CALL void GlobalMemoryCacheModelA64Access(__global MemoryCacheModelArgsCombo* memoryCacheModelArgsCombo);

#if defined(__cplusplus)
    using GlobalMemoryCacheModelA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, MemoryCacheModelArgs*, uint64_t*>;
#endif


/*!
 * @brief HLI function that models cache and reports the number of hits and misses
 * @param[in]       addresses            Array of 64-bit addresses
 * @param[in]       accessMask           Per-channel mask of memory accesses
 * @param[in]       dataSize             Data size per single access
 * @param[in,out]   MemoryCacheModelArgs Information about cache model
 * @param[in]       cacheTagsVector      Vector of cache buckets tags
 */
IGC_STACK_CALL void GlobalMemoryCacheModelBlock2DAccess(__global MemoryCacheModelArgsCombo* memoryCacheModelArgsCombo);

#if defined(__cplusplus)
    using GlobalMemoryCacheModelBlock2DAccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, MemoryCacheModelArgs*, uint64_t*>;
#endif

/*!
 * @brief HLI function checks type of access (RaR, WaR, WaW, RaW) for A64 access
 * @param[in]       addresses                      Array of 64-bit addresses
 * @param[in]       accessMask                     Per-channel mask of memory accesses
 * @param[in]       dataSize                       Data size per single access
 * @param[in]       accessType                     Type of access
 * @param[in,out]   memoryAccessAnalysisArgsCombo  Information about memory access
 * @param[out]      bitvector                      Resulting per-cacheline bitvector
 */
IGC_STACK_CALL void GlobalMemoryAccessAnalysisA64Access(__global MemoryAccessAnalysisArgsCombo* memoryAccessAnalysisArgsCombo);

#if defined(__cplusplus)
using GlobalMemoryAccessAnalysisA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, MemoryAccessAnalysisArgs*, uint32_t*>;
#endif

/*!
 * @brief HLI function checks type of access (RaR, WaR, WaW, RaW) for load_block2d/store_block2d messages
 * @param[in]       addresses                Array of 64-bit addresses
 * @param[in]       accessMask               Per-channel mask of memory accesses
 * @param[in]       dataSize                 Data size
 * @param[in]       accessType               Type of access
 * @param[in,out]   memoryAccessAnalysisArgs Information about memory access
 * @param[out]      bitvector                Resulting per-cacheline bitvector
 */
IGC_STACK_CALL void GlobalMemoryAccessAnalysisBlock2DAccess(__global MemoryAccessAnalysisArgsCombo* memoryAccessAnalysisArgsCombo);

#if defined(__cplusplus)
using GlobalMemoryAccessAnalysisBlock2DAccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, MemoryAccessAnalysisArgs*, uint8_t*>;
#endif

/*!
 * @brief HLI function checks for WaW accesses from different HW threads for A64 access
 * @param[in]       addresses                              Array of 64-bit addresses
 * @param[in]       accessMask                             Per-channel mask of memory accesses
 * @param[in]       dataSize                               Data size per single access
 * @param[in]       accessType                             Type of access
 * @param[in,out]   MemoryRaceDetectionArgsCombo           Information about memory access
 * @param[in]       hwThreadDataVector                     Resulting data structure
 * @param[out]      bitvector                              Resulting per-cacheline bitvector
 */
IGC_STACK_CALL void GlobalMemoryRaceDetectionA64Access(__global MemoryRaceDetectionArgsCombo* memoryRaceDetectionArgsCombo);

#if defined(__cplusplus)
using GlobalMemoryRaceDetectionA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, uint32_t, MemoryRaceDetectionArgs*, uint32_t*, uint32_t*>;
#endif

IGC_STACK_CALL void GlobalMemoryAccessAnalysisAndRaceDetectionA64Access(__global MemoryRaceDetectionArgsCombo* memoryRaceDetectionArgsCombo);

#if defined(__cplusplus)
using GlobalMemoryAccessAnalysisAndRaceDetectionA64AccessFunc = GtHliFunction<void, const uint64_t*, uint32_t, uint32_t, uint32_t, uint32_t, MemoryRaceDetectionArgs*, uint32_t*, uint32_t*>;
#endif

#pragma pack(pop)

#endif // CACHELINEPROF_H_
