Пример #1
0
  tlm::tlm_sync_enum send_end_req(tlm::tlm_generic_payload& trans)
  {
    tlm::tlm_sync_enum status;
    tlm::tlm_phase bw_phase;
    tlm::tlm_phase int_phase = internal_ph;
    sc_time delay;

    // Queue the acceptance and the response with the appropriate latency
    bw_phase = tlm::END_REQ;
    delay = sc_time(rand_ps(), SC_PS); // Accept delay
    status = socket->nb_transport_bw( trans, bw_phase, delay );
    if (status == tlm::TLM_COMPLETED)
    {
      // Transaction aborted by the initiator
      // (TLM_UPDATED cannot occur at this point in the base protocol, so need not be checked)
      trans.release();
      return status;
    }

    // Queue internal event to mark beginning of response
    delay = delay + sc_time(rand_ps(), SC_PS); // Latency
    m_peq.notify( trans, int_phase, delay );
    n_trans++;

    return status;
  }
Пример #2
0
    void send_response(tlm::tlm_generic_payload& trans){
        tlm::tlm_sync_enum status;
        tlm::tlm_phase bw_phase;

        bw_phase = tlm::BEGIN_RESP;
        sc_time zeroDelay = SC_ZERO_TIME;
        status = (*(this->socket[transId]))->nb_transport_bw(trans, bw_phase, zeroDelay);

        //std::cerr << "response status " << status << std::endl;
        if (status == tlm::TLM_UPDATED){
            // The timing annotation must be honored
            m_peq.notify(trans, bw_phase, SC_ZERO_TIME);
        }
        else if (status == tlm::TLM_COMPLETED){
            // The initiator has terminated the transaction
            trans.release();
        }
    }
Пример #3
0
    tlm::tlm_sync_enum send_end_req(tlm::tlm_generic_payload& trans){
        tlm::tlm_sync_enum status;
        tlm::tlm_phase bw_phase;
        tlm::tlm_phase int_phase = internal_ph;

        // Queue the acceptance and the response with the appropriate latency
        bw_phase = tlm::END_REQ;
        sc_time zeroDelay = SC_ZERO_TIME;
        status = (*(this->socket[transId]))->nb_transport_bw(trans, bw_phase, zeroDelay);
        if (status == tlm::TLM_COMPLETED){
            // Transaction aborted by the initiator
            // (TLM_UPDATED cannot occur at this point in the base protocol, so need not be checked)
            trans.release();
            return status;
        }
        // Queue internal event to mark beginning of response
        m_peq.notify( trans, int_phase, this->latency );
        return status;
    }
Пример #4
0
  // Called on receiving BEGIN_RESP or TLM_COMPLETED
  void check_transaction(tlm::tlm_generic_payload& trans)
  {
    if ( trans.is_response_error() )
    {
      char txt[100];
      sprintf(txt, "Transaction returned with error, response status = %s",
                   trans.get_response_string().c_str());
      SC_REPORT_ERROR("TLM-2", txt);
    }

    tlm::tlm_command cmd = trans.get_command();
    sc_dt::uint64    adr = trans.get_address();
    int*             ptr = reinterpret_cast<int*>( trans.get_data_ptr() );

    fout << hex << adr << " " << name() << " check, cmd=" << (cmd ? 'W' : 'R')
         << ", data=" << hex << *ptr << " at time " << sc_time_stamp() << endl;

    // Allow the memory manager to free the transaction object
    trans.release();
  }
Пример #5
0
  void send_response(tlm::tlm_generic_payload& trans)
  {
    tlm::tlm_sync_enum status;
    tlm::tlm_phase bw_phase;
    sc_time delay;

    response_in_progress = true;
    bw_phase = tlm::BEGIN_RESP;
    delay = SC_ZERO_TIME;
    status = socket->nb_transport_bw( trans, bw_phase, delay );

    if (status == tlm::TLM_UPDATED)
    {
      // The timing annotation must be honored
      m_peq.notify( trans, bw_phase, delay);
    }
    else if (status == tlm::TLM_COMPLETED)
    {
      // The initiator has terminated the transaction
      trans.release();
      n_trans--;
      response_in_progress = false;
    }
  }
Пример #6
0
  void peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase)
  {
    tlm::tlm_sync_enum status;
    sc_time delay;

    switch (phase) {
    case tlm::BEGIN_REQ:

      #ifdef DEBUG
        fout << hex << trans.get_address() << " " << name() << " BEGIN_REQ at " << sc_time_stamp() << endl;
      #endif

      // Increment the transaction reference count
      trans.acquire();

      // Put back-pressure on initiator by deferring END_REQ until pipeline is clear
      if (n_trans == 2)
        end_req_pending = &trans;
      else
      {
        status = send_end_req(trans);
        if (status == tlm::TLM_COMPLETED) // It is questionable whether this is valid
          break;
      }

      break;

    case tlm::END_RESP:
      // On receiving END_RESP, the target can release the transaction
      // and allow other pending transactions to proceed

      #ifdef DEBUG
        fout << hex << trans.get_address() << " " << name() << " END_RESP at " << sc_time_stamp() << endl;
      #endif

      if (!response_in_progress)
        SC_REPORT_FATAL("TLM-2", "Illegal transaction phase END_RESP received by target");

      trans.release();
      n_trans--;

      // Target itself is now clear to issue the next BEGIN_RESP
      response_in_progress = false;
      if (next_response_pending)
      {
        send_response( *next_response_pending );
        next_response_pending = 0;
      }

      // ... and to unblock the initiator by issuing END_REQ
      if (end_req_pending)
      {
        status = send_end_req( *end_req_pending );
        end_req_pending = 0;
      }

      break;

    case tlm::END_REQ:
    case tlm::BEGIN_RESP:
      SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by target");
      break;

    default:
      if (phase == internal_ph)
      {
        // Execute the read or write commands

        tlm::tlm_command cmd = trans.get_command();
        sc_dt::uint64    adr = trans.get_address();
        unsigned char*   ptr = trans.get_data_ptr();
        unsigned int     len = trans.get_data_length();

        if ( cmd == tlm::TLM_READ_COMMAND )
        {
          *reinterpret_cast<int*>(ptr) = rand();
          fout << hex << adr << " " << name() << " Execute READ, target = " << name()
               << " data = " << *reinterpret_cast<int*>(ptr) << endl;
        }
        else if ( cmd == tlm::TLM_WRITE_COMMAND )
          fout << hex << adr << " " << name() << " Execute WRITE, target = " << name()
               << " data = " << *reinterpret_cast<int*>(ptr) << endl;

        trans.set_response_status( tlm::TLM_OK_RESPONSE );

        // Target must honor BEGIN_RESP/END_RESP exclusion rule
        // i.e. must not send BEGIN_RESP until receiving previous END_RESP or BEGIN_REQ
        if (response_in_progress)
        {
          // Target allows only two transactions in-flight
          if (next_response_pending)
            SC_REPORT_FATAL("TLM-2", "Attempt to have two pending responses in target");
          next_response_pending = &trans;
        }
        else
          send_response(trans);
        break;
      }
    }
  }
tlm::tlm_sync_enum BridgeClassicToAMBATLM2<BUSWIDTH>::nb_bw_transport(tlm::tlm_generic_payload & trans, tlm::tlm_phase & ph, sc_core::sc_time &delay)
{
//  		std::cout << sc_core::sc_object::name()<< ph << std::endl;
	  	amba::amba_id * m_id;
	  	amba::amba_exclusive * m_exclusive;
	    tlm::tlm_sync_enum returnVal=tlm::TLM_ACCEPTED;
	    std::ostringstream msg;
	    msg.str("");
	    if(ph == amba::BEGIN_LAST_RESP || ph == tlm::BEGIN_RESP)
		{
			//assert(trans.get_command()==tlm::TLM_READ_COMMAND && "Write Command doesn't support the response.");
			master_sock.template get_extension<amba::amba_id>(m_id,trans);
			if (trans.is_write())
			{
//				std::cout << "TLM BEHAVIOR: received BEGIN_RESP at time " << sc_core::sc_time_stamp() << std::endl;
			  assert(ph == tlm::BEGIN_RESP);
			  assert(wr_packets[m_id->value] != NULL);
			  //as per packet.cc:74 writeback never needs a response
			  if (wr_packets[m_id->value]->cmd != MemCmd::Writeback)
			  {
					if (master_sock.template get_extension<amba::amba_exclusive>(m_exclusive,trans))
					{
						if (m_exclusive->value)
						{
							wr_packets[m_id->value]->req->setExtraData(0);
						}
						else
						{
							wr_packets[m_id->value]->req->setExtraData(1);
						}
					}
				  setCurTick(sc_core::sc_time_stamp().value());
                  wr_packets[m_id->value]->busFirstWordDelay = wr_packets[m_id->value]->busLastWordDelay = 0;
				  if (bus_stalling)
					  retryQueue.push(wr_packets[m_id->value]);
				  else if (!slavePort->sendTimingResp(wr_packets[m_id->value]))
				  {
						bus_stalling=true;
						retryQueue.push(wr_packets[m_id->value]);
				  }	
#ifdef DEBUG
				  else if (_trace_transactions)
					std::cout << "In " << sc_core::sc_object::name() << " at time " << sc_time_stamp() << " sending a WS response to GEM5 with address=0x" << hex << trans.get_address() << dec << " size=" << trans.get_data_length() << std::endl;
#endif
			  }
			  master_sock.release_transaction(&trans); //now we release
			  wr_packets[m_id->value] = NULL;
				if (needWrIdRetry)
				{
					setCurTick(sc_core::sc_time_stamp().value());
					needWrIdRetry=false;
					slavePort->sendRetry();
				}
			}
           else if (ph == amba::BEGIN_LAST_RESP)
           {
//				std::cout << "TLM BEHAVIOR: received BEGIN_LAST_RESP at time " << sc_core::sc_time_stamp() << std::endl;
				assert(rd_packets[m_id->value] != NULL);
				uint8_t * data=trans.get_data_ptr();
				PacketPtr pkt = rd_packets[m_id->value];
				pkt->makeTimingResponse();
				uint32_t shadow_size=pkt->getSize();
				uint64_t shadow_addr=pkt->getAddr();
//				std::cout << sc_core::sc_object::name() << " bridge received read data for address = "  << trans.get_address()-pkt->getAddr() << " at time " << sc_time_stamp() << std::endl;
				memcpy(pkt->getPtr<uint8_t>(),data,pkt->getSize());
//				if (master_sock.template get_extension<amba::amba_exclusive>(m_exclusive,trans))
//				{
//					if (m_exclusive->value)
//						pkt->req->setExtraData(0);
//					else
//						pkt->req->setExtraData(1);
//				}
				setCurTick(sc_core::sc_time_stamp().value());
                pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
				if (bus_stalling)
					retryQueue.push(pkt);
				else if (!slavePort->sendTimingResp(pkt))
				{
					bus_stalling=true;
					retryQueue.push(pkt);
				}	
#ifdef DEBUG				  						  
				else if (_trace_transactions)
				{
					std::cout << "In " << sc_core::sc_object::name() << " at time " << sc_time_stamp() << " sending a READ response to GEM5 with address=0x" << hex << shadow_addr << dec << " size=" << shadow_size;
					std::cout << hex << " and data= [";
					for(unsigned j=0;j<shadow_size; j++)
						std::cout << "0x" << uint32_t(data[j]) << ",";
					std::cout << "]" << dec << std::endl;
				}
#endif
				rd_packets[m_id->value]=NULL;
				master_sock.release_transaction(&trans);
				if (needRdIdRetry)
				{
					setCurTick(sc_core::sc_time_stamp().value());
					needRdIdRetry=false;
					slavePort->sendRetry();
				}
			}
           else
           {
        	   //received a read data phase
           }
			//always accept directly (cf EagleNest spec)
//			std::cout << "TLM BEHAVIOR: sending  TLM_UPDATED & END_RESP at time " << sc_core::sc_time_stamp() << std::endl;
            ph=tlm::END_RESP;
			return tlm::TLM_UPDATED;
		}
	    else if(ph ==tlm::END_REQ)
	    { 
//			std::cout << "TLM BEHAVIOR: received END_REQ and returning TLM_ACCEPTED at time " << sc_core::sc_time_stamp() << std::endl;
			if (needRetry)
			{
				setCurTick(sc_core::sc_time_stamp().value());
				trans.release();
				needRetry=false;
				slavePort->sendRetry();
			}
	    }
		else if(ph== amba::END_DATA )
		{
//			std::cout << "TLM BEHAVIOR: received END_DATA and returning TLM_ACCEPTED at time " << sc_core::sc_time_stamp() << std::endl;
			if (need_wenable_event)
			{
				need_wenable_event=false;
            	wenable_event.notify();
			}
			return tlm::TLM_ACCEPTED;
		}
		else
				assert("Unexpected phase returned from AXI slave.");	
		return returnVal;
}