virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { tlm::tlm_command cmd = trans.get_command(); unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int bel = trans.get_byte_enable_length(); my_extension* ext; trans.get_extension(ext); assert( ext ); assert( len == ext->len ); assert( bel == ext->bel ); for (unsigned int i = 0; i < bel; i++) assert( byt[i] == ext->byt[i] ); for (unsigned int i = 0; i < len; i++) assert( ptr[i] == ext->ptr[i] ); if (cmd == tlm::TLM_READ_COMMAND) { for (unsigned int i = 0; i < len; i++) { data[i] = rand() % 256; ptr[i] = data[i]; } ext->ptr = data; } trans.set_dmi_allowed( true ); trans.set_response_status( tlm::TLM_OK_RESPONSE ); }
//Method used for receiving acknowledgements of interrupts; the ack consists of //uninteresting data and the address corresponds to the interrupt signal to //be lowered //As a response, I lower the interrupt by sending a NULL pointer on the init_socket void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) { if(this->lastIrq < 0) { THROW_EXCEPTION("Error, lowering an interrupt which hasn't been raised yet!!"); } tlm::tlm_command cmd = trans.get_command(); sc_dt::uint64 adr = trans.get_address(); unsigned char* ptr = trans.get_data_ptr(); if(trans.get_command() == tlm::TLM_READ_COMMAND) { THROW_EXCEPTION("Error, the read request is not currently supported by external PINs"); } else if(cmd == tlm::TLM_WRITE_COMMAND) { if(this->lastIrq != adr) { THROW_EXCEPTION("Error, lowering interrupt " << std::hex << std::showbase << (unsigned)adr << " while " << std::hex << std::showbase << this->lastIrq << " was raised"); } else { //finally I can really lower the interrupt: I send 0 on //the initSocked unsigned char data = 0; trans.set_data_ptr(&data); trans.set_dmi_allowed(false); trans.set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); sc_time delay; this->init_socket->b_transport(trans, delay); if(trans.is_response_error()) { std::string errorStr("Error in b_transport of PIN, response status = " + trans.get_response_string()); SC_REPORT_ERROR("TLM-2", errorStr.c_str()); } this->lastIrq = -1; } } trans.set_response_status(tlm::TLM_OK_RESPONSE); }
inline void lt_target::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay){ sc_dt::uint64 adr = trans.get_address() / 4; unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int blen = trans.get_byte_enable_length(); unsigned int wid = trans.get_streaming_width(); if (adr >= sc_dt::uint64(mem_size) ) { trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE ); return; } if ( wid < len ) { trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE ); return; } if (trans.is_read()) { delay += rd_latency; if ( byt != 0 ) { for ( unsigned int i = 0; i < len; i++ ) if ( byt[i % blen] == TLM_BYTE_ENABLED ){ ptr[i] = (mem[adr+i/4] >> ((i&3)*8)) & 0xFF; } } else {
// TLM-2 blocking transport method virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { 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(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int wid = trans.get_streaming_width(); // Obliged to check address range and check for unsupported features, // i.e. byte enables, streaming, and bursts // Can ignore DMI hint and extensions // Using the SystemC report handler is an acceptable way of signalling an error if (adr >= sc_dt::uint64(SIZE) || byt != 0 || len > 4 || wid < len) SC_REPORT_ERROR("TLM-2", "Target does not support given generic payload transaction"); // Obliged to implement read and write commands if ( cmd == tlm::TLM_READ_COMMAND ){ memcpy(ptr, &mem[adr], len); cout << "Data: " << dec << mem[adr] << " is read from Address: " << dec << adr << endl; } else if ( cmd == tlm::TLM_WRITE_COMMAND ){ memcpy(&mem[adr], ptr, len); cout << "Data: " << dec << mem[adr] << " is written into Address: " << dec << adr << endl; } // Obliged to set response status to indicate successful completion trans.set_response_status( tlm::TLM_OK_RESPONSE ); }
//============================================================================== // dbg_transport implementation calls from initiators // //============================================================================= unsigned int model_jxz_tlm::entry_transport_dbg (tlm::tlm_generic_payload &gp) { tlm::tlm_command command = gp.get_command();// memory command unsigned char *data = gp.get_data_ptr();// data pointer unsigned int length = gp.get_data_length();// data length gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); return 0; }
//============================================================================== // b_transport implementation calls from initiators // //============================================================================= void model_jxz_tlm::entry_b_transport (tlm::tlm_generic_payload &gp, sc_core:: sc_time &delay_time) { tlm::tlm_command command = gp.get_command();// memory command unsigned char *data = gp.get_data_ptr();// data pointer unsigned int length = gp.get_data_length();// data length unsigned long timefactor = ((length+BUSWIDTHBYTE-1)/BUSWIDTHBYTE)-1; bool write_ok = true; gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); return; }
// TLM-2 blocking transport method virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { tlm::tlm_command cmd = trans.get_command(); sc_dt::uint64 adr = trans.get_address() / 4; unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int wid = trans.get_streaming_width(); // Obliged to check address range and check for unsupported features, // i.e. byte enables, streaming, and bursts // Can ignore extensions // ********************************************* // Generate the appropriate error response // ********************************************* if (adr >= sc_dt::uint64(SIZE)) { trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE ); return; } if (byt != 0) { trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE ); return; } if (len > 4 || wid < len) { trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE ); return; } // Obliged to implement read and write commands if ( cmd == tlm::TLM_READ_COMMAND ) memcpy(ptr, &mem[adr], len); else if ( cmd == tlm::TLM_WRITE_COMMAND ) memcpy(&mem[adr], ptr, len); // Illustrates that b_transport may block wait(delay); // Reset timing annotation after waiting delay = SC_ZERO_TIME; // ********************************************* // Set DMI hint to indicated that DMI is supported // ********************************************* trans.set_dmi_allowed(true); // Obliged to set response status to indicate successful completion trans.set_response_status( tlm::TLM_OK_RESPONSE ); }
void memory::operation ( tlm::tlm_generic_payload &gp , sc_core::sc_time &delay_time ///< transaction delay ) { sc_dt::uint64 address = gp.get_address(); // memory address tlm::tlm_command command = gp.get_command(); // memory command unsigned char *data = gp.get_data_ptr(); // data pointer unsigned int length = gp.get_data_length(); // data length tlm::tlm_response_status response_status = check_address(gp) ? tlm::TLM_OK_RESPONSE : tlm::TLM_ADDRESS_ERROR_RESPONSE; if (gp.get_byte_enable_ptr()) { gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); } else if (gp.get_streaming_width() != gp.get_data_length()) { gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); } switch (command) { default: { gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); break; } case tlm::TLM_WRITE_COMMAND: { if (response_status == tlm::TLM_OK_RESPONSE) { for (unsigned int i = 0; i < length; i++) { m_memory[address++] = data[i]; // move the data to memory } } break; } case tlm::TLM_READ_COMMAND: { if (response_status == tlm::TLM_OK_RESPONSE) { for (unsigned int i = 0; i < length; i++) { data[i] = m_memory[address++]; // move the data from memory } } break; } } // end switch gp.set_response_status(response_status); }
void leon3_funclt_trap::IntrTLMPort_32::b_transport( int tag, tlm::tlm_generic_payload \ & trans, sc_time & delay ){ unsigned char* ptr = trans.get_data_ptr(); sc_dt::uint64 adr = trans.get_address(); if(*ptr == 0){ //Lower the interrupt this->irqSignal = -1; } else{ //Raise the interrupt this->irqSignal = adr; } trans.set_response_status(tlm::TLM_OK_RESPONSE); }
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: status = send_end_req(trans); break; case tlm::END_RESP: //std::cerr << "tlm::END_RESP in memory peq_cb" << std::endl; this->transactionInProgress = false; this->transactionCompleted.notify(); 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){ for(int i = 0; i < len; i++, ptr++) *ptr = this->mem[adr + i]; } else if(cmd == tlm::TLM_WRITE_COMMAND){ for(int i = 0; i < len; i++, ptr++) this->mem[adr + i] = *ptr; } 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 send_response(trans); //std::cerr << "Memory reading address in memory " << std::hex << std::showbase << adr << std::endl; } break; } }
// Data interface to functional part of the model void mmu_cache::exec_data(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay, bool is_dbg) { // Vars for payload decoding tlm::tlm_command cmd = trans.get_command(); sc_dt::uint64 addr = trans.get_address(); unsigned char * ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); // Log number of reads and writes for power monitoring if (m_pow_mon) { if (cmd == tlm::TLM_READ_COMMAND) { dyn_reads += (len >> 2) + 1; } else {
virtual unsigned int transport_dbg(tlm::tlm_generic_payload & trans) { tlm::tlm_command cmd = trans.get_command(); sc_dt::uint64 adr = trans.get_address() / 4; unsigned char* ptr = trans.get_data_ptr(); unsigned int len = trans.get_data_length(); // Calculate the number of bytes to be actually copied unsigned int num_bytes = (len < (SIZE - adr) * 4) ? len : (SIZE - adr) * 4; if (cmd == tlm::TLM_READ_COMMAND) memcpy(ptr, &mem[adr], num_bytes); else if (cmd == tlm::TLM_WRITE_COMMAND) memcpy(&mem[adr], ptr, num_bytes); return num_bytes; }
void DNP_master_device::master_cb( tlm::tlm_generic_payload &arg_Req, sc_time& delay) { uint32_t addr = (uint32_t) arg_Req.get_address(); uint32_t len = (uint32_t) arg_Req.get_data_length(); uint8_t *data_ptr = (uint8_t *) arg_Req.get_data_ptr(); crt_trans_id ++ ; memset(recvd_data, 0, sizeof(recvd_data)); if (arg_Req.is_read()){ /* * Read command */ DPRINTF("R @ 0x%08x(%d) <%d>\n", addr, len, crt_trans_id); for(uint32_t i = 0; i < len; i+=4){ #ifdef DEBUG_DNP_MASTER uint32_t *p = (uint32_t *)recvd_data; #endif send_req(crt_trans_id, (addr + i), recvd_data, 4, false); wait(rsp_rcvd_ev); memcpy((data_ptr + i), (uint32_t *)recvd_data, 4); DPRINTF("R @ 0x%08x -- %08x \n", (addr + i), *p); } }else{ /* * Write command */ DPRINTF("W @ 0x%08x(%d) <%d>\n", addr, len, crt_trans_id); for (uint32_t i = 0; i < len; i+=4){ #ifdef DEBUG_DNP_MASTER uint32_t *p = (uint32_t *)(data_ptr + i); #endif DPRINTF("W @ 0x%08x -- %08x\n", (addr + i), *p); send_req(crt_trans_id, (addr + i), (data_ptr + i), 4, true); wait(rsp_rcvd_ev); } } arg_Req.set_response_status(tlm::TLM_OK_RESPONSE); }
// TLM-2 debug transaction method unsigned int transport_dbg(int tag, tlm::tlm_generic_payload& trans){ 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){ for(int i = 0; i < len; i++, ptr++) *ptr = this->mem[adr + i]; } else if(cmd == tlm::TLM_WRITE_COMMAND){ for(int i = 0; i < len; i++, ptr++) this->mem[adr + i] = *ptr; } return len; }
// 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(); }
///////////////////////////////////////////////////////////////////////////////////// // Interface function called when receiving an IRQ event ///////////////////////////////////////////////////////////////////////////////////// tmpl (tlm::tlm_sync_enum)::irq_nb_transport_fw ( int id, tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_core::sc_time &time) { uint8_t value = payload.get_data_ptr()[0]; #ifdef SOCLIB_MODULE_DEBUG std::cout << "[" << name() << "] time = " << std::dec << time.value() << " receive Interrupt " << id << " / value = " << (int)value << std::endl; #endif assert(time.value() >= m_pending_time[id].value() && "IRQ event received with a wrong date"); m_pending_irq[id] = ( value != 0 ); m_pending_time[id] = time; return tlm::TLM_COMPLETED; }
// TLM-2 blocking transport method virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { 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(); unsigned char* byt = trans.get_byte_enable_ptr(); unsigned int wid = trans.get_streaming_width(); // Obliged to check address range and check for unsupported features, // i.e. byte enables, streaming, and bursts // Can ignore DMI hint and extensions // Using the SystemC report handler is an acceptable way of signalling an error if (adr >= sc_dt::uint64(SIZE) * 4 || adr % 4) { trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE ); return; } else if (byt != 0) { trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE ); return; } else if (len > 4 || wid < len) { trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE ); return; } // Obliged to implement read and write commands if ( cmd == tlm::TLM_READ_COMMAND ) memcpy(ptr, &mem[adr/4], len); else if ( cmd == tlm::TLM_WRITE_COMMAND ) memcpy(&mem[adr/4], ptr, len); // Obliged to set response status to indicate successful completion trans.set_response_status( tlm::TLM_OK_RESPONSE ); }
//! @param payload The generic TLM payload //! @param delay How far the initiator is beyond baseline SystemC time. //! Ignored here. // ---------------------------------------------------------------------------- void LoggerSC::loggerReadWrite( tlm::tlm_generic_payload &payload, sc_core::sc_time &delay ) { // Break out the address, mask and data pointer. tlm::tlm_command comm = payload.get_command(); sc_dt::uint64 addr = payload.get_address(); unsigned char *maskPtr = payload.get_byte_enable_ptr(); unsigned char *dataPtr = payload.get_data_ptr(); // Record the payload fields (data only if it's a write) const char *commStr; switch( comm ) { case tlm::TLM_READ_COMMAND: commStr = "Read"; break; case tlm::TLM_WRITE_COMMAND: commStr = "Write"; break; case tlm::TLM_IGNORE_COMMAND: commStr = "Ignore"; break; default: commStr = "Unknown command"; break; } std::cout << "Logging" << std::endl; std::cout << " Command: " << commStr << std::endl; std::cout << " Address: 0x" << std::setw( 8 ) << std::setfill( '0' ) <<std::hex << (uint64_t)addr << std::endl; std::cout << " Byte enables: 0x" << std::setw( 8 ) << std::setfill( '0' ) <<std::hex << *((uint32_t *)maskPtr) << std::endl; if( tlm::TLM_WRITE_COMMAND == comm ) { std::cout << " Data: 0x" << std::setw( 8 ) << std::setfill( '0' ) <<std::hex << *((uint32_t *)dataPtr) << std::endl; } std::cout << std::endl; payload.set_response_status( tlm::TLM_OK_RESPONSE ); // Always OK } // loggerReadWrite()
unsigned int memory::debug ( tlm::tlm_generic_payload &gp , sc_core::sc_time &delay_time ///< transaction delay ) { sc_dt::uint64 address = gp.get_address(); // memory address tlm::tlm_command command = gp.get_command(); // memory command unsigned char *data = gp.get_data_ptr(); // data pointer unsigned int length = gp.get_data_length(); // data length bool ok = check_address(gp); if(ok) { switch (command) { case tlm::TLM_WRITE_COMMAND: for (unsigned int i = 0; i < length; i++) { m_memory[address++] = data[i]; // move the data to memory } gp.set_response_status(tlm::TLM_OK_RESPONSE); break; case tlm::TLM_READ_COMMAND: for (unsigned int i = 0; i < length; i++) { data[i] = m_memory[address++]; // move the data from memory } gp.set_response_status(tlm::TLM_OK_RESPONSE); break; default: ok = 0; break; } } // end switch return ok ? length : 0; }
//===================================================================== /// @fn dmi_memory::operation // /// @brief DMI read and write processing // /// @details /// This routine implements dmi based read and write operations // //===================================================================== void dmi_memory::operation ( tlm::tlm_generic_payload &gp , sc_core::sc_time &delay ///< transaction delay ) { std::ostringstream msg; msg.str(""); m_address = gp.get_address(); m_data = gp.get_data_ptr(); ///< data pointer m_length = gp.get_data_length(); ///< data length m_command = gp.get_command(); m_is_dmi_flag = false; gp.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); if (is_address_dmi(gp) == false ) { msg << "Iniiator:" << m_ID << "A GP with an address not in the allowed DMI ranges has been received" << endl << " " << "Use check_status before passing a gp to operation"; REPORT_INFO(filename, __FUNCTION__, msg.str()); gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); // Need a different error } else { m_offset = m_address - m_dmi_base_address; switch (m_command) { case tlm::TLM_WRITE_COMMAND: { for (unsigned int i = 0; i < m_length; i++) { m_dmi_ptr[m_offset + i] = m_data[i]; } gp.set_response_status(tlm::TLM_OK_RESPONSE); delay = delay + m_dmi_write_latency; // update time report::print(m_ID, gp, filename); break; } case tlm::TLM_READ_COMMAND: { // clear read buffer for (unsigned int i = 0; i < m_length; i++) { m_data[i] = m_dmi_ptr [m_offset + i]; } gp.set_response_status(tlm::TLM_OK_RESPONSE); delay = delay + m_dmi_read_latency; // update time report::print(m_ID, gp, filename); break; } default: { msg << "Target: " << m_ID << " Unknown GP command that could be ignorable"; REPORT_WARNING(filename, __FUNCTION__, msg.str()); gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); break; } }//end switch } return; //============================================================================== } // end memory_operation
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; } } }
//////////////////////////////////////////////////////////////////////////////////// // Interface function used when receiving a VCI command on the target port // As the dated transactions on the VCI target port are used to update the local // time when all DMA channels are IDLE, this component requires periodical // NULL messages from the interconnect. //////////////////////////////////////////////////////////////////////////////////// tmpl(tlm::tlm_sync_enum)::nb_transport_fw ( tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_core::sc_time &time) { size_t cell; size_t reg; size_t channel; soclib_payload_extension* extension_pointer; payload.get_extension(extension_pointer); // Compute global state bool all_idle = true; for( size_t k = 0 ; k < m_channels ; k++ ) { if( m_state[k] != STATE_IDLE ) all_idle = false; } // update local time if all channels IDLE if ( all_idle and (m_pdes_local_time->get().value() < time.value()) ) { m_pdes_local_time->set( time ); } // No other action on NULL messages if ( extension_pointer->is_null_message() ) { #if SOCLIB_MODULE_DEBUG std::cout << "[" << name() << "] time = " << time.value() << " Receive NULL message" << std::endl; #endif return tlm::TLM_COMPLETED; } // address and length checking for a VCI command bool one_flit = (payload.get_data_length() == 4); addr_t address = payload.get_address(); if ( m_segment.contains(address) && one_flit ) { cell = (size_t)((address - m_segment.baseAddress()) >> 2); reg = cell % DMA_SPAN; channel = cell / DMA_SPAN; // checking channel overflow if ( channel < m_channels ) payload.set_response_status(tlm::TLM_OK_RESPONSE); else payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); if ( extension_pointer->get_command() == VCI_READ_COMMAND ) { #if SOCLIB_MODULE_DEBUG std::cout << "[" << name() << "] time = " << time.value() << " Receive VCI read command : address = " << std::hex << address << " / channel = " << std::dec << channel << " / reg = " << reg << std::endl; #endif if ( reg == DMA_SRC ) { utoa( m_source[channel], payload.get_data_ptr(), 0 ); } else if ( reg == DMA_DST ) { utoa( m_destination[channel], payload.get_data_ptr(), 0 ); } else if ( reg == DMA_LEN ) { utoa( m_state[channel], payload.get_data_ptr(), 0 ); } else if ( reg == DMA_IRQ_DISABLED ) { utoa( (int)(m_irq_disabled[channel]), payload.get_data_ptr(), 0 ); } else payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); } // end read else if (extension_pointer->get_command() == VCI_WRITE_COMMAND) { uint32_t data = atou(payload.get_data_ptr(), 0); #if SOCLIB_MODULE_DEBUG std::cout << "[" << name() << "] time = " << time.value() << " Receive VCI write command : address = " << std::hex << address << " / channel = " << std::dec << channel << " / reg = " << reg << " / data = " << data << std::endl; #endif // configuration command other than soft reset // are ignored when the DMA channel is active if ( reg == DMA_RESET ) { m_stop[channel] = true; } else if ( m_state[channel] != STATE_IDLE ) { if ( reg == DMA_SRC ) m_source[channel] = data; else if ( reg == DMA_DST ) m_destination[channel] = data; else if ( reg == DMA_LEN ) { m_length[channel] = data; m_stop[channel] = false; m_event.notify(); } else if ( cell == DMA_IRQ_DISABLED ) m_irq_disabled[channel] = (data != 0); else payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); } else { std::cout << name() << " warning: receiving a new command while busy, ignored" << std::endl; } } // end if write else // illegal command { payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); } } // end if legal address
//============================================================================== /// @fn memory::operation // /// @brief performs read and write // /// @details /// This routine implements the read and write operations. including /// checking for byte_enable and streaming that are not implemented // //============================================================================== void memory::operation ( tlm::tlm_generic_payload &gp , sc_core::sc_time &delay_time ///< transaction delay ) { /// Access the required attributes from the payload sc_dt::uint64 address = gp.get_address(); // memory address tlm::tlm_command command = gp.get_command(); // memory command unsigned char *data = gp.get_data_ptr(); // data pointer unsigned int length = gp.get_data_length(); // data length std::ostringstream msg; msg.str(""); tlm::tlm_response_status response_status = check_address(gp); if (gp.get_byte_enable_ptr()) { gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); } else if (gp.get_streaming_width() != gp.get_data_length()) { gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); } switch (command) { default: { if (m_previous_warning == false) { msg << "Target: " << m_ID << " Unsupported Command Extension"; REPORT_INFO(filename, __FUNCTION__, msg.str()); gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); delay_time = sc_core::SC_ZERO_TIME; m_previous_warning = true; } break; } /// Setup a TLM_WRITE_COMMAND Informational Message and Write the Data from /// the Generic Payload Data pointer to Memory /// case tlm::TLM_WRITE_COMMAND: { if (response_status == tlm::TLM_OK_RESPONSE) { for (unsigned int i = 0; i < length; i++) { m_memory[address++] = data[i]; // move the data to memory } delay_time = delay_time + m_write_delay; report::print(m_ID, gp, filename); } break; } case tlm::TLM_READ_COMMAND: { if (response_status == tlm::TLM_OK_RESPONSE) { for (unsigned int i = 0; i < length; i++) { data[i] = m_memory[address++]; // move the data to memory } delay_time = delay_time + m_read_delay; report::print(m_ID, gp, filename); } break; } } // end switch gp.set_response_status(response_status); return; } // end memory_operation
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; }
// Instruction interface to functional part of the model void mmu_cache::exec_instr(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay, bool is_dbg) { // Vars for payload decoding tlm::tlm_command cmd = trans.get_command(); sc_dt::uint64 addr = trans.get_address(); unsigned char * ptr = trans.get_data_ptr(); // Log instruction reads for power monitoring if (m_pow_mon) { dyn_reads += (trans.get_data_length() >> 2) + 1; } // Extract extension icio_payload_extension * iext; trans.get_extension(iext); unsigned int *debug; unsigned int flush; // Check/extract instruction payload extension if (iext!=NULL) { debug = iext->debug; flush = iext->flush; } else { // No iext debug = NULL; flush = 0; v::error << name() << "IEXT Payload extension missing" << v::endl; } // Flush instruction if (flush) { v::debug << name() << "Received flush instruction - flushing both caches" << v::endl; // Simultaneous flush of both caches icache->flush(&delay, debug, is_dbg); dcache->flush(&delay, debug, is_dbg); trans.set_response_status(tlm::TLM_OK_RESPONSE); return; } if (cmd == tlm::TLM_READ_COMMAND) { assert( 1 ); // fix asi -> priv / unpriv mmu_cache_base::exec_instr(addr, ptr, 0x8, debug, flush, delay, is_dbg); // ToDo: fix ASI! 0x8 -> unprivileged instruction // Set response status trans.set_response_status(tlm::TLM_OK_RESPONSE); } else { v::error << name() << " Command not valid for instruction cache (tlm_write)" << v::endl; // Set response status trans.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); } }