//==============================================================================
// TLP Package - Common Types and Constants for PCILeech TLP Processing
// Generated by PCILeech Firmware Generator
//
// This package contains all common type definitions, constants, and utility
// functions used across the PCILeech TLP processing modules.
//==============================================================================

`ifndef TLP_PKG_SVH
`define TLP_PKG_SVH

package tlp_pkg;

    // ========================================================================
    // TLP Type Definitions
    // ========================================================================
    
    // TLP Format and Type Encoding (PCIe Base Spec)
    typedef enum logic [4:0] {
        TLP_MEM_READ_32     = 5'b00000,
        TLP_MEM_READ_64     = 5'b00001,
        TLP_MEM_WRITE_32    = 5'b01000,
        TLP_MEM_WRITE_64    = 5'b01001,
        TLP_COMPLETION      = 5'b01010,
        TLP_COMPLETION_DATA = 5'b01011,
        TLP_CONFIG_READ_0   = 5'b00100,
        TLP_CONFIG_WRITE_0  = 5'b00101,
        TLP_CONFIG_READ_1   = 5'b00110,
        TLP_CONFIG_WRITE_1  = 5'b00111,
        TLP_MSG_TO_ROOT     = 5'b10000,
        TLP_MSG_BY_ADDR     = 5'b10001,
        TLP_MSG_FROM_ROOT   = 5'b10010,
        TLP_MSG_LOCAL       = 5'b10011,
        TLP_MSG_GATHER      = 5'b10100,
        TLP_INVALID         = 5'b11111
    } tlp_type_t;

    // TLP Header Structure (128-bit aligned)
    typedef struct packed {
        logic [4:0]  fmt_type;      // Format and Type
        logic [2:0]  tc;            // Traffic Class
        logic        td;            // TLP Digest Present
        logic        ep;            // Poisoned TLP
        logic [1:0]  attr;          // Attributes
        logic        th;            // TLP Hints
        logic [9:0]  length;        // Length in DW
        logic [15:0] requester_id;  // Requester ID
        logic [7:0]  tag;           // Tag
        logic [3:0]  first_be;      // First DW Byte Enables
        logic [3:0]  last_be;       // Last DW Byte Enables
        logic [31:0] address_low;   // Address[31:0] or Data[31:0]
        logic [31:0] address_high;  // Address[63:32] (64-bit only)
    } tlp_header_t;

    // Completion Header Structure
    typedef struct packed {
        logic [4:0]  fmt_type;      // Format and Type
        logic [2:0]  tc;            // Traffic Class
        logic        td;            // TLP Digest Present
        logic        ep;            // Poisoned TLP
        logic [1:0]  attr;          // Attributes
        logic        th;            // TLP Hints
        logic [9:0]  length;        // Length in DW
        logic [15:0] completer_id;  // Completer ID
        logic [2:0]  completion_status; // Completion Status
        logic        bcm;           // Byte Count Modified
        logic [11:0] byte_count;    // Byte Count
        logic [15:0] requester_id;  // Original Requester ID
        logic [7:0]  tag;           // Original Tag
        logic [6:0]  lower_addr;    // Lower Address
        logic        reserved;      // Reserved bit
    } tlp_completion_header_t;

    // TLP Interface Structure
    typedef struct packed {
        logic        valid;
        logic [127:0] data;
        logic        sop;           // Start of Packet
        logic        eop;           // End of Packet
        logic [3:0]  empty;         // Empty bytes in last cycle
        logic        err;           // Error indication
    } tlp_stream_t;

    // ========================================================================
    // PCILeech Command Definitions
    // ========================================================================
    
    typedef enum logic [7:0] {
        PCILEECH_CMD_READ           = 8'h01,
        PCILEECH_CMD_WRITE          = 8'h02,
        PCILEECH_CMD_PROBE          = 8'h03,
        PCILEECH_CMD_WRITE_SCATTER  = 8'h04,
        PCILEECH_CMD_READ_SCATTER   = 8'h05,
        PCILEECH_CMD_EXEC           = 8'h06,
        PCILEECH_CMD_STATUS         = 8'h07,
        PCILEECH_CMD_IDENTIFY       = 8'h08,
        PCILEECH_CMD_CONFIG_READ    = 8'h09,
        PCILEECH_CMD_CONFIG_WRITE   = 8'h0A,
        PCILEECH_CMD_INVALID        = 8'hFF
    } pcileech_cmd_t;

    // PCILeech Status Codes
    typedef enum logic [7:0] {
        PCILEECH_STATUS_SUCCESS     = 8'h00,
        PCILEECH_STATUS_FAIL_GENERAL = 8'h01,
        PCILEECH_STATUS_FAIL_ADDR   = 8'h02,
        PCILEECH_STATUS_FAIL_TIMEOUT = 8'h03,
        PCILEECH_STATUS_FAIL_PERM   = 8'h04,
        PCILEECH_STATUS_BUSY        = 8'h80,
        PCILEECH_STATUS_READY       = 8'h81
    } pcileech_status_t;

    // ========================================================================
    // Memory Region Definitions
    // ========================================================================
    
    typedef enum logic [3:0] {
        REGION_DEVICE_CTRL,     // Device Control Region
        REGION_STATUS_REG,      // Status Registers
        REGION_DATA_BUFFER,     // Data Buffer
        REGION_CUSTOM_PIO,      // Custom PIO Region
        REGION_MSIX_TABLE,      // MSI-X Table
        REGION_MSIX_PBA,        // MSI-X PBA
        REGION_CONFIG_SHADOW,   // Configuration Space Shadow
        REGION_GENERAL_MEM,     // General Memory
        REGION_DMA_CTRL,        // DMA Control
        REGION_PERF_MON,        // Performance Monitor
        REGION_ERROR_LOG,       // Error Log
        REGION_INVALID          // Invalid/Unknown Region
    } region_select_t;

    // Region Configuration Structure
    typedef struct packed {
        logic [31:0] base_addr;
        logic [31:0] size;
        logic        read_enable;
        logic        write_enable;
        logic        dma_enable;
        logic [3:0]  access_width;  // 0=byte, 1=word, 2=dword, 3=qword
    } region_config_t;

    // ========================================================================
    // Controller State Definitions
    // ========================================================================
    
    typedef enum logic [3:0] {
        STATE_IDLE,
        STATE_TLP_DECODE,
        STATE_ADDRESS_DECODE,
        STATE_READ_PROCESS,
        STATE_WRITE_PROCESS,
        STATE_COMPLETION_GEN,
        STATE_DMA_READ,
        STATE_DMA_WRITE,
        STATE_ERROR_HANDLE,
        STATE_PCILEECH_EXEC,
        STATE_CONFIG_ACCESS,
        STATE_MSIX_PROCESS
    } controller_state_t;

    // ========================================================================
    // Error and Status Definitions
    // ========================================================================
    
    typedef struct packed {
        logic        address_error;
        logic        tlp_error;
        logic        timeout_error;
        logic        parity_error;
        logic        completion_error;
        logic        unsupported_request;
        logic        malformed_tlp;
        logic        dma_error;
        logic [7:0]  error_count;
        logic [15:0] reserved;
    } error_status_t;

    typedef struct packed {
        logic [31:0] read_count;
        logic [31:0] write_count;
        logic [31:0] completion_count;
        logic [31:0] error_count;
        logic [31:0] dma_read_bytes;
        logic [31:0] dma_write_bytes;
        logic [15:0] max_latency_cycles;
        logic [15:0] avg_latency_cycles;
    } performance_counters_t;

    // ========================================================================
    // Interface Definitions
    // ========================================================================
    
    // Ready/Valid Interface
    interface tlp_ready_valid_if;
        logic        ready;
        logic        valid;
        logic [127:0] data;
        logic        sop;
        logic        eop;
        logic [3:0]  empty;
        logic        err;
        
        modport source (
            input  ready,
            output valid, data, sop, eop, empty, err
        );
        
        modport sink (
            output ready,
            input  valid, data, sop, eop, empty, err
        );
    endinterface

    // BAR Access Interface
    interface bar_access_if;
        logic [31:0] addr;
        logic [31:0] wr_data;
        logic [3:0]  wr_be;
        logic        wr_en;
        logic        rd_en;
        logic [31:0] rd_data;
        logic        rd_valid;
        logic        access_error;
        
        modport controller (
            input  addr, wr_data, wr_be, wr_en, rd_en,
            output rd_data, rd_valid, access_error
        );
        
        modport client (
            output addr, wr_data, wr_be, wr_en, rd_en,
            input  rd_data, rd_valid, access_error
        );
    endinterface

    // ========================================================================
    // Utility Functions
    // ========================================================================
    
    // Calculate address alignment
    function automatic logic [1:0] get_address_alignment(logic [31:0] addr);
        return addr[1:0];
    endfunction

    // Check if TLP is memory request
    function automatic logic is_memory_request(tlp_type_t tlp_type);
        return (tlp_type == TLP_MEM_READ_32) || 
               (tlp_type == TLP_MEM_READ_64) ||
               (tlp_type == TLP_MEM_WRITE_32) || 
               (tlp_type == TLP_MEM_WRITE_64);
    endfunction

    // Check if TLP is read request
    function automatic logic is_read_request(tlp_type_t tlp_type);
        return (tlp_type == TLP_MEM_READ_32) || (tlp_type == TLP_MEM_READ_64);
    endfunction

    // Check if TLP is write request
    function automatic logic is_write_request(tlp_type_t tlp_type);
        return (tlp_type == TLP_MEM_WRITE_32) || (tlp_type == TLP_MEM_WRITE_64);
    endfunction

    // Check if TLP uses 64-bit addressing
    function automatic logic is_64bit_address(tlp_type_t tlp_type);
        return (tlp_type == TLP_MEM_READ_64) || (tlp_type == TLP_MEM_WRITE_64);
    endfunction

    // Calculate byte count from length and byte enables
    function automatic logic [11:0] calculate_byte_count(
        logic [9:0] length,
        logic [3:0] first_be,
        logic [3:0] last_be
    );
        logic [11:0] total_bytes;
        logic [3:0]  first_count, last_count;
        
        // Count enabled bytes in first and last DW
        first_count = first_be[0] + first_be[1] + first_be[2] + first_be[3];
        last_count = last_be[0] + last_be[1] + last_be[2] + last_be[3];
        
        if (length == 1) begin
            // Single DW - use first_be only
            total_bytes = first_count;
        end else begin
            // Multiple DW - first + middle + last
            total_bytes = first_count + ((length - 2) * 4) + last_count;
        end
        
        return total_bytes;
    endfunction

    // Generate completion header
    function automatic tlp_completion_header_t generate_completion_header(
        tlp_header_t req_header,
        logic [15:0] completer_id,
        logic [2:0]  completion_status,
        logic [11:0] byte_count
    );
        tlp_completion_header_t comp_header;
        
        comp_header.fmt_type = (byte_count > 0) ? TLP_COMPLETION_DATA : TLP_COMPLETION;
        comp_header.tc = req_header.tc;
        comp_header.td = 1'b0;
        comp_header.ep = 1'b0;
        comp_header.attr = req_header.attr;
        comp_header.th = 1'b0;
        comp_header.length = (byte_count + 3) >> 2; // Convert bytes to DW
        comp_header.completer_id = completer_id;
        comp_header.completion_status = completion_status;
        comp_header.bcm = 1'b0;
        comp_header.byte_count = byte_count;
        comp_header.requester_id = req_header.requester_id;
        comp_header.tag = req_header.tag;
        comp_header.lower_addr = req_header.address_low[6:0];
        comp_header.reserved = 1'b0;
        
        return comp_header;
    endfunction

    // ========================================================================
    // Constants
    // ========================================================================
    
    // Standard PCIe constants
    localparam int MAX_PAYLOAD_SIZE = 512;  // bytes
    localparam int MAX_READ_REQUEST = 512;  // bytes
    localparam int TLP_HEADER_SIZE = 16;    // bytes (128-bit)
    localparam int DW_SIZE = 4;             // bytes per DW
    
    // Timing constants
    localparam int DEFAULT_TIMEOUT_CYCLES = 1024;
    localparam int MIN_INTER_PACKET_GAP = 2;
    
    // Error injection patterns (for testing)
    localparam logic [15:0] ERROR_INJECT_ADDR = 16'hAAAA;
    localparam logic [15:0] ERROR_INJECT_TLP = 16'h5555;
    localparam logic [15:0] ERROR_INJECT_TIMEOUT = 16'hCCCC;

endpackage

`endif // TLP_PKG_SVH