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; }
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(); } }
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; }
// 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(); }
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; } }
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; }