SimpleLTInitiator_ext.h revision 12855
112855Sgabeblack@google.com/***************************************************************************** 212855Sgabeblack@google.com 312855Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412855Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 512855Sgabeblack@google.com with this work for additional information regarding copyright ownership. 612855Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 712855Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 812855Sgabeblack@google.com License. You may obtain a copy of the License at 912855Sgabeblack@google.com 1012855Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1112855Sgabeblack@google.com 1212855Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1312855Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1412855Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512855Sgabeblack@google.com implied. See the License for the specific language governing 1612855Sgabeblack@google.com permissions and limitations under the License. 1712855Sgabeblack@google.com 1812855Sgabeblack@google.com *****************************************************************************/ 1912855Sgabeblack@google.com 2012855Sgabeblack@google.com#ifndef __SIMPLE_LT_INITIATOR_EXT_H__ 2112855Sgabeblack@google.com#define __SIMPLE_LT_INITIATOR_EXT_H__ 2212855Sgabeblack@google.com 2312855Sgabeblack@google.com#include "tlm.h" 2412855Sgabeblack@google.com#include "tlm_utils/simple_initiator_socket.h" 2512855Sgabeblack@google.com#include "my_extension.h" 2612855Sgabeblack@google.com 2712855Sgabeblack@google.com#include <systemc> 2812855Sgabeblack@google.com#include <cassert> 2912855Sgabeblack@google.com#include <iostream> 3012855Sgabeblack@google.com#include <iomanip> 3112855Sgabeblack@google.com#include <map> 3212855Sgabeblack@google.com 3312855Sgabeblack@google.comclass SimpleLTInitiator_ext : public sc_core::sc_module 3412855Sgabeblack@google.com{ 3512855Sgabeblack@google.compublic: 3612855Sgabeblack@google.com typedef tlm::tlm_generic_payload transaction_type; 3712855Sgabeblack@google.com typedef tlm::tlm_dmi dmi_type; 3812855Sgabeblack@google.com typedef tlm::tlm_phase phase_type; 3912855Sgabeblack@google.com typedef tlm::tlm_sync_enum sync_enum_type; 4012855Sgabeblack@google.com typedef tlm_utils::simple_initiator_socket<SimpleLTInitiator_ext, 32, 4112855Sgabeblack@google.com my_extended_payload_types> initiator_socket_type; 4212855Sgabeblack@google.com 4312855Sgabeblack@google.compublic: 4412855Sgabeblack@google.com initiator_socket_type socket; 4512855Sgabeblack@google.com 4612855Sgabeblack@google.compublic: 4712855Sgabeblack@google.com SC_HAS_PROCESS(SimpleLTInitiator_ext); 4812855Sgabeblack@google.com SimpleLTInitiator_ext(sc_core::sc_module_name name, 4912855Sgabeblack@google.com unsigned int nrOfTransactions = 0x5, 5012855Sgabeblack@google.com unsigned int baseAddress = 0x0) : 5112855Sgabeblack@google.com sc_core::sc_module(name), 5212855Sgabeblack@google.com socket("socket"), 5312855Sgabeblack@google.com mNrOfTransactions(nrOfTransactions), 5412855Sgabeblack@google.com mBaseAddress(baseAddress), 5512855Sgabeblack@google.com mTransactionCount(0) 5612855Sgabeblack@google.com { 5712855Sgabeblack@google.com invalidate(mDMIData); 5812855Sgabeblack@google.com 5912855Sgabeblack@google.com // register nb_transport method 6012855Sgabeblack@google.com socket.register_nb_transport_bw(this, &SimpleLTInitiator_ext::myNBTransport); 6112855Sgabeblack@google.com socket.register_invalidate_direct_mem_ptr(this, &SimpleLTInitiator_ext::invalidate_direct_mem_ptr); 6212855Sgabeblack@google.com 6312855Sgabeblack@google.com // Initiator thread 6412855Sgabeblack@google.com SC_THREAD(run); 6512855Sgabeblack@google.com 6612855Sgabeblack@google.com } 6712855Sgabeblack@google.com 6812855Sgabeblack@google.com bool initTransaction(transaction_type& trans) 6912855Sgabeblack@google.com { 7012855Sgabeblack@google.com // initialize DMI hint: 7112855Sgabeblack@google.com trans.set_dmi_allowed(false); 7212855Sgabeblack@google.com 7312855Sgabeblack@google.com if (mTransactionCount < mNrOfTransactions) 7412855Sgabeblack@google.com { 7512855Sgabeblack@google.com trans.set_address(mBaseAddress + 4*mTransactionCount); 7612855Sgabeblack@google.com mData = mTransactionCount; 7712855Sgabeblack@google.com trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 7812855Sgabeblack@google.com trans.set_command(tlm::TLM_WRITE_COMMAND); 7912855Sgabeblack@google.com 8012855Sgabeblack@google.com } 8112855Sgabeblack@google.com else if (mTransactionCount < 2 * mNrOfTransactions) 8212855Sgabeblack@google.com { 8312855Sgabeblack@google.com trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); 8412855Sgabeblack@google.com mData = 0; 8512855Sgabeblack@google.com trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 8612855Sgabeblack@google.com trans.set_command(tlm::TLM_READ_COMMAND); 8712855Sgabeblack@google.com 8812855Sgabeblack@google.com } 8912855Sgabeblack@google.com else 9012855Sgabeblack@google.com { 9112855Sgabeblack@google.com return false; 9212855Sgabeblack@google.com } 9312855Sgabeblack@google.com 9412855Sgabeblack@google.com ++mTransactionCount; 9512855Sgabeblack@google.com return true; 9612855Sgabeblack@google.com } 9712855Sgabeblack@google.com 9812855Sgabeblack@google.com void logStartTransation(transaction_type& trans) 9912855Sgabeblack@google.com { 10012855Sgabeblack@google.com if (trans.get_command() == tlm::TLM_WRITE_COMMAND) 10112855Sgabeblack@google.com { 10212855Sgabeblack@google.com std::cout << name() << ": Send write request: A = 0x" 10312855Sgabeblack@google.com << std::hex << (unsigned int)trans.get_address() 10412855Sgabeblack@google.com << ", D = 0x" << mData << std::dec 10512855Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 10612855Sgabeblack@google.com 10712855Sgabeblack@google.com } 10812855Sgabeblack@google.com else 10912855Sgabeblack@google.com { 11012855Sgabeblack@google.com std::cout << name() << ": Send read request: A = 0x" 11112855Sgabeblack@google.com << std::hex << (unsigned int)trans.get_address() 11212855Sgabeblack@google.com << std::dec 11312855Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 11412855Sgabeblack@google.com } 11512855Sgabeblack@google.com } 11612855Sgabeblack@google.com 11712855Sgabeblack@google.com void logEndTransaction(transaction_type& trans) 11812855Sgabeblack@google.com { 11912855Sgabeblack@google.com if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { 12012855Sgabeblack@google.com std::cout << name() << ": Received error response @ " 12112855Sgabeblack@google.com << sc_core::sc_time_stamp() << std::endl; 12212855Sgabeblack@google.com } 12312855Sgabeblack@google.com else 12412855Sgabeblack@google.com { 12512855Sgabeblack@google.com std::cout << name() << ": Received ok response"; 12612855Sgabeblack@google.com if (trans.get_command() == tlm::TLM_READ_COMMAND) { 12712855Sgabeblack@google.com std::cout << ": D = 0x" << std::hex << mData << std::dec; 12812855Sgabeblack@google.com } 12912855Sgabeblack@google.com std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; 13012855Sgabeblack@google.com } 13112855Sgabeblack@google.com } 13212855Sgabeblack@google.com 13312855Sgabeblack@google.com void run() 13412855Sgabeblack@google.com { 13512855Sgabeblack@google.com transaction_type trans; 13612855Sgabeblack@google.com phase_type phase; 13712855Sgabeblack@google.com sc_core::sc_time t; 13812855Sgabeblack@google.com // make sure that our transaction has the proper extension: 13912855Sgabeblack@google.com my_extension* tmp_ext = new my_extension(); 14012855Sgabeblack@google.com tmp_ext->m_data = 11; 14112855Sgabeblack@google.com 14212855Sgabeblack@google.com trans.set_extension(tmp_ext); 14312855Sgabeblack@google.com 14412855Sgabeblack@google.com while (initTransaction(trans)) 14512855Sgabeblack@google.com { 14612855Sgabeblack@google.com // Create transaction and initialise phase and t 14712855Sgabeblack@google.com phase = tlm::BEGIN_REQ; 14812855Sgabeblack@google.com t = sc_core::SC_ZERO_TIME; 14912855Sgabeblack@google.com 15012855Sgabeblack@google.com logStartTransation(trans); 15112855Sgabeblack@google.com /////////////////////////////////////////////////////////// 15212855Sgabeblack@google.com // DMI handling: 15312855Sgabeblack@google.com // We use the DMI hint to check if it makes sense to ask for 15412855Sgabeblack@google.com // DMI pointers. The pattern is: 15512855Sgabeblack@google.com // - if the address is covered by a DMI region do a DMI access 15612855Sgabeblack@google.com // - otherwise do a normal transaction 15712855Sgabeblack@google.com // -> check if we get a DMI hint and acquire the DMI pointers if it 15812855Sgabeblack@google.com // is set 15912855Sgabeblack@google.com /////////////////////////////////////////////////////////// 16012855Sgabeblack@google.com 16112855Sgabeblack@google.com // Check if the address is covered by our DMI region 16212855Sgabeblack@google.com if ( (trans.get_address() >= mDMIData.get_start_address()) && 16312855Sgabeblack@google.com (trans.get_address() <= mDMIData.get_end_address()) ) 16412855Sgabeblack@google.com { 16512855Sgabeblack@google.com // We can handle the data here. As the logEndTransaction is 16612855Sgabeblack@google.com // assuming something to happen in the data structure, we really 16712855Sgabeblack@google.com // need to do this: 16812855Sgabeblack@google.com trans.set_response_status(tlm::TLM_OK_RESPONSE); 16912855Sgabeblack@google.com sc_dt::uint64 tmp = trans.get_address() - mDMIData.get_start_address(); 17012855Sgabeblack@google.com if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 17112855Sgabeblack@google.com *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp] = mData; 17212855Sgabeblack@google.com 17312855Sgabeblack@google.com } else { 17412855Sgabeblack@google.com mData = *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp]; 17512855Sgabeblack@google.com } 17612855Sgabeblack@google.com 17712855Sgabeblack@google.com // Do the wait immediately. Note that doing the wait here eats 17812855Sgabeblack@google.com // almost all the performance anyway, so we only gain something 17912855Sgabeblack@google.com // if we're using temporal decoupling. 18012855Sgabeblack@google.com if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 18112855Sgabeblack@google.com wait(mDMIData.get_write_latency()); 18212855Sgabeblack@google.com 18312855Sgabeblack@google.com } else { 18412855Sgabeblack@google.com wait(mDMIData.get_read_latency()); 18512855Sgabeblack@google.com } 18612855Sgabeblack@google.com 18712855Sgabeblack@google.com logEndTransaction(trans); 18812855Sgabeblack@google.com 18912855Sgabeblack@google.com } else { // we need a full transaction 19012855Sgabeblack@google.com switch (socket->nb_transport_fw(trans, phase, t)) { 19112855Sgabeblack@google.com case tlm::TLM_COMPLETED: 19212855Sgabeblack@google.com // Transaction Finished, wait for the returned delay 19312855Sgabeblack@google.com wait(t); 19412855Sgabeblack@google.com break; 19512855Sgabeblack@google.com 19612855Sgabeblack@google.com case tlm::TLM_ACCEPTED: 19712855Sgabeblack@google.com case tlm::TLM_UPDATED: 19812855Sgabeblack@google.com // Transaction not yet finished, wait for the end of it 19912855Sgabeblack@google.com wait(mEndEvent); 20012855Sgabeblack@google.com break; 20112855Sgabeblack@google.com 20212855Sgabeblack@google.com default: 20312855Sgabeblack@google.com sc_assert(0); exit(1); 20412855Sgabeblack@google.com }; 20512855Sgabeblack@google.com 20612855Sgabeblack@google.com logEndTransaction(trans); 20712855Sgabeblack@google.com 20812855Sgabeblack@google.com // Acquire DMI pointer if one is available: 20912855Sgabeblack@google.com if (trans.is_dmi_allowed()) 21012855Sgabeblack@google.com { 21112855Sgabeblack@google.com trans.set_write(); 21212855Sgabeblack@google.com dmi_type tmp; 21312855Sgabeblack@google.com if (socket->get_direct_mem_ptr(trans, 21412855Sgabeblack@google.com tmp)) 21512855Sgabeblack@google.com { 21612855Sgabeblack@google.com // FIXME: No support for separate read/write ranges 21712855Sgabeblack@google.com sc_assert(tmp.is_read_write_allowed()); 21812855Sgabeblack@google.com mDMIData = tmp; 21912855Sgabeblack@google.com } 22012855Sgabeblack@google.com } 22112855Sgabeblack@google.com } 22212855Sgabeblack@google.com } 22312855Sgabeblack@google.com delete tmp_ext; 22412855Sgabeblack@google.com wait(); 22512855Sgabeblack@google.com 22612855Sgabeblack@google.com } 22712855Sgabeblack@google.com 22812855Sgabeblack@google.com sync_enum_type myNBTransport(transaction_type& trans, 22912855Sgabeblack@google.com phase_type& phase, 23012855Sgabeblack@google.com sc_core::sc_time& t) 23112855Sgabeblack@google.com { 23212855Sgabeblack@google.com switch (phase) { 23312855Sgabeblack@google.com case tlm::END_REQ: 23412855Sgabeblack@google.com // Request phase ended 23512855Sgabeblack@google.com return tlm::TLM_ACCEPTED; 23612855Sgabeblack@google.com 23712855Sgabeblack@google.com case tlm::BEGIN_RESP: 23812855Sgabeblack@google.com sc_assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? 23912855Sgabeblack@google.com mEndEvent.notify(t); 24012855Sgabeblack@google.com // Not needed to update the phase if true is returned 24112855Sgabeblack@google.com return tlm::TLM_COMPLETED; 24212855Sgabeblack@google.com 24312855Sgabeblack@google.com case tlm::BEGIN_REQ: // fall-through 24412855Sgabeblack@google.com case tlm::END_RESP: // fall-through 24512855Sgabeblack@google.com default: 24612855Sgabeblack@google.com // A target should never call nb_transport with these phases 24712855Sgabeblack@google.com sc_assert(0); exit(1); 24812855Sgabeblack@google.com// return tlm::TLM_COMPLETED; //unreachable code 24912855Sgabeblack@google.com }; 25012855Sgabeblack@google.com } 25112855Sgabeblack@google.com 25212855Sgabeblack@google.com void invalidate(dmi_type& dmiData) 25312855Sgabeblack@google.com { 25412855Sgabeblack@google.com dmiData.set_start_address(1); 25512855Sgabeblack@google.com dmiData.set_end_address(0); 25612855Sgabeblack@google.com } 25712855Sgabeblack@google.com 25812855Sgabeblack@google.com // Invalidate DMI pointer(s) 25912855Sgabeblack@google.com void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, 26012855Sgabeblack@google.com sc_dt::uint64 end_range) 26112855Sgabeblack@google.com { 26212855Sgabeblack@google.com // do the invalidation if there is an address range overlap 26312855Sgabeblack@google.com if (start_range <= mDMIData.get_end_address ()&& 26412855Sgabeblack@google.com end_range >= mDMIData.get_start_address()) { 26512855Sgabeblack@google.com std::cout << name() << ": got DMI pointer invalidation" 26612855Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 26712855Sgabeblack@google.com 26812855Sgabeblack@google.com invalidate(mDMIData); 26912855Sgabeblack@google.com } else { 27012855Sgabeblack@google.com std::cout << name() << ": ignored DMI invalidation for addresses " 27112855Sgabeblack@google.com << std::hex << start_range << ", " 27212855Sgabeblack@google.com << end_range << std::dec 27312855Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 27412855Sgabeblack@google.com } 27512855Sgabeblack@google.com } 27612855Sgabeblack@google.com 27712855Sgabeblack@google.com // Test for transport_dbg, this one should fail in bus_dmi as we address 27812855Sgabeblack@google.com // a target that doesn't support transport_dbg: 27912855Sgabeblack@google.com // FIXME: use a configurable address 28012855Sgabeblack@google.com void end_of_simulation() 28112855Sgabeblack@google.com { 28212855Sgabeblack@google.com std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl 28312855Sgabeblack@google.com << std::endl; 28412855Sgabeblack@google.com unsigned char data[32]; 28512855Sgabeblack@google.com 28612855Sgabeblack@google.com transaction_type trans; 28712855Sgabeblack@google.com trans.set_address(mBaseAddress); 28812855Sgabeblack@google.com trans.set_data_length(32); 28912855Sgabeblack@google.com trans.set_data_ptr(data); 29012855Sgabeblack@google.com trans.set_read(); 29112855Sgabeblack@google.com 29212855Sgabeblack@google.com unsigned int n = socket->transport_dbg(trans); 29312855Sgabeblack@google.com 29412855Sgabeblack@google.com std::cout << "Mem @" << std::hex << mBaseAddress << std::endl; 29512855Sgabeblack@google.com unsigned int j = 0; 29612855Sgabeblack@google.com 29712855Sgabeblack@google.com if (n > 0) 29812855Sgabeblack@google.com { 29912855Sgabeblack@google.com // always align endianness, so that we don't get a diff when 30012855Sgabeblack@google.com // printing the raw data 30112855Sgabeblack@google.com int e_start = 0; 30212855Sgabeblack@google.com int e_end = 4; 30312855Sgabeblack@google.com int e_increment = 1; 30412855Sgabeblack@google.com if (!tlm::host_has_little_endianness()) 30512855Sgabeblack@google.com { 30612855Sgabeblack@google.com e_start = 3; 30712855Sgabeblack@google.com e_end = -1; 30812855Sgabeblack@google.com e_increment = -1; 30912855Sgabeblack@google.com } 31012855Sgabeblack@google.com 31112855Sgabeblack@google.com for (unsigned int i=0; i<n; i+=4) 31212855Sgabeblack@google.com { 31312855Sgabeblack@google.com for (int k=e_start; k!=e_end; k+=e_increment) 31412855Sgabeblack@google.com { 31512855Sgabeblack@google.com std::cout << std::setw(2) << std::setfill('0') 31612855Sgabeblack@google.com << (int)data[i+k]; 31712855Sgabeblack@google.com j++; 31812855Sgabeblack@google.com if (j==16) { 31912855Sgabeblack@google.com j=0; 32012855Sgabeblack@google.com std::cout << std::endl; 32112855Sgabeblack@google.com } else { 32212855Sgabeblack@google.com std::cout << " "; 32312855Sgabeblack@google.com } 32412855Sgabeblack@google.com } 32512855Sgabeblack@google.com } 32612855Sgabeblack@google.com } 32712855Sgabeblack@google.com else 32812855Sgabeblack@google.com { 32912855Sgabeblack@google.com std::cout << "OK: debug transaction didn't give data." << std::endl; 33012855Sgabeblack@google.com } 33112855Sgabeblack@google.com std::cout << std::dec << std::endl; 33212855Sgabeblack@google.com } 33312855Sgabeblack@google.comprivate: 33412855Sgabeblack@google.com dmi_type mDMIData; 33512855Sgabeblack@google.com 33612855Sgabeblack@google.com sc_core::sc_event mEndEvent; 33712855Sgabeblack@google.com unsigned int mNrOfTransactions; 33812855Sgabeblack@google.com unsigned int mBaseAddress; 33912855Sgabeblack@google.com unsigned int mTransactionCount; 34012855Sgabeblack@google.com unsigned int mData; 34112855Sgabeblack@google.com}; 34212855Sgabeblack@google.com 34312855Sgabeblack@google.com#endif 344