⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at_interconnect.h

📁 这是一个systemc语言的几个实例。都能正常运行。
💻 H
📖 第 1 页 / 共 2 页
字号:

// Filename: at_interconnect.h

//----------------------------------------------------------------------
//  Copyright (c) 2008 by Doulos Ltd.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//----------------------------------------------------------------------

// Version 1  09-Sep-2008


#ifndef __AT_INTERCONNECT_H__
#define __AT_INTERCONNECT_H__

#include "common_header.h"

struct AT_interconnect: sc_module
{
  tlm_utils::multi_passthrough_target_socket   <AT_interconnect, 32> targ_socket;
  tlm_utils::multi_passthrough_initiator_socket<AT_interconnect, 32> init_socket;

  SC_CTOR(AT_interconnect)
  : targ_socket("targ_socket")
  , init_socket("init_socket")
  {
    targ_socket.register_b_transport              (this, &AT_interconnect::b_transport);
    targ_socket.register_nb_transport_fw          (this, &AT_interconnect::nb_transport_fw);
    targ_socket.register_get_direct_mem_ptr       (this, &AT_interconnect::get_direct_mem_ptr);
    targ_socket.register_transport_dbg            (this, &AT_interconnect::transport_dbg);
    init_socket.register_nb_transport_bw          (this, &AT_interconnect::nb_transport_bw);
    init_socket.register_invalidate_direct_mem_ptr(this, &AT_interconnect::invalidate_direct_mem_ptr);
  }

  void end_of_elaboration()
  {
    n_targets       = init_socket.size();
    n_inits         = targ_socket.size();
    req_in_progress = new gp_ptr  [n_targets];
    rsp_in_progress = new gp_ptr  [n_inits];
    end_req_event   = new sc_event[n_targets];
    end_rsp_event   = new sc_event[n_inits];
    req_queue       = new std::deque<Trans>[n_targets];
    rsp_queue       = new std::deque<Trans>[n_inits];

    // Spawn one process per target, to wake up on receiving END_REQ

    for (unsigned int i = 0; i < n_targets; i++)
    {
      sc_spawn_options* opt = new sc_spawn_options;
      opt->spawn_method();
      opt->dont_initialize();
      opt->set_sensitivity( &end_req_event[i] );

      ostringstream oss;
      oss << "end_req_process" << i;
      sc_spawn(sc_bind(&AT_interconnect::end_req_process, this, i), oss.str().c_str(), opt);

      req_in_progress[i] = 0;
    }

    // Spawn one process per initiator, to wake up on receiving END_RESP

    for (unsigned int i = 0; i < n_inits; i++)
    {
      sc_spawn_options* opt = new sc_spawn_options;
      opt->spawn_method();
      opt->dont_initialize();
      opt->set_sensitivity( &end_rsp_event[i] );

      ostringstream oss;
      oss << "end_rsp_process" << i;
      sc_spawn(sc_bind(&AT_interconnect::end_rsp_process, this, i), oss.str().c_str(), opt);

      rsp_in_progress[i] = 0;
    }
  }

  // Forward interface

  virtual void b_transport( int id, tlm::tlm_generic_payload& trans, sc_time& delay )
  {
    sc_dt::uint64 masked_address;
    unsigned int target = decode_address( trans.get_address(), masked_address );
    trans.set_address( masked_address );

    init_socket[target]->b_transport( trans, delay );
  }


  virtual tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload& trans,
                                              tlm::tlm_phase& phase, sc_time& delay )
  {
    unsigned int target;

    // Sticky extension, survives the transaction pool
    route_extension* ext;
    accessor(trans).get_extension(ext);

    bool is_request = (phase == tlm::BEGIN_REQ);

    if (phase == tlm::BEGIN_REQ)
    {
      sc_dt::uint64 masked_address;
      target = decode_address( trans.get_address(), masked_address );
      trans.set_address( masked_address );

      if (!ext)
      {
        ext = new route_extension;
        accessor(trans).set_extension(ext);
      }
      ext->init   = id;
      ext->target = target;
      ext->dont_propagate_fw = false;

      if (req_in_progress[target])
      {
        // Queue the request to be sent forward later
        trans.acquire();
        Trans req;
        req.trans = &trans;
        req.time  = sc_time_stamp() + delay;
        req_queue[target].push_back( req );

        return tlm::TLM_ACCEPTED;
      }
      req_in_progress[target] = &trans;
    }
    else if (phase == tlm::END_RESP)
    {
      assert(ext);
      assert( ext->init == id );
      target = ext->target;

      assert( rsp_in_progress[ext->init] );
      end_rsp_event[ext->init].notify();

      if (ext->dont_propagate_fw)
        return tlm::TLM_ACCEPTED;
    }

    tlm::tlm_sync_enum status;
    status = init_socket[target]->nb_transport_fw( trans, phase, delay );

    if (status == tlm::TLM_UPDATED)
    {
      if ((phase == tlm::END_REQ) || (phase == tlm::BEGIN_RESP))
      {
        assert( req_in_progress[target] );
        end_req_event[target].notify();
      }

      // Need to check response exclusion rule here before passing BEGIN_RESP on return path!
      if (phase == tlm::BEGIN_RESP)
      {
        if (rsp_in_progress[id])
        {
          queue_the_rsp_to_be_sent_bw_later( id, &trans, delay );
          return tlm::TLM_ACCEPTED;
        }
        rsp_in_progress[id] = &trans;
      }
    }
    else if (status == tlm::TLM_COMPLETED)
    {
      // Incoming phase could have been BEGIN_REQ or END_RESP
      if ( is_request )
      {
        end_req_event[target].notify();

        // Once target has returned TLM_COMPLETED, do not propagate transaction forward again
        ext->dont_propagate_fw = true;

        // Need to check response exclusion rule here before passing BEGIN_RESP on return path!
        if (rsp_in_progress[id])
        {
          queue_the_rsp_to_be_sent_bw_later( id, &trans, delay );
          return tlm::TLM_ACCEPTED;
        }
      }
      // Cannot expect an END_RESP from the initiator after returning TLM_COMPLETED
    }

    return status;
  }

  virtual bool get_direct_mem_ptr( int id, tlm::tlm_generic_payload& trans,
                                           tlm::tlm_dmi& dmi_data)
  {
    sc_dt::uint64 masked_address;
    unsigned int target = decode_address( trans.get_address(), masked_address );
    trans.set_address( masked_address );

    bool status = init_socket[target]->get_direct_mem_ptr( trans, dmi_data );

    dmi_data.set_start_address( reconstruct_address(dmi_data.get_start_address(), target) );
    dmi_data.set_end_address(   reconstruct_address(dmi_data.get_end_address(), target) );

    return status;
  }

  virtual unsigned int transport_dbg( int id, tlm::tlm_generic_payload& trans )
  {
    sc_dt::uint64 masked_address;
    unsigned int target = decode_address( trans.get_address(), masked_address );
    trans.set_address( masked_address );

    return init_socket[target]->transport_dbg( trans );
  }


  // Backward interface

  virtual tlm::tlm_sync_enum nb_transport_bw( int id, tlm::tlm_generic_payload& trans,
                                              tlm::tlm_phase& phase, sc_time& delay )
  {
    if (phase == tlm::END_REQ || (&trans == req_in_progress[id] && phase == tlm::BEGIN_RESP))
    {
      assert( req_in_progress[id] );
      end_req_event[id].notify();
    }

    route_extension* ext;
    accessor(trans).get_extension(ext);
    assert(ext);

    int init   = ext->init;

    if (phase == tlm::BEGIN_RESP)
    {
      if (rsp_in_progress[init])
      {
        queue_the_rsp_to_be_sent_bw_later( init, &trans, delay );
        return tlm::TLM_ACCEPTED;
      }

      rsp_in_progress[init] = &trans;

      // Set the delay so there are multiple responses pending
      delay = delay + sc_time(1000, SC_PS);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -