SimpleATInitiator1.h revision 12922
112922Sgabeblack@google.com/***************************************************************************** 212922Sgabeblack@google.com 312922Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412922Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 512922Sgabeblack@google.com with this work for additional information regarding copyright ownership. 612922Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 712922Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 812922Sgabeblack@google.com License. You may obtain a copy of the License at 912922Sgabeblack@google.com 1012922Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1112922Sgabeblack@google.com 1212922Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1312922Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1412922Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512922Sgabeblack@google.com implied. See the License for the specific language governing 1612922Sgabeblack@google.com permissions and limitations under the License. 1712922Sgabeblack@google.com 1812922Sgabeblack@google.com *****************************************************************************/ 1912922Sgabeblack@google.com 2012922Sgabeblack@google.com//==================================================================== 2112922Sgabeblack@google.com// Nov 06, 2008 2212922Sgabeblack@google.com// 2312922Sgabeblack@google.com// Updated by: 2412922Sgabeblack@google.com// Xiaopeng Qiu, JEDA Technologies, Inc 2512922Sgabeblack@google.com// Email: qiuxp@jedatechnologies.net 2612922Sgabeblack@google.com// 2712922Sgabeblack@google.com// To fix violations of TLM2.0 rules, which are detected by JEDA 2812922Sgabeblack@google.com// TLM2.0 checker. 2912922Sgabeblack@google.com// 3012922Sgabeblack@google.com//==================================================================== 3112922Sgabeblack@google.com 3212922Sgabeblack@google.com#ifndef __SIMPLE_AT_INITIATOR1_H__ 3312922Sgabeblack@google.com#define __SIMPLE_AT_INITIATOR1_H__ 3412922Sgabeblack@google.com 3512922Sgabeblack@google.com#include "tlm.h" 3612922Sgabeblack@google.com#include "tlm_utils/simple_initiator_socket.h" 3712922Sgabeblack@google.com//#include <systemc> 3812922Sgabeblack@google.com#include <cassert> 3912922Sgabeblack@google.com#include <queue> 4012922Sgabeblack@google.com//#include <iostream> 4112922Sgabeblack@google.com 4212922Sgabeblack@google.comclass SimpleATInitiator1 : public sc_core::sc_module 4312922Sgabeblack@google.com{ 4412922Sgabeblack@google.compublic: 4512922Sgabeblack@google.com typedef tlm::tlm_generic_payload transaction_type; 4612922Sgabeblack@google.com typedef tlm::tlm_phase phase_type; 4712922Sgabeblack@google.com typedef tlm::tlm_sync_enum sync_enum_type; 4812922Sgabeblack@google.com typedef tlm_utils::simple_initiator_socket<SimpleATInitiator1> initiator_socket_type; 4912922Sgabeblack@google.com 5012922Sgabeblack@google.compublic: 5112922Sgabeblack@google.com // extended transaction, holds tlm_generic_payload + data storage 5212922Sgabeblack@google.com template <typename DT> 5312922Sgabeblack@google.com class MyTransaction : public transaction_type 5412922Sgabeblack@google.com { 5512922Sgabeblack@google.com public: 5612922Sgabeblack@google.com MyTransaction() 5712922Sgabeblack@google.com { 5812922Sgabeblack@google.com this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 5912922Sgabeblack@google.com } 6012922Sgabeblack@google.com MyTransaction(tlm::tlm_mm_interface* mm) : transaction_type(mm) 6112922Sgabeblack@google.com { 6212922Sgabeblack@google.com this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 6312922Sgabeblack@google.com } 6412922Sgabeblack@google.com 6512922Sgabeblack@google.com void setData(DT& data) { mData = data; } 6612922Sgabeblack@google.com DT getData() const { return mData; } 6712922Sgabeblack@google.com 6812922Sgabeblack@google.com private: 6912922Sgabeblack@google.com DT mData; 7012922Sgabeblack@google.com }; 7112922Sgabeblack@google.com typedef MyTransaction<unsigned int> mytransaction_type; 7212922Sgabeblack@google.com 7312922Sgabeblack@google.com // Dummy Transaction Pool 7412922Sgabeblack@google.com class SimplePool : public tlm::tlm_mm_interface 7512922Sgabeblack@google.com { 7612922Sgabeblack@google.com public: 7712922Sgabeblack@google.com SimplePool() {} 7812922Sgabeblack@google.com mytransaction_type* claim() 7912922Sgabeblack@google.com { 8012922Sgabeblack@google.com mytransaction_type* t = new mytransaction_type(this); 8112922Sgabeblack@google.com t->acquire(); 8212922Sgabeblack@google.com return t; 8312922Sgabeblack@google.com } 8412922Sgabeblack@google.com void release(mytransaction_type* t) 8512922Sgabeblack@google.com { 8612922Sgabeblack@google.com t->release(); 8712922Sgabeblack@google.com } 8812922Sgabeblack@google.com void free(tlm::tlm_generic_payload* t) 8912922Sgabeblack@google.com { 9012922Sgabeblack@google.com t->reset(); 9112922Sgabeblack@google.com delete t; 9212922Sgabeblack@google.com } 9312922Sgabeblack@google.com }; 9412922Sgabeblack@google.com 9512922Sgabeblack@google.compublic: 9612922Sgabeblack@google.com initiator_socket_type socket; 9712922Sgabeblack@google.com 9812922Sgabeblack@google.compublic: 9912922Sgabeblack@google.com SC_HAS_PROCESS(SimpleATInitiator1); 10012922Sgabeblack@google.com SimpleATInitiator1(sc_core::sc_module_name name, 10112922Sgabeblack@google.com unsigned int nrOfTransactions = 0x5, 10212922Sgabeblack@google.com unsigned int baseAddress = 0x0) : 10312922Sgabeblack@google.com sc_core::sc_module(name), 10412922Sgabeblack@google.com socket("socket"), 10512922Sgabeblack@google.com ACCEPT_DELAY(10, sc_core::SC_NS), 10612922Sgabeblack@google.com mNrOfTransactions(nrOfTransactions), 10712922Sgabeblack@google.com mBaseAddress(baseAddress), 10812922Sgabeblack@google.com mTransactionCount(0), 10912922Sgabeblack@google.com mCurrentTransaction(0) 11012922Sgabeblack@google.com { 11112922Sgabeblack@google.com // register nb_transport method 11212922Sgabeblack@google.com socket.register_nb_transport_bw(this, &SimpleATInitiator1::myNBTransport); 11312922Sgabeblack@google.com 11412922Sgabeblack@google.com // Initiator thread 11512922Sgabeblack@google.com SC_THREAD(run); 11612922Sgabeblack@google.com 11712922Sgabeblack@google.com SC_METHOD(endResponse) 11812922Sgabeblack@google.com sensitive << mEndResponseEvent; 11912922Sgabeblack@google.com dont_initialize(); 12012922Sgabeblack@google.com } 12112922Sgabeblack@google.com 12212922Sgabeblack@google.com bool initTransaction(mytransaction_type*& trans) 12312922Sgabeblack@google.com { 12412922Sgabeblack@google.com if (mTransactionCount < mNrOfTransactions) { 12512922Sgabeblack@google.com trans = transPool.claim(); 12612922Sgabeblack@google.com trans->set_address(mBaseAddress + 4*mTransactionCount); 12712922Sgabeblack@google.com trans->setData(mTransactionCount); 12812922Sgabeblack@google.com trans->set_command(tlm::TLM_WRITE_COMMAND); 12912922Sgabeblack@google.com 13012922Sgabeblack@google.com } else if (mTransactionCount < 2 * mNrOfTransactions) { 13112922Sgabeblack@google.com trans = transPool.claim(); 13212922Sgabeblack@google.com trans->set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); 13312922Sgabeblack@google.com trans->set_command(tlm::TLM_READ_COMMAND); 13412922Sgabeblack@google.com 13512922Sgabeblack@google.com } else { 13612922Sgabeblack@google.com return false; 13712922Sgabeblack@google.com } 13812922Sgabeblack@google.com 13912922Sgabeblack@google.com trans->set_data_length(4); 14012922Sgabeblack@google.com trans->set_streaming_width(4); 14112922Sgabeblack@google.com 14212922Sgabeblack@google.com ++mTransactionCount; 14312922Sgabeblack@google.com return true; 14412922Sgabeblack@google.com } 14512922Sgabeblack@google.com 14612922Sgabeblack@google.com void logStartTransation(mytransaction_type& trans) 14712922Sgabeblack@google.com { 14812922Sgabeblack@google.com if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 14912922Sgabeblack@google.com std::cout << name() << ": Send write request: A = 0x" 15012922Sgabeblack@google.com << std::hex << (unsigned int)trans.get_address() 15112922Sgabeblack@google.com << ", D = 0x" << trans.getData() << std::dec 15212922Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 15312922Sgabeblack@google.com 15412922Sgabeblack@google.com } else { 15512922Sgabeblack@google.com std::cout << name() << ": Send read request: A = 0x" 15612922Sgabeblack@google.com << std::hex << (int)trans.get_address() << std::dec 15712922Sgabeblack@google.com << " @ " << sc_core::sc_time_stamp() << std::endl; 15812922Sgabeblack@google.com } 15912922Sgabeblack@google.com } 16012922Sgabeblack@google.com 16112922Sgabeblack@google.com void logEndTransaction(mytransaction_type& trans) 16212922Sgabeblack@google.com { 16312922Sgabeblack@google.com if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { 16412922Sgabeblack@google.com std::cout << name() << ": Received error response @ " 16512922Sgabeblack@google.com << sc_core::sc_time_stamp() << std::endl; 16612922Sgabeblack@google.com 16712922Sgabeblack@google.com } else { 16812922Sgabeblack@google.com std::cout << name() << ": Received ok response"; 16912922Sgabeblack@google.com if (trans.get_command() == tlm::TLM_READ_COMMAND) { 17012922Sgabeblack@google.com std::cout << ": D = 0x" << trans.getData() << std::dec; 17112922Sgabeblack@google.com } 17212922Sgabeblack@google.com std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; 17312922Sgabeblack@google.com } 17412922Sgabeblack@google.com } 17512922Sgabeblack@google.com 17612922Sgabeblack@google.com // 17712922Sgabeblack@google.com // Simple AT Initiator 17812922Sgabeblack@google.com // - Request must be accepted by the target before the next request can be 17912922Sgabeblack@google.com // send 18012922Sgabeblack@google.com // - Responses can come out of order 18112922Sgabeblack@google.com // - Responses will be accepted after fixed delay 18212922Sgabeblack@google.com // 18312922Sgabeblack@google.com void run() 18412922Sgabeblack@google.com { 18512922Sgabeblack@google.com phase_type phase; 18612922Sgabeblack@google.com sc_core::sc_time t; 18712922Sgabeblack@google.com 18812922Sgabeblack@google.com mytransaction_type* ptrans; 18912922Sgabeblack@google.com while (initTransaction(ptrans)) { 19012922Sgabeblack@google.com // Create transaction and initialise phase and t 19112922Sgabeblack@google.com mytransaction_type& trans = *ptrans; 19212922Sgabeblack@google.com phase = tlm::BEGIN_REQ; 19312922Sgabeblack@google.com t = sc_core::SC_ZERO_TIME; 19412922Sgabeblack@google.com 19512922Sgabeblack@google.com logStartTransation(trans); 19612922Sgabeblack@google.com 19712922Sgabeblack@google.com switch (socket->nb_transport_fw(trans, phase, t)) { 19812922Sgabeblack@google.com case tlm::TLM_COMPLETED: 19912922Sgabeblack@google.com // Transaction Finished, wait for the returned delay 20012922Sgabeblack@google.com wait(t); 20112922Sgabeblack@google.com logEndTransaction(trans); 20212922Sgabeblack@google.com transPool.release(&trans); 20312922Sgabeblack@google.com break; 20412922Sgabeblack@google.com 20512922Sgabeblack@google.com case tlm::TLM_ACCEPTED: 20612922Sgabeblack@google.com case tlm::TLM_UPDATED: 20712922Sgabeblack@google.com switch (phase) { 20812922Sgabeblack@google.com case tlm::BEGIN_REQ: 20912922Sgabeblack@google.com // Request phase not yet finished 21012922Sgabeblack@google.com // Wait until end of request phase before sending new request 21112922Sgabeblack@google.com 21212922Sgabeblack@google.com // FIXME 21312922Sgabeblack@google.com mCurrentTransaction = &trans; 21412922Sgabeblack@google.com wait(mEndRequestPhase); 21512922Sgabeblack@google.com mCurrentTransaction = 0; 21612922Sgabeblack@google.com break; 21712922Sgabeblack@google.com 21812922Sgabeblack@google.com case tlm::END_REQ: 21912922Sgabeblack@google.com // Request phase ended 22012922Sgabeblack@google.com if (t != sc_core::SC_ZERO_TIME) { 22112922Sgabeblack@google.com // Wait until end of request time before sending new request 22212922Sgabeblack@google.com wait(t); 22312922Sgabeblack@google.com } 22412922Sgabeblack@google.com break; 22512922Sgabeblack@google.com 22612922Sgabeblack@google.com case tlm::BEGIN_RESP: 22712922Sgabeblack@google.com // Request phase ended and response phase already started 22812922Sgabeblack@google.com if (t != sc_core::SC_ZERO_TIME) { 22912922Sgabeblack@google.com // Wait until end of request time before sending new request 23012922Sgabeblack@google.com wait(t); 23112922Sgabeblack@google.com } 23212922Sgabeblack@google.com if (mEndResponseQueue.empty()) { 23312922Sgabeblack@google.com // Notify end of response phase after ACCEPT delay 23412922Sgabeblack@google.com mEndResponseEvent.notify(ACCEPT_DELAY); 23512922Sgabeblack@google.com } 23612922Sgabeblack@google.com mEndResponseQueue.push(&trans); 23712922Sgabeblack@google.com break; 23812922Sgabeblack@google.com 23912922Sgabeblack@google.com case tlm::END_RESP: // fall-through 24012922Sgabeblack@google.com default: 24112922Sgabeblack@google.com // A target should never return with these phases 24212922Sgabeblack@google.com // If phase == END_RESP, nb_transport should have returned true 24312922Sgabeblack@google.com assert(0); exit(1); 24412922Sgabeblack@google.com break; 24512922Sgabeblack@google.com } 24612922Sgabeblack@google.com break; 24712922Sgabeblack@google.com 24812922Sgabeblack@google.com default: 24912922Sgabeblack@google.com assert(0); exit(1); 25012922Sgabeblack@google.com }; 25112922Sgabeblack@google.com } 25212922Sgabeblack@google.com wait(); 25312922Sgabeblack@google.com } 25412922Sgabeblack@google.com 25512922Sgabeblack@google.com sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) 25612922Sgabeblack@google.com { 25712922Sgabeblack@google.com switch (phase) { 25812922Sgabeblack@google.com case tlm::END_REQ: 25912922Sgabeblack@google.com assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? 26012922Sgabeblack@google.com // Request phase ended 26112922Sgabeblack@google.com mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); 26212922Sgabeblack@google.com return tlm::TLM_ACCEPTED; 26312922Sgabeblack@google.com 26412922Sgabeblack@google.com case tlm::BEGIN_RESP: 26512922Sgabeblack@google.com { 26612922Sgabeblack@google.com assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? 26712922Sgabeblack@google.com 26812922Sgabeblack@google.com // Notify end of request phase if run thread is waiting for it 26912922Sgabeblack@google.com // FIXME 27012922Sgabeblack@google.com if (&trans == mCurrentTransaction) { 27112922Sgabeblack@google.com mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); 27212922Sgabeblack@google.com } 27312922Sgabeblack@google.com 27412922Sgabeblack@google.com assert(dynamic_cast<mytransaction_type*>(&trans)); 27512922Sgabeblack@google.com mytransaction_type* myTrans = static_cast<mytransaction_type*>(&trans); 27612922Sgabeblack@google.com assert(myTrans); 27712922Sgabeblack@google.com 27812922Sgabeblack@google.com if (mEndResponseQueue.empty()) { 27912922Sgabeblack@google.com // Notify end of response phase after ACCEPT delay 28012922Sgabeblack@google.com mEndResponseEvent.notify(ACCEPT_DELAY); 28112922Sgabeblack@google.com } 28212922Sgabeblack@google.com mEndResponseQueue.push(myTrans); 28312922Sgabeblack@google.com return tlm::TLM_ACCEPTED; 28412922Sgabeblack@google.com } 28512922Sgabeblack@google.com 28612922Sgabeblack@google.com case tlm::BEGIN_REQ: // fall-through 28712922Sgabeblack@google.com case tlm::END_RESP: // fall-through 28812922Sgabeblack@google.com default: 28912922Sgabeblack@google.com // A target should never call nb_transport with these phases 29012922Sgabeblack@google.com assert(0); exit(1); 29112922Sgabeblack@google.com// return tlm::TLM_COMPLETED; //unreachable code 29212922Sgabeblack@google.com }; 29312922Sgabeblack@google.com } 29412922Sgabeblack@google.com 29512922Sgabeblack@google.com void endResponse() 29612922Sgabeblack@google.com { 29712922Sgabeblack@google.com assert(!mEndResponseQueue.empty()); 29812922Sgabeblack@google.com // end response phase 29912922Sgabeblack@google.com phase_type phase = tlm::END_RESP; 30012922Sgabeblack@google.com sc_core::sc_time t = sc_core::SC_ZERO_TIME; 30112922Sgabeblack@google.com mytransaction_type* trans = mEndResponseQueue.front(); 30212922Sgabeblack@google.com assert(trans); 30312922Sgabeblack@google.com mEndResponseQueue.pop(); 30412922Sgabeblack@google.com #if ( ! NDEBUG ) 30512922Sgabeblack@google.com sync_enum_type r = socket->nb_transport_fw(*trans, phase, t); 30612922Sgabeblack@google.com #endif /* ! NDEBUG */ 30712922Sgabeblack@google.com assert(r == tlm::TLM_COMPLETED); // FIXME: target should return TLM_COMPLETED? 30812922Sgabeblack@google.com assert(t == sc_core::SC_ZERO_TIME); // t must be SC_ZERO_TIME 30912922Sgabeblack@google.com 31012922Sgabeblack@google.com logEndTransaction(*trans); 31112922Sgabeblack@google.com transPool.release(trans); 31212922Sgabeblack@google.com 31312922Sgabeblack@google.com if (!mEndResponseQueue.empty()) { 31412922Sgabeblack@google.com // Notify end of response phase after ACCEPT delay 31512922Sgabeblack@google.com mEndResponseEvent.notify(ACCEPT_DELAY); 31612922Sgabeblack@google.com } 31712922Sgabeblack@google.com } 31812922Sgabeblack@google.com 31912922Sgabeblack@google.comprivate: 32012922Sgabeblack@google.com const sc_core::sc_time ACCEPT_DELAY; 32112922Sgabeblack@google.com 32212922Sgabeblack@google.comprivate: 32312922Sgabeblack@google.com unsigned int mNrOfTransactions; 32412922Sgabeblack@google.com unsigned int mBaseAddress; 32512922Sgabeblack@google.com SimplePool transPool; 32612922Sgabeblack@google.com unsigned int mTransactionCount; 32712922Sgabeblack@google.com sc_core::sc_event mEndRequestPhase; 32812922Sgabeblack@google.com std::queue<mytransaction_type*> mEndResponseQueue; 32912922Sgabeblack@google.com sc_core::sc_event mEndResponseEvent; 33012922Sgabeblack@google.com transaction_type* mCurrentTransaction; 33112922Sgabeblack@google.com}; 33212922Sgabeblack@google.com 33312922Sgabeblack@google.com#endif 334