/*  ****************************************************************************
 *  File: astris_awl.h
 *
 *  Astris AWL Target Header
 *
 ****************************************************************************
 *
 *  Copyright (C) 2021 - 2022
 *
 *  This document is the property of Apple Inc.
 *  It is considered confidential and proprietary.
 *
 *  This document may not be reproduced or transmitted in any form,
 *  in whole or in part, without the express written permission of
 *  Apple Inc.
 ************************************************************************* */

#ifndef astris_awl_target_h
#define astris_awl_target_h

#include <map>
#include <string>

#include "astris_api.h"
#include "bitfields.h"

class AWLTarget_t {
public:
    AWLTarget_t(uint32_t tgt_num, std::string tgt_name, uint32_t die_id = 0);
    virtual ~AWLTarget_t();

    typedef enum {
        PMS,
        ACC
    } AWLTgtType_t;

    virtual uint32_t     get_tgt_num();
    virtual uint32_t     get_die_id();
    virtual std::string  get_tgt_name();
    virtual AWLTgtType_t get_tgt_type() = 0;

    virtual bool equal(AXawl_tgt_info_t *tgt);

protected:
    uint32_t m_tgt_num;
    std::string m_tgt_name;
    uint32_t m_die_id;

};

class AWLTargetACC_t:
    public AWLTarget_t {

public:
    typedef enum {
        PWR_STS,
        DVFM,
        PRB_DSB,
    } AWLACCCmd_t;

    AWLTargetACC_t(uint32_t tgt_num, std::string tgt_name, uint32_t die_id = 0);
    ~AWLTargetACC_t();

    AWLTgtType_t get_tgt_type() override;
    virtual int  create_acc_power_status_cmd(uint32_t * &encoded_msg, uint8_t &len);
    virtual int  create_acc_dvfm_cmd(uint32_t * &encoded_msg, uint8_t &len);
    virtual int  create_acc_prb_dsb_cmd(uint32_t array_index, uint32_t * &encoded_msg, uint8_t &len);

    virtual int create_acc_reg_cmd(uint32_t core, AXawl_cpu_reg_t reg_name, uint32_t * &encoded_msg, uint8_t &len);

protected:

    std::map <AWLACCCmd_t, uint32_t> m_cmd_map;
    std::map <AXawl_cpu_reg_t, uint32_t> m_reg_cmd_map;

    int create_cmd_helper(AWLACCCmd_t cmd_name, uint32_t * &encoded_msg, uint8_t &len);
    int create_reg_cmd_helper(uint32_t core, AXawl_cpu_reg_t cmd_name, uint32_t * &encoded_msg, uint8_t &len);

    static constexpr uint32_t S_ACC_CMD = 0;
    static constexpr uint32_t M_ACC_CMD = _MM_MAKEMASK(8, S_ACC_CMD);

    static constexpr uint32_t S_ACC_CORE_SELECT = 8;
    static constexpr uint32_t M_ACC_CORE_SELECT = _MM_MAKEMASK(8, S_ACC_CORE_SELECT);

    const uint8_t m_acc_msg_size = 3;

};

class AWLTargetACCv2_t:
    public AWLTargetACC_t {

public:
    AWLTargetACCv2_t(uint32_t tgt_num, std::string tgt_name, uint32_t die_id = 0);
    ~AWLTargetACCv2_t();

};

class AWLTargetASCv1_t:
    public AWLTargetACC_t {

public:
    AWLTargetASCv1_t(uint32_t tgt_num, std::string tgt_name, uint32_t die_id = 0);
    ~AWLTargetASCv1_t();

};

class AWLTargetPMS_t:
    public AWLTarget_t {

public:
    AWLTargetPMS_t(uint32_t tgt_num, std::string tgt_name, uint32_t die_id = 0);
    ~AWLTargetPMS_t();

    AWLTgtType_t get_tgt_type() override;

    void        set_addr_width(uint32_t addr_width);
    virtual int create_pms_read_cmd(AXmemaddr_t addr, uint32_t * &encoded_msg, uint8_t &len);

protected:
    uint32_t m_addr_width;
    const uint8_t m_pms_msg_size = 3;
};

#endif /* astris_awl_target_h */
