// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : ucp_utility.h
// Author        : xianfeng.du
// Created On    : 2022-06-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------


#ifndef __UCP_UTILITY_H__
#define __UCP_UTILITY_H__

#include <string.h>
#include "typedef.h"
#include "ucps2-intrin.h"
#include "mem_sections.h"
#include "spinlock.h"

#define do_write(a,v)       __ucps2_store_ext_mem((void *)(a), (uint32_t)(v), f_W)
#define do_write_byte(a,v)  __ucps2_store_ext_mem((void *)(a), (uint8_t)(v), f_B)
#define do_write_short(a,v) __ucps2_store_ext_mem((void *)(a), (uint16_t)(v), f_S)

#define do_read(a)          __ucps2_load_ext_mem((void *)(a), f_W)
#define do_read_byte(a)     __ucps2_load_ext_mem((void *)(a), f_B)
#define do_read_short(a)    __ucps2_load_ext_mem((void *)(a), f_S)

#define do_read_volatile(a)         __ucps2_load_ext_mem_v((void *)(a), f_W)
#define do_read_volatile_byte(a)    __ucps2_load_ext_mem_v((void *)(a), f_B)
#define do_read_volatile_short(a)   __ucps2_load_ext_mem_v((void *)(a), f_S)

#define memcpy_ucp(d,s,l)   memcpy_ext((void *__restrict)(d), (const void *__restrict)(s), (l))
#define memset_ucp(d,v,l)   memset_ext((void *)(d), (uint32_t)(v), (l))

//vector copy,sm address must align 64 bytes
#define memcpy_ucp_dm2sm(d,s,l) vmemcpy_dm2sm((void *__restrict)(d), (const void *__restrict)(s), (l))
#define memcpy_ucp_sm2dm(d,s,l) vmemcpy_sm2dm((void *__restrict)(d), (const void *__restrict)(s), (l))

#define sizeof_aligned_4bytes(a)	(((sizeof(a) + 3) >> 2) << 2)//aligned 4 bytes
#define sizeof_aligned_64bytes(a)	(((sizeof(a) + 63) >> 6) << 6)

#define spin_lock_init(x) smart_spinlock_init(x)
#define spin_lock(x) smart_spinlock_irq(x)//smart_spinlock(x)
#define spin_unlock(x) smart_spinunlock_irqrestore(x)//smart_spinunlock(x)

typedef enum eUcpSpinlockType {
    LOCK_UL_TX_ALLOC = 1,
    LOCK_UL_TX_PUT,
    LOCK_DL_RX_GET,
    LOCK_DL_RX_FREE,
    LOCK_BUILD_CELL,
} UcpSpinlockType_e;

typedef enum eDdrSpinlockType {
    LOCK_DDR_STC_CTW = 0,
    LOCK_DDR_CTC,
    LOCK_DDR_BUILD_CELL,
} DdrSpinlockType_e;


ALWAYS_INLINE int32_t get_core_id();
int32_t isPowerOf2(uint32_t n);
void ucp_spinlock_init();
void ucp_nop(uint32_t cycleCnt);

#define DBG_DDR_PALLADIUM
#define DBG_DDR_ADDR_BASE       (0xB7E00000) //0xA8000000
#define DBG_DDR_IDX_COMMON_BASE (0)
#define DBG_DDR_IDX_OSP_BASE    (2048*1)
#define DBG_DDR_IDX_MSG_BASE    (2048*2)
#define DBG_DDR_IDX_DRV_BASE    (2048*3)
#define DBG_DDR_IDX_OSP2_BASE   (2048*11)       // 0xB7E16000
#define DBG_DDR_IDX_ERR_BASE    (2048*18)
#define DBG_DDR_IDX_CPRI_BASE   (2048*20)
#define DBG_DDR_IDX_ECPRI_BASE  (2048*24)       // 0xB7E30000
#define DBG_DDR_IRQ_ADDR_BASE   (0xB7FC0000)
#define DBG_DDR_IRQ_LEN         (0x1000)
#define DBG_DDR_OS_ADDR_BASE    (0xB7FCD000)
#define DBG_DDR_OS_LEN          (0x100)         //(0x400)
#define DBG_DDR_OS_NO_IDLE_BASE (0xB7FCD800)
#define DBG_DDR_OS_NO_IDLE_LEN  (0x100)

#define DBG_DDR_HW_ADDR_BASE    (0xB7FD0400)
#define DBG_DDR_HW_LEN          (0x200)
#define DBG_DDR_SPIN_ADDR_BASE  (0xB7FD1400)
#define DBG_DDR_SPIN_LEN        (0x80)
#define DBG_DDR_OSP_HW_BASE     (476544)        // 0xB7FD1600
#define DBG_DDR_OSP_HW_LEN      (0x30)          // 48

#define DBG_DDR_COMMON_IDX(core_id,x) (DBG_DDR_IDX_COMMON_BASE + (core_id) * 128 + (x))
#define DBG_DDR_MSG_IDX(queue_no,x)   (DBG_DDR_IDX_MSG_BASE + (queue_no) * 192 + (x))
#define DBG_DDR_ERR_IDX(core_id,x)    (DBG_DDR_IDX_ERR_BASE + (core_id)*128 + (x))
#define DBG_DDR_ECPRI_IDX(ecs_id, x)     (DBG_DDR_IDX_ECPRI_BASE + (ecs_id) * 1024 + (x))
#define OSP_DEBUG_HW_POT(core_id, idx)   (DBG_DDR_OSP_HW_BASE + ((core_id)*DBG_DDR_OSP_HW_LEN) + idx)

#define UCP_OSP_DBG_HW_CNT_ENABLE

#ifdef DBG_DDR_PALLADIUM
void pld_debug_write(uint32_t idx, uint32_t value);
void pld_debug_write_splice_short(uint32_t idx, uint16_t hi, uint16_t lo);
void pld_debug_write_splice_byte(uint32_t idx, uint8_t hi0, uint8_t hi1, uint8_t lo0, uint8_t lo1);
#define debug_write(a, b)                       pld_debug_write((uint32_t)(a), (uint32_t)(b))
#define debug_write_splice_short(a, b, c)       pld_debug_write_splice_short((a), (b), (c))
#define debug_write_splice_byte(a, b, c, d, e)  pld_debug_write_splice_byte((a), (b), (c), (d), (e))
#else
#define debug_write(a, b)
#define debug_write_splice_short(a, b, c)
#define debug_write_splice_byte(a, b, c, d, e)
#endif

//#define ATOMIC_IMPLEMENTATION
#define atomic_load(object) __ucps2_atomicld((void *)object, f_W)
#define atomic_store(object, operand) __ucps2_atomicst((void *)object, operand, f_W)
ALWAYS_INLINE int32_t atomic_fetch_add(void* object, int32_t operand);

#endif

