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_TARGET1_H__ 21#define __SIMPLE_AT_TARGET1_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 SimpleATTarget1 : 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<SimpleATTarget1> target_socket_type; 38 39public: 40 target_socket_type socket; 41 42public: 43 SC_HAS_PROCESS(SimpleATTarget1); 44 SimpleATTarget1(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, &SimpleATTarget1::myNBTransport); 52 53 SC_METHOD(endRequest) 54 sensitive << mEndRequestEvent; 55 dont_initialize(); 56 57 SC_METHOD(beginResponse) 58 sensitive << mBeginResponseEvent; 59 dont_initialize(); 60 61 SC_METHOD(endResponse) 62 sensitive << mEndResponseEvent; 63 dont_initialize(); 64 } 65 66 // 67 // Simple AT target 68 // - Request is accepted after ACCEPT delay (relative to end of prev request 69 // phase) 70 // - Response is started after RESPONSE delay (relative to end of prev resp 71 // phase) 72 // 73 sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) 74 { 75 if (phase == tlm::BEGIN_REQ) { 76 // transactions may be kept in queue after the initiator has send END_REQ 77 trans.acquire(); 78 79 sc_dt::uint64 address = trans.get_address(); 80 assert(address < 400); 81 82 unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); 83 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 84 std::cout << name() << ": Received write request: A = 0x" 85 << std::hex << (unsigned int)address << ", D = 0x" 86 << data << std::dec 87 << " @ " << sc_core::sc_time_stamp() << std::endl; 88 89 *reinterpret_cast<unsigned int*>(&mMem[address]) = data; 90 91 } else { 92 std::cout << name() << ": Received read request: A = 0x" 93 << std::hex << (unsigned int)address << std::dec 94 << " @ " << sc_core::sc_time_stamp() << std::endl; 95 96 data = *reinterpret_cast<unsigned int*>(&mMem[address]); 97 } 98 99 // Notify end of request phase after ACCEPT delay 100 if (mEndRequestQueue.empty()) { 101 mEndRequestEvent.notify(t + ACCEPT_DELAY); 102 } 103 mEndRequestQueue.push(&trans); 104 105 // AT-noTA target 106 // - always return false 107 // - seperate call to indicate end of phase (do not update phase or t) 108 return tlm::TLM_ACCEPTED; 109 110 } else if (phase == tlm::END_RESP) { 111 112 // response phase ends after t 113 mEndResponseEvent.notify(t); 114 115 return tlm::TLM_COMPLETED; 116 } 117 118 // Not possible 119 assert(0); exit(1); 120// return tlm::TLM_COMPLETED; //unreachable code 121 } 122 123 void endRequest() 124 { 125 assert(!mEndRequestQueue.empty()); 126 // end request phase of oldest transaction 127 phase_type phase = tlm::END_REQ; 128 sc_core::sc_time t = sc_core::SC_ZERO_TIME; 129 transaction_type* trans = mEndRequestQueue.front(); 130 assert(trans); 131 mEndRequestQueue.pop(); 132 #if ( ! NDEBUG ) 133 sync_enum_type r = socket->nb_transport_bw(*trans, phase, t); 134 #endif /* ! NDEBUG */ 135 assert(r == tlm::TLM_ACCEPTED); // FIXME: initiator should return TLM_ACCEPTED? 136 assert(t == sc_core::SC_ZERO_TIME); // t must be SC_ZERO_TIME 137 138 // Notify end of request phase for next transaction after ACCEPT delay 139 if (!mEndRequestQueue.empty()) { 140 mEndRequestEvent.notify(ACCEPT_DELAY); 141 } 142 143 if (mResponseQueue.empty()) { 144 // Start processing transaction 145 // Notify begin of response phase after RESPONSE delay 146 mBeginResponseEvent.notify(RESPONSE_DELAY); 147 } 148 mResponseQueue.push(trans); 149 } 150 151 void beginResponse() 152 { 153 assert(!mResponseQueue.empty()); 154 // start response phase of oldest transaction 155 phase_type phase = tlm::BEGIN_RESP; 156 sc_core::sc_time t = sc_core::SC_ZERO_TIME; 157 transaction_type* trans = mResponseQueue.front(); 158 assert(trans); 159 160 // Set response data 161 trans->set_response_status(tlm::TLM_OK_RESPONSE); 162 if (trans->get_command() == tlm::TLM_READ_COMMAND) { 163 sc_dt::uint64 address = trans->get_address(); 164 assert(address < 400); 165 *reinterpret_cast<unsigned int*>(trans->get_data_ptr()) = 166 *reinterpret_cast<unsigned int*>(&mMem[address]); 167 } 168 169 switch (socket->nb_transport_bw(*trans, phase, t)) { 170 case tlm::TLM_COMPLETED: 171 // response phase ends after t 172 mEndResponseEvent.notify(t); 173 break; 174 175 case tlm::TLM_ACCEPTED: 176 case tlm::TLM_UPDATED: 177 // initiator will call nb_transport to indicate end of response phase 178 break; 179 180 default: 181 assert(0); exit(1); 182 }; 183 } 184 185 void endResponse() 186 { 187 assert(!mResponseQueue.empty()); 188 mResponseQueue.front()->release(); 189 mResponseQueue.pop(); 190 191 if (!mResponseQueue.empty()) { 192 // Start processing next transaction 193 // Notify begin of response phase after RESPONSE delay 194 mBeginResponseEvent.notify(RESPONSE_DELAY); 195 } 196 } 197 198private: 199 const sc_core::sc_time ACCEPT_DELAY; 200 const sc_core::sc_time RESPONSE_DELAY; 201 202private: 203 unsigned char mMem[400]; 204 std::queue<transaction_type*> mEndRequestQueue; 205 sc_core::sc_event mEndRequestEvent; 206 std::queue<transaction_type*> mResponseQueue; 207 sc_core::sc_event mBeginResponseEvent; 208 sc_core::sc_event mEndResponseEvent; 209}; 210 211#endif 212