Code Search for Developers
 
 
  

ship_masterport.h from GreenSocs at Krugle


Show ship_masterport.h syntax highlighted

#ifndef __ship_masterport_h__
#define __ship_masterport_h__

#include "ship_serializable_if.h"
#include "ship_datatypes.h"

namespace tlm {


//---------------------------------------------------------------------------
/**
 * This is the SHIP master port.
 * Use target_addr parameter to configure the target address if
 * connected to a router.
 * Use mode parameter to configure operation mode of this SHIP port.
 */
//---------------------------------------------------------------------------
template <class T>
class shipMasterAPI
: public GenericMasterPort
{  
public:
  typedef GenericMasterPort PORT;

  typedef typename PORT::transaction transaction;
  typedef typename PORT::transactionHandle transactionHandle;
  typedef typename PORT::accessHandle accessHandle;
  typedef typename PORT::phase phase;

  /// the operation mode of this SHIP port
  gs_param<gs_uint32> mode;
  /// the clock period of this SHIP port
  gs_param<gs_uint32> clk_period;


  SC_HAS_PROCESS(shipMasterAPI);

  /**
   * Create a SHIP master port. Use configuration framework
   * to set parameters target_addr and mode.
   */
  shipMasterAPI ( sc_module_name port_name ) 
    : PORT(port_name),
      mVector(NULL)
  {
    // DUST structure analysis
#ifdef DUST_ENABLE
    DUST_MASTER_PORT("ShipMasterAPI", "SHIP");
#endif

    SC_METHOD(react); // handle PVT protocol
    sensitive << PORT::default_event();
    dont_initialize();

    SC_METHOD(ct_react); // this method handles CT quark update events
    sensitive << mCTStartEvent;
    dont_initialize();

    mCmd.cmd = SHIP_NONE;

    mVector = new std::vector<gs_uint8>();

    GS_PARAM(mode, gs_uint32, SHIP_MODE_PV); // default mode is PV
    GS_PARAM(clk_period, gs_uint32, 10); // default clock period is 10ns (not used in PV mode)
  }

 
  /// Send a SHIP object to a slave
  /**
   * The send method sends a SHIP object to a SHIP slave.
   * Communication using this method is blocking, thus 
   * it will not return until the SHIP object has been 
   * completely delivered to the slave.
   *
   * @param obj The object to be send.
   */
  void send( T& obj ) {
    mah = PORT::create_transaction();

    mVector->empty();
    GSDataType data;
    data.setData(*mVector);

    unsigned int objbytes = obj.getSerialLength();
    mCmd.cmd = SHIP_SEND;
    mCmd.burstlength = objbytes; 

    mah->setMAddr(target_addr);
    mah->setMBurstLength(objbytes); 
    mah->setMCmd(Generic_MCMD_WR);

    if (mode==SHIP_MODE_PV) { // PV bypass mode 
      data.setPointer(static_cast<void*>(&obj));
      mah->setMData(data); // pass SHIP object by pointer
      GS_TRACE(name(), "send() calls PV Transact.");
      PORT::Transact(mah);
      mCmd.cmd = SHIP_NONE;
    }

    else { // PVT mode
      // fill transaction container with transaction data
      if (mode==SHIP_MODE_BA_P) { // BA performance mode
        data.setPointer(static_cast<void*>(&obj)); 
        mah->setMData(data); // pass SHIP object by pointer
      }
      else { // BA or CT mode
        obj.serialize(data); // serialize SHIP object
        mah->setMData(data); // pass SHIP object by value
      }
      
      // request phase
      bool success=false;
      while(!success) {
        if (mode==SHIP_MODE_CT) {
          GS_TRACE(name(), "send() starts write request with burstlength=%d, running in CT simulation mode.", objbytes);
          PORT::Request.block(mah, SC_ZERO_TIME, MODE_CT);
        }
        else {
          GS_TRACE(name(), "send() starts write request with burstlength=%d.", objbytes);
          PORT::Request.block(mah, SC_ZERO_TIME);
        }
        
        mph = PORT::get_phase();
        if (mph.state == GenericPhase::RequestAccepted) {
          if (mph.getSimulationMode()==MODE_CT) {
            GS_TRACE(name(), "send() write request has been accepted by the slave, running in CT simulation mode.");
          }
          else {
            GS_TRACE(name(), "send() write request has been accepted by the slave.");
          }
          success = true;
        } else {
          char ch[1024];
          sprintf(ch, "A write request was not acknowledged by the slave - got phase=%s (%d) - maybe a timeout occured. Sending request again.", mph.toString().c_str(), mph.state);
          SC_REPORT_WARNING(name(), ch);
        }
      }
      
      // data phase 
      if (mode==SHIP_MODE_CT) { // CT mode
        sendDataCT();
      }
      else { // BA mode
        PORT::SendData.block(mah, mph, SC_ZERO_TIME); // atomic BA data phase
      }

      mph = PORT::get_phase();
      if (mph.state == GenericPhase::DataAccepted) {
        GS_TRACE(name(), "send() write data has been accepted by the slave.");
      } else {
        char ch[1024];
        sprintf(ch, "Master data was not acknowledged by the slave - got phase=%s (%d) - a severe error occured.", mph.toString().c_str(), mph.state);
        SC_REPORT_ERROR(name(), ch);
      }
      
      mCmd.cmd = SHIP_NONE;
    }

  }

  ~shipMasterAPI() {
    if (mVector != NULL)
      delete mVector;
  }
  

  /// Request a SHIP object from a slave
  /**
   * The request method requests a SHIP object from a SHIP slave.
   * Communication using this method is blocking, thus the request
   * method will not return unless the SHIP object
   * has been completely received.
   * @param obj A reference to an SHIP object, into which 
   *            the requested data will be copied.
   */
  void request( T& obj ) {
    sc_assert(mCmd.cmd == SHIP_NONE);

    accessHandle mah = PORT::create_transaction();

    mah->setMCmd(Generic_MCMD_RD);
    mah->setMAddr(target_addr);

    mCmd.cmd = SHIP_REQUEST;
    mCmd.burstlength = 0;

    if (mode==SHIP_MODE_PV) { // PV bypass mode 
      GS_TRACE(name(), "request() calls PV b_transact.");
      PORT::Transact(mah);
      
      // now lets look what we have received
      GSDataType data;
      data.set(mah->getMData());
      sc_assert(data.isPointer());
      T *robj = static_cast<T*>(data.getPointer()); 
      obj = *robj; // copy received SHIP object to master
    }

    else { // PVT modes
      bool success=false;
      while(!success) {
        if (mode==SHIP_MODE_CT) {
          GS_TRACE(name(), "request() starts request phase, running in CT simulation mode.");
          PORT::Request.block(mah, SC_ZERO_TIME, MODE_CT);
        }
        else {
          GS_TRACE(name(), "request() starts request phase.");
          PORT::Request.block(mah, SC_ZERO_TIME);
        }
        
        mph = PORT::get_phase();
        if (mph.state == GenericPhase::RequestAccepted) {
          mCmd.burstlength = mah->getSBurstLength();
          if (mph.getSimulationMode()==MODE_CT) {
            GS_TRACE(name(), "request() read request has been accepted by the slave, burstlength=%d, running in CT simulation mode.", mCmd.burstlength);
          }
          else {
            GS_TRACE(name(), "request() read request has been accepted by the slave, burstlength=%d.", mCmd.burstlength);
          }
          success = true;
        } else {
          char ch[1024];
          sprintf(ch, "A read request was not acknowledged by the slave - got phase=%s (%d) - maybe a timeout occured. Sending request again.", mph.toString().c_str(), mph.state);
          SC_REPORT_WARNING(name(), ch);
        }
      }

      // now wait for slave response (will be received by react method)
      sc_core::wait(mResponseEvent);

      // check the received data
      GSDataType data;
      data.set(mah->getMData());

      if (data.isPointer()) { // slave uses BA performance mode and sent just a pointer
        T *robj = static_cast<T*>(data.getPointer()); 
        obj = *robj; // copy received SHIP object to master
        mah->setMBurstLength(obj.getSerialLength()); // ack complete reception
      }

      // TODO: we assume here that we can accept one data quark per clock cycle

      else { // slave sent a serialized SHIP object
        if ((mph.getSimulationMode() == MODE_CT)) { // slave responses in CT mode
          // notify ct_react method of that there is some work for it now
          ct_react_wakeup = true;
          mCTStartEvent.notify();
          sc_core::wait(mCTFinishEvent); // wait for CT simulation to finish
        }

        obj.deserialize(data); // deserialize received data
      }      
      
      if (data.isPointer() || mph.getSimulationMode()!=MODE_CT) { // BA atomic ack
        mah->setMBurstLength(mah->getSBurstLength()); // ack all data quarks at once
        PORT::AckResponse(mah, mph, sc_time(clk_period*mah->getSBurstLength()/mah->getSDataWidth(), SC_NS)); 
        // block request method for the transfer delay
        sc_core::wait(sc_time(clk_period*mah->getSBurstLength()/mah->getSDataWidth(), SC_NS));
      }
      
      GS_TRACE(name(), "request() received slave response OK.");
    }
    
    mCmd.cmd = SHIP_NONE;
  }


  /// Wrapper for bind operator
  void operator() (tlm_port<b_if_type,if_type>& other) {
    PORT::operator()(other);
  }
  
  /// Wrapper for bind operator
  void operator() (tlm_multi_port<b_if_type,if_type>& other) {
    PORT::operator()(other);
  }
  
  void operator() (tlm_port_forwarder_base<b_if_type,if_type>& other) {
    PORT::operator()(other);
  }


protected:
  /**
   * Play the PVT protocol with the slave
   */
  void react() {
    mah = PORT::get_transaction();
    mph = PORT::get_phase();
    PVTProcess();
  }

  void PVTProcess() { 
    switch (mph.state) {
    case GenericPhase::ResponseValid: // slave sends response
      {
        mCmd.burstlength = mah->getSBurstLength();
        GS_TRACE(name(), "react() received slave response (a SHIP object of %d bytes).", (gs_uint32)mah->getSBurstLength());        
        // notify request() method
        mResponseEvent.notify();
      }
      break;

    default:
      break; // do nothing
    }
  }


  /**
   * Send data in CT simulation mode to the target.
   */
  inline void sendDataCT() {
    GS_TRACE(name(), "sendDataCT() starting data phase.");
    mCTStartEvent.notify(SC_ZERO_TIME); 
    PORT::SendData.block(mah, mph, SC_ZERO_TIME, MODE_CT); // start CT data phase
  }


  /**
   * Play the CT-protocol with the slave.
   * This method is made dynamically sensitive to the quark update event 
   * by the send() and request() functions when they run in CT simulation mode. 
   */
  void ct_react() {
    if (mCmd.cmd == SHIP_SEND) { // we are the transmitter
      // send next data quark
      if (mCmd.burstlength>mah->getSBurstLength()) {
        mah->notifyTargetUpdate(clk_period, SC_NS); // send a data quark with the next rising clock edge
        // wait for target acknowledge
        next_trigger(mah->getInitiatorUpdateEvent());
      }
      else {
        GS_TRACE(name(), "ct_react() sent last data quark.");
      }
    }

    else if (mCmd.cmd == SHIP_REQUEST) { // we are the receiver
      if (ct_react_wakeup) { 
        ct_react_wakeup=false;
      }
      else {
        mah->notifyTargetUpdate(SC_ZERO_TIME); // acknowledge the received quark
        mah->setMBurstLength(mah->getMBurstLength()+mah->getMDataWidth()); // increment number of received bytes
        //GS_TRACE(name(), "ct_react() received data quark %d", (gs_uint32)mah->getMBurstLength());
        if (mah->getSBurstLength()<=mah->getMBurstLength()) { // are we done?
          GS_TRACE(name(), "ct_react() received last data quark. Sending AckResponse.");
          PORT::AckResponse(mah, mph, clk_period, SC_NS, MODE_CT);
          mCTFinishEvent.notify();
          return;
        }        
      }
      // wait for next data quark 
      next_trigger(mah->getInitiatorUpdateEvent());
    }
  }
  


protected:
  /// The current SHIP command
  ship_command mCmd;
  /// Internal notification
  sc_event mResponseEvent;
  /// Serialization buffer
  std::vector<gs_uint8> *mVector;
  /// Internal events for CT simulation
  sc_event mCTStartEvent, mCTFinishEvent;
  /// Wake-up indicator for ct_react method
  bool ct_react_wakeup;
  /// The current transcation container
  accessHandle mah;
  /// The current phase
  phase mph;
};

} // namespace tlm

#endif




See more files for this project here

GreenSocs

To develop SystemC infrustructure, basic IP, patches and add on library code for eventual standerdization.\r\nThe GreenSocs project is made up of a number of contributions (sub projects). Please visit www.greensocs.com for more information.

Project homepage: http://sourceforge.net/projects/greensocs
Programming language(s): C,C++,Java,Perl,XML
License: other

  ship_datatypes.h
  ship_masterport.h
  ship_serializable_if.h
  ship_slaveport.h