/**
 * \file    arch.h
 * \brief   Architecture specific defs and inlines
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-12
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-12  Original Creation
 * 
 */
 
#ifndef __ARCH_H_
#define __ARCH_H_

#include <stdint.h>
#include <stdbool.h>
#include "csr.h"

/** Every project must configure its platform_config.h */
#include "platform_config.h"
 
/** Architecture endian: little endian */
#define __LITTLE_ENDIAN__                   (1)

#define SYSTEM_SLEEP_CLOCK_FREQ             4000000UL
#define SYSTEM_SLEEP_CLOCK_TICK             250UL

#ifndef SYSTEM_CLOCK_FREQ
#define SYSTEM_CLOCK_FREQ                   33000000UL
#endif
#ifndef SYSTEM_CLOCK_TICK
#define SYSTEM_CLOCK_TICK                   (3030303/100000)
#endif

/** BSP version definition */
#define BSP_MAJOR_VERSION                   (22)
#define BSP_MINOR_VERSION                   (10)


/** \brief Get Machine ISA Register
 *
 * \return Register value
 */
static inline unsigned long __attribute__((const)) arch_isa(void)
{
    unsigned long res;
    asm ("csrr %0, misa" : "=r"(res));
    return res;
}

/** \brief Get Machine Implementation ID Register
 *
 * \return Register value
 */
static inline unsigned long __attribute__((const)) arch_impid(void)
{
    unsigned long res;
    asm ("csrr %0, mimpid" : "=r"(res));
    return res;
}

/** \brief Get Hart ID Register
 *
 * \return Register value
 */
static inline unsigned long __attribute__((const)) arch_hartid(void)
{
    unsigned long res;
    asm ("csrr %0, mhartid" : "=r"(res));
    return res;
}

/** \brief Get Machine Trap Value (mtval) Register
 *
 * \return Register value
 */
static inline unsigned long __attribute__((const)) arch_badaddr(void)
{
    unsigned long res;
    asm ("csrr %0, 0x343" : "=r"(res));
    return res;
}

/** \brief Execute FENCE.I instruction
 *  The FENCE.I instruction is used to synchronize the instruction and 
 *  data streams
 */
static inline void ifence(void)
{
    asm volatile ("fence.i" ::: "memory");
}

/** \brief Execute FENCE instruction
 *  The FENCE instruction is used to order device I/O and memory accesses as 
 *  viewed by other RISC-V harts and external devices or coprocessors.
 */
static inline void fence(void)
{
    asm volatile ("fence" ::: "memory");
}

/** \brief Wait for interrupt
 *
 */
static inline void wfi(void)
{
    asm volatile ("wfi" ::: "memory");
}

/** \brief System halt request
 *
 */
void __attribute__((noreturn)) _hart_halt(void);

#endif /* #ifndef __ARCH_H_ */

