58class port_fnct : 
public tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>
 
   60    SCP_LOGGER((), 
"register");
 
   61    std::vector<std::shared_ptr<tlm_fnct>> m_pre_read_fncts;
 
   62    std::vector<std::shared_ptr<tlm_fnct>> m_pre_write_fncts;
 
   63    std::vector<std::shared_ptr<tlm_fnct>> m_post_read_fncts;
 
   64    std::vector<std::shared_ptr<tlm_fnct>> m_post_write_fncts;
 
   65    cci::cci_param<bool> p_is_callback;
 
   66    bool m_in_callback = 
false;
 
   68    std::function<
unsigned int(tlm::tlm_generic_payload&)> transport_dbg_func;
 
   72        std::string 
n(name());
 
   73        n = 
n.substr(0, 
n.length() - 
strlen(
"_target_socket")); 
 
   74        n = 
n.substr(
n.find_last_of(
".") + 1);                  
 
   79    unsigned int transport_dbg(tlm::tlm_generic_payload& 
txn)
 
   81        if (transport_dbg_func) {
 
   82            return transport_dbg_func(
txn);
 
   87    void b_transport(tlm::tlm_generic_payload& 
txn, sc_core::sc_time& delay)
 
   89        if (m_pre_read_fncts.size() || m_pre_write_fncts.size() || m_post_read_fncts.size() ||
 
   90            m_post_write_fncts.size()) {
 
   93                switch (
txn.get_response_status()) {
 
   94                case tlm::TLM_INCOMPLETE_RESPONSE:
 
   95                    switch (
txn.get_command()) {
 
   96                    case tlm::TLM_READ_COMMAND:
 
   97                        if (m_pre_read_fncts.size()) {
 
   98                            SCP_INFO(())(
"Pre-Read callbacks: {}", my_name());
 
   99                            for (
auto& 
cb : m_pre_read_fncts) (*
cb)(
txn, delay);
 
  102                    case tlm::TLM_WRITE_COMMAND:
 
  103                        if (m_pre_write_fncts.size()) {
 
  104                            SCP_INFO(())(
"Pre-Write callbacks: {}", my_name());
 
  105                            for (
auto& 
cb : m_pre_write_fncts) (*
cb)(
txn, delay);
 
  111                    capture_txn_pre(
txn);
 
  113                case tlm::TLM_OK_RESPONSE:
 
  114                    handle_mask_post(
txn);
 
  115                    switch (
txn.get_command()) {
 
  116                    case tlm::TLM_READ_COMMAND:
 
  117                        if (m_post_read_fncts.size()) {
 
  118                            SCP_INFO(())(
"Post-Read callbacks: {}", my_name());
 
  119                            for (
auto& 
cb : m_post_read_fncts) (*
cb)(
txn, delay);
 
  122                    case tlm::TLM_WRITE_COMMAND:
 
  123                        if (m_post_write_fncts.size()) {
 
  124                            SCP_INFO(())(
"Post-Write callbacks: {}", my_name());
 
  125                            for (
auto& 
cb : m_post_write_fncts) (*
cb)(
txn, delay);
 
  135                m_in_callback = 
false;
 
  138        txn.set_dmi_allowed(
false);
 
  149    void pre_read(tlm_fnct::TLMFUNC 
cb) { m_pre_read_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
 
  150    void pre_write(tlm_fnct::TLMFUNC 
cb) { m_pre_write_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
 
  151    void post_read(tlm_fnct::TLMFUNC 
cb) { m_post_read_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
 
  152    void post_write(tlm_fnct::TLMFUNC 
cb) { m_post_write_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
 
  153    virtual void capture_txn_pre(tlm::tlm_generic_payload& 
txn) = 0;
 
  154    virtual void handle_mask_post(tlm::tlm_generic_payload& 
txn) = 0;
 
  159        , p_is_callback(
path_name + 
".target_socket.is_callback", 
true, 
"Is a callback (true)")
 
  161        SCP_LOGGER_NAME().features[0] = parent(sc_core::sc_object::name()) + 
"." + name;
 
  163        p_is_callback = 
true;
 
  164        p_is_callback.lock();
 
  165        tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>::register_b_transport(
this,
 
  166                                                                                               &port_fnct::b_transport);
 
  167        tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>::register_transport_dbg(
 
  168            this, &port_fnct::transport_dbg);
 
  171    void register_transport_dbg_func(std::function<
unsigned int(tlm::tlm_generic_payload&)> 
fn)
 
  173        transport_dbg_func = 
fn;
 
  177    std::string parent(std::string name) { 
return name.substr(0, name.find_last_of(
'.')); }
 
 
  187    scp::scp_logger_cache& SCP_LOGGER_NAME();
 
  188    TYPE* m_dmi = 
nullptr;
 
  192        tlm::tlm_generic_payload m_txn;
 
  194        m_txn.set_byte_enable_length(0);
 
  195        m_txn.set_dmi_allowed(
false);
 
  196        m_txn.set_command(tlm::TLM_IGNORE_COMMAND);
 
  197        m_txn.set_data_ptr(
nullptr);
 
  198        m_txn.set_address(p_offset);
 
  199        m_txn.set_data_length(
sizeof(TYPE) * p_number);
 
  200        m_txn.set_streaming_width(
sizeof(TYPE) * p_number);
 
  201        m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
 
  202        if (initiator_socket->get_direct_mem_ptr(m_txn, 
m_dmi_data)) {
 
  205            ptr += (p_offset - start);
 
  207            m_dmi = 
reinterpret_cast<TYPE*
>(
ptr);
 
  212    std::string m_path_name;
 
  213    cci::cci_param<uint64_t> p_number;
 
  214    cci::cci_param<uint64_t> p_offset;
 
  215    cci::cci_param<uint64_t> p_size;
 
  216    cci::cci_param<TYPE> p_mask;
 
  217    cci::cci_param<bool> p_relative_addresses;
 
  219    tlm_utils::simple_initiator_socket<proxy_data_array, DEFAULT_TLM_BUSWIDTH> initiator_socket;
 
  226            SCP_TRACE(())(
"Got value (DMI) : [{:#x}]", fmt::join(std::vector<TYPE>(&
dst[0], &
dst[length]), 
","));
 
  228            tlm::tlm_generic_payload m_txn;
 
  229            sc_core::sc_time dummy;
 
  230            m_txn.set_byte_enable_length(0);
 
  231            m_txn.set_dmi_allowed(
false);
 
  232            m_txn.set_command(tlm::TLM_READ_COMMAND);
 
  233            m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
dst));
 
  234            m_txn.set_address(p_offset + (
sizeof(TYPE) * 
idx));
 
  235            m_txn.set_data_length(
sizeof(TYPE) * length);
 
  236            m_txn.set_streaming_width(
sizeof(TYPE) * length);
 
  237            m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
 
  238            initiator_socket->b_transport(m_txn, dummy);
 
  239            sc_assert(m_txn.get_response_status() == tlm::TLM_OK_RESPONSE);
 
  240            SCP_TRACE(())(
"Got value (transport) : [{:#x}]", fmt::join(std::vector<TYPE>(&
dst[0], &
dst[length]), 
","));
 
  241            if (m_txn.is_dmi_allowed()) {
 
  251            SCP_TRACE(())(
"Set value (DMI) : [{:#x}]", fmt::join(std::vector<TYPE>(&
src[0], &
src[length]), 
","));
 
  256                write_with_mask(
src, 
reinterpret_cast<TYPE*
>(&m_dmi[
idx]), length);
 
  259            tlm::tlm_generic_payload m_txn;
 
  260            sc_core::sc_time dummy;
 
  263                m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
src));
 
  266                get(
reinterpret_cast<TYPE*
>(
curr_data.data()), 
idx, length);
 
  267                write_with_mask(
src, 
reinterpret_cast<TYPE*
>(
curr_data.data()), length);
 
  268                m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
curr_data.data()));
 
  270            m_txn.set_byte_enable_length(0);
 
  271            m_txn.set_dmi_allowed(
false);
 
  272            m_txn.set_command(tlm::TLM_WRITE_COMMAND);
 
  273            m_txn.set_address(p_offset + (
sizeof(TYPE) * 
idx));
 
  274            m_txn.set_data_length(
sizeof(TYPE) * length);
 
  275            m_txn.set_streaming_width(
sizeof(TYPE) * length);
 
  276            m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
 
  277            SCP_TRACE(())(
"Set value (transport) : [{:#x}]", fmt::join(std::vector<TYPE>(&
src[0], &
src[length]), 
","));
 
  278            initiator_socket->b_transport(m_txn, dummy);
 
  279            sc_assert(m_txn.get_response_status() == tlm::TLM_OK_RESPONSE);
 
  280            if (m_txn.is_dmi_allowed()) {
 
  289            SCP_FATAL(())(
"write_with_mask(): src pointer is NULL");
 
  292            SCP_FATAL(())(
"write_with_mask(): dst pointer is NULL");
 
  306    TYPE& operator[](
int idx)
 
  311                SCP_FATAL(())(
"Operator[] can only be used for DMI'able registers");
 
  314        SCP_TRACE(())(
"Access value (DMI) using operator [] at idx {}", 
idx);
 
  316            SCP_FATAL(()) << 
"operator[](): Register Mask: 0x" << std::hex << p_mask.get_value()
 
  317                          << 
" has readonly bits, please use set(TYPE* src, uint64_t idx, uint64_t length) and " 
  318                             "get(TYPE* dst, uint64_t idx, uint64_t length) instead";
 
  322    void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) { m_dmi = 
nullptr; }
 
  326        : SCP_LOGGER_NAME()(
logger)
 
  328        , p_number(
path_name + 
".number", 
number, 
"number of elements in this register")
 
  329        , initiator_socket((name + 
"_initiator_socket").
c_str())
 
  330        , p_offset(
path_name + 
".target_socket.address", 
_offset, 
"Offset of this register")
 
  331        , p_size(
path_name + 
".target_socket.size", 
sizeof(TYPE) * 
number, 
"size of this register")
 
  332        , p_mask(
path_name + 
".target_socket.mask", 
mask, 
" R/W mask, 0 means read only, and 1 means write/read")
 
  333        , p_relative_addresses(
path_name + 
".target_socket.relative_addresses", 
true,
 
  334                               "allow relative_addresses for this register")
 
  337        initiator_socket.register_invalidate_direct_mem_ptr(
this,
 
 
  385    SCP_LOGGER((), 
"register");
 
  388    std::string m_regname;
 
  390    std::vector<unsigned char> captured_txn_data;
 
  401        std::string 
n(name());
 
  402        SCP_LOGGER_NAME().features[0] = parent(
n) + 
"." + 
_name;
 
  403        n = 
n.substr(0, 
n.length() - 
strlen(
"_target_socket")); 
 
  406        register_transport_dbg_func([&](tlm::tlm_generic_payload& 
txn) {
 
  407            if (
txn.get_data_length() < 
sizeof(TYPE)) 
return (
unsigned int)0;
 
  408            unsigned char* data = 
txn.get_data_ptr();
 
  409            if (
txn.get_command() == tlm::TLM_READ_COMMAND) {
 
  410                TYPE tmp = proxy_data<TYPE>::get();
 
  411                memset(data, 0, txn.get_data_length());
 
  412                memcpy(data, &tmp, sizeof(TYPE));
 
  413                return (unsigned int)sizeof(TYPE);
 
  415            if (
txn.get_command() == tlm::TLM_WRITE_COMMAND) {
 
  417                memcpy(&tmp, data, sizeof(TYPE));
 
  418                proxy_data<TYPE>::set(tmp);
 
  419                return (unsigned int)sizeof(TYPE);
 
  430    void operator/=(TYPE 
other)
 
  432        if (
other == 0) 
SCP_FATAL(())(
"Trying to divide a register value by 0!");
 
  450    std::string get_regname()
 const { 
return m_regname; }
 
  451    std::string get_path()
 const { 
return m_path; }
 
  454    void set_mask(TYPE 
mask) 
 
  460    void capture_txn_pre(tlm::tlm_generic_payload& 
txn)
 override 
  463            (
txn.get_command() != tlm::tlm_command::TLM_WRITE_COMMAND)) {
 
  468            SCP_FATAL(()) << 
"capture_txn_pre(): txn data length should be n * sizeof(TYPE) where n >= 1";
 
  476        captured_txn_data.clear();
 
  478        get(
reinterpret_cast<TYPE*
>(captured_txn_data.data()), 
idx, 
txn_data_len / 
sizeof(TYPE));
 
  480    void handle_mask_post(tlm::tlm_generic_payload& 
txn)
 override 
  483            (
txn.get_command() != tlm::tlm_command::TLM_WRITE_COMMAND)) {
 
  488            SCP_FATAL(()) << 
"handle_mask_post(): txn data length should be n * sizeof(TYPE) where n >= 1";
 
  498                                          reinterpret_cast<TYPE*
>(captured_txn_data.data()),
 
  500        set(
reinterpret_cast<TYPE*
>(captured_txn_data.data()), 
idx, 
txn_data_len / 
sizeof(TYPE), 
false);