SimpleATTarget2.h revision 12922:a4f51f3405ac
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20#ifndef __SIMPLE_AT_TARGET2_H__ 21#define __SIMPLE_AT_TARGET2_H__ 22 23#include "tlm.h" 24#include "tlm_utils/simple_target_socket.h" 25//#include <systemc> 26#include <cassert> 27#include <vector> 28#include <queue> 29//#include <iostream> 30 31class SimpleATTarget2 : public sc_core::sc_module 32{ 33public: 34 typedef tlm::tlm_generic_payload transaction_type; 35 typedef tlm::tlm_phase phase_type; 36 typedef tlm::tlm_sync_enum sync_enum_type; 37 typedef tlm_utils::simple_target_socket<SimpleATTarget2> target_socket_type; 38 39public: 40 target_socket_type socket; 41 42public: 43 SC_HAS_PROCESS(SimpleATTarget2); 44 SimpleATTarget2(sc_core::sc_module_name name) : 45 sc_core::sc_module(name), 46 socket("socket"), 47 ACCEPT_DELAY(25, sc_core::SC_NS), 48 RESPONSE_DELAY(100, sc_core::SC_NS) 49 { 50 // register nb_transport method 51 socket.register_nb_transport_fw(this, &SimpleATTarget2::myNBTransport); 52 53 SC_METHOD(beginResponse) 54 sensitive << mBeginResponseEvent; 55 dont_initialize(); 56 57 SC_METHOD(endResponse) 58 sensitive << mEndResponseEvent; 59 dont_initialize(); 60 } 61 62 // 63 // Simple AT-TA target 64 // - Request is accepted after fixed delay (relative to end of prev request 65 // phase) 66 // - Response is started after fixed delay (relative to end of prev resp 67 // phase) 68 // 69 sync_enum_type myNBTransport(transaction_type& trans, 70 phase_type& phase, 71 sc_core::sc_time& t) 72 { 73 if (phase == tlm::BEGIN_REQ) { 74 // transactions may be kept in queue after the initiator has send END_REQ 75 trans.acquire(); 76 77 sc_dt::uint64 address = trans.get_address(); 78 assert(address < 400); 79 80 unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); 81 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 82 std::cout << name() << ": Received write request: A = 0x" 83 << std::hex << (unsigned int)address << ", D = 0x" << data 84 << std::dec << " @ " << sc_core::sc_time_stamp() 85 << std::endl; 86 87 *reinterpret_cast<unsigned int*>(&mMem[address]) = data; 88 89 } else { 90 std::cout << name() << ": Received read request: A = 0x" 91 << std::hex << (unsigned int)address 92 << std::dec << " @ " << sc_core::sc_time_stamp() 93 << std::endl; 94 95 data = *reinterpret_cast<unsigned int*>(&mMem[address]); 96 } 97 98 // End request phase after accept delay 99 t += ACCEPT_DELAY; 100 phase = tlm::END_REQ; 101 102 if (mResponseQueue.empty()) { 103 // Start processing transaction after accept delay 104 // Notify begin of response phase after accept delay + response delay 105 mBeginResponseEvent.notify(t + RESPONSE_DELAY); 106 } 107 mResponseQueue.push(&trans); 108 109 // AT-noTA target 110 // - always return false 111 // - immediately return delay to indicate end of phase 112 return tlm::TLM_UPDATED; 113 114 } else if (phase == tlm::END_RESP) { 115 116 // response phase ends after t 117 mEndResponseEvent.notify(t); 118 119 return tlm::TLM_COMPLETED; 120 } 121 122 // Not possible 123 assert(0); exit(1); 124// return tlm::TLM_COMPLETED; //unreachable code 125 } 126 127 void beginResponse() 128 { 129 assert(!mResponseQueue.empty()); 130 // start response phase of oldest transaction 131 phase_type phase = tlm::BEGIN_RESP; 132 sc_core::sc_time t = sc_core::SC_ZERO_TIME; 133 transaction_type* trans = mResponseQueue.front(); 134 assert(trans); 135 136 // Set response data 137 trans->set_response_status(tlm::TLM_OK_RESPONSE); 138 if (trans->get_command() == tlm::TLM_READ_COMMAND) { 139 sc_dt::uint64 address = trans->get_address(); 140 assert(address < 400); 141 *reinterpret_cast<unsigned int*>(trans->get_data_ptr()) = 142 *reinterpret_cast<unsigned int*>(&mMem[address]); 143 } 144 145 if (socket->nb_transport_bw(*trans, phase, t) == tlm::TLM_COMPLETED) { 146 // response phase ends after t 147 mEndResponseEvent.notify(t); 148 149 } else { 150 // initiator will call nb_transport to indicate end of response phase 151 } 152 } 153 154 void endResponse() 155 { 156 assert(!mResponseQueue.empty()); 157 mResponseQueue.front()->release(); 158 mResponseQueue.pop(); 159 160 // Start processing next transaction when previous response is accepted. 161 // Notify begin of response phase after RESPONSE delay 162 if (!mResponseQueue.empty()) { 163 mBeginResponseEvent.notify(RESPONSE_DELAY); 164 } 165 } 166 167private: 168 const sc_core::sc_time ACCEPT_DELAY; 169 const sc_core::sc_time RESPONSE_DELAY; 170 171private: 172 unsigned char mMem[400]; 173 std::queue<transaction_type*> mResponseQueue; 174 sc_core::sc_event mBeginResponseEvent; 175 sc_core::sc_event mEndResponseEvent; 176}; 177 178#endif 179