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

📄 at_interconnect.h

📁 这是一个systemc语言的几个实例。都能正常运行。
💻 H
📖 第 1 页 / 共 2 页
字号:
    tlm::tlm_sync_enum status;
    status = targ_socket[init]->nb_transport_bw( trans, phase, delay );

    if (status == tlm::TLM_COMPLETED)
    {
      assert( phase == tlm::BEGIN_RESP );
      assert( rsp_in_progress[init] );
      end_rsp_event[init].notify();
    }

    return status;
  }


  virtual void invalidate_direct_mem_ptr( int id, sc_dt::uint64 start_range,
                                                  sc_dt::uint64 end_range )
  {
    // Reconstruct address range in system memory map
    sc_dt::uint64 bw_start_range = reconstruct_address(start_range, id);
    sc_dt::uint64 bw_end_range   = reconstruct_address(end_range, id);

    // Propagate call backward to all initiators
    for (unsigned int i = 0; i < targ_socket.size(); i++)
      targ_socket[i]->invalidate_direct_mem_ptr(bw_start_range, bw_end_range);
  }


private:

  void end_req_process( unsigned int target )
  {
    // Called whenever END_REQ is received from a target
    assert( req_in_progress[target] );

    if ( req_queue[target].empty() )
    {
      req_in_progress[target] = 0;
    }
    else
    {
      // Requests are serviced in a first-come-first-served order
      // You would re-write this to implement the arbitration strategy of
      // your particular interconnect component.

      Trans req = req_queue[target].front();
      req_queue[target].pop_front();

      gp_ptr         trans = req.trans;
      tlm::tlm_phase phase = tlm::BEGIN_REQ;
      sc_time        delay;

      if (req.time < sc_time_stamp())
        delay = SC_ZERO_TIME;
      else
        delay = req.time - sc_time_stamp();

      req_in_progress[target] = trans;

      route_extension* ext;
      accessor(*trans).get_extension(ext);
      assert(ext);
      assert( ext->target == int(target) );
      int init = ext->init;

      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
        if (phase == tlm::BEGIN_RESP)
        {
          if (rsp_in_progress[init])
          {
            queue_the_rsp_to_be_sent_bw_later( init, trans, delay );
            return;
          }
          rsp_in_progress[init] = trans;
        }

        // Need to propagate transaction to initiator on backward path
        send_bw_to_initiator( trans, phase, delay);
      }
      else if (status == tlm::TLM_COMPLETED)
      {
        // The original BEGIN_REQ was stalled because there was an outstanding request on the
        // target-side socket. Then on finally sending the delayed BEGIN_REQ to the target,
        // the target immediately returns TLM_COMPLETED. This suggests a weird target!

        assert( req_in_progress[target] );
        end_req_event[target].notify();

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

        // Need to propagate response to initiator on backward path
        phase = tlm::BEGIN_RESP;

        // Need to check response exclusion rule
        if (rsp_in_progress[init])
        {
          queue_the_rsp_to_be_sent_bw_later( init, trans, delay );
          return;
        }
        rsp_in_progress[init] = trans;

        // Need to propagate transaction to initiator on backward path
        send_bw_to_initiator( trans, phase, delay);
      }

      // Finally finished with the delayed request transaction
      trans->release();
    }
  }

  void queue_the_rsp_to_be_sent_bw_later( unsigned int init, tlm::tlm_generic_payload* trans, sc_time& delay )
  {
    trans->acquire();
    Trans rsp;
    rsp.trans = trans;
    rsp.time  = sc_time_stamp() + delay;
    rsp_queue[init].push_back( rsp );
  }

  void end_rsp_process( unsigned int init )
  {
    // Called whenever END_RESP (or TLM_COMPLETED) is received from an initiator
    assert( rsp_in_progress[init] );

    if ( rsp_queue[init].empty() )
    {
      rsp_in_progress[init] = 0;
    }
    else
    {
      Trans rsp = rsp_queue[init].front();
      rsp_queue[init].pop_front();

      gp_ptr         trans = rsp.trans;
      tlm::tlm_phase phase = tlm::BEGIN_RESP;
      sc_time        delay;

      if (rsp.time < sc_time_stamp())
        delay = SC_ZERO_TIME;
      else
        delay = rsp.time - sc_time_stamp();

      rsp_in_progress[init] = trans;

      // Need to propagate transaction to initiator on backward path
      send_bw_to_initiator( trans, phase, delay);

      // Finally finished with the delayed response transaction
      trans->release();
    }
  }

  void send_bw_to_initiator( tlm::tlm_generic_payload* trans,
                             tlm::tlm_phase& phase, sc_time& delay )
  {
    // Propagate END_REQ or BEGIN_RESP transaction to initiator on backward path

    route_extension* ext;
    accessor(*trans).get_extension(ext);
    assert(ext);
    int init   = ext->init;
    int target = ext->target;

    tlm::tlm_sync_enum status = targ_socket[init]->nb_transport_bw( *trans, phase, delay );

    if (status == tlm::TLM_UPDATED || status == tlm::TLM_COMPLETED)
    {
      // Initiator would normally return TLM_COMPLETED here
      // TLM_UPDATED only makes sense when an extended phase will be sent later

      assert( rsp_in_progress[init] );
      end_rsp_event[init].notify();

      if (ext->dont_propagate_fw)
        return;

      // Need to propagate END_RESP transaction to target on forward path
      phase = tlm::END_RESP;

      status = init_socket[target]->nb_transport_fw( *trans, phase, delay );
      assert( status != tlm::TLM_UPDATED );
      // Ignore return value
    }
  }

  unsigned int decode_address( sc_dt::uint64 address, sc_dt::uint64& masked_address )
  {
    // You would re-write this function to implement the particular routing strategy
    // of your interconnect component.

    // Use the top bits of the address to indicate target
    masked_address = address & 0xff;
    unsigned int target = (unsigned int)(address >> 8);

    // If address is too big, just wrap around the target number
    return target % n_targets;
  }

  sc_dt::uint64 reconstruct_address ( uint64 address, unsigned int target )
  {
    return address | (target << 8);
  }


private:

  unsigned int n_targets;
  unsigned int n_inits;

  typedef tlm::tlm_generic_payload* gp_ptr;

  // Extension to store routing information in transaction

  struct route_extension: tlm_utils::instance_specific_extension<route_extension>
  {
    int init;
    int target;
    bool dont_propagate_fw;
  };

  tlm_utils::instance_specific_extension_accessor accessor;

  // Flags, events and queues to implement the request and response exclusion rules

  gp_ptr*     req_in_progress;
  gp_ptr*     rsp_in_progress;
  sc_event*   end_req_event;
  sc_event*   end_rsp_event;

  struct Trans
  {
    gp_ptr  trans;
    sc_time time;
  };

  std::deque<Trans>* req_queue;
  std::deque<Trans>* rsp_queue;
};

#endif

⌨️ 快捷键说明

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