SimpleATInitiator2.h revision 12922
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//==================================================================== 21// Nov 06, 2008 22// 23// Updated by: 24// Xiaopeng Qiu, JEDA Technologies, Inc 25// Email: qiuxp@jedatechnologies.net 26// 27// To fix violations of TLM2.0 rules, which are detected by JEDA 28// TLM2.0 checker. 29// 30//==================================================================== 31 32#ifndef __SIMPLE_AT_INITIATOR2_H__ 33#define __SIMPLE_AT_INITIATOR2_H__ 34 35#include "tlm.h" 36#include "tlm_utils/simple_initiator_socket.h" 37//#include <systemc> 38#include <cassert> 39#include <queue> 40//#include <iostream> 41 42class SimpleATInitiator2 : public sc_core::sc_module 43{ 44public: 45 typedef tlm::tlm_generic_payload transaction_type; 46 typedef tlm::tlm_phase phase_type; 47 typedef tlm::tlm_sync_enum sync_enum_type; 48 typedef tlm_utils::simple_initiator_socket<SimpleATInitiator2> initiator_socket_type; 49 50public: 51 // extended transaction, holds tlm_generic_payload + data storage 52 template <typename DT> 53 class MyTransaction : public transaction_type 54 { 55 public: 56 MyTransaction() 57 { 58 this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 59 } 60 MyTransaction(tlm::tlm_mm_interface* mm) : transaction_type(mm) 61 { 62 this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 63 } 64 65 void setData(DT& data) { mData = data; } 66 DT getData() const { return mData; } 67 68 private: 69 DT mData; 70 }; 71 typedef MyTransaction<unsigned int> mytransaction_type; 72 73 // Dummy Transaction Pool 74 class SimplePool : public tlm::tlm_mm_interface 75 { 76 public: 77 SimplePool() {} 78 mytransaction_type* claim() 79 { 80 mytransaction_type* t = new mytransaction_type(this); 81 t->acquire(); 82 return t; 83 } 84 void release(mytransaction_type* t) 85 { 86 t->release(); 87 } 88 void free(tlm::tlm_generic_payload* t) 89 { 90 t->reset(); 91 delete t; 92 } 93 }; 94 95public: 96 initiator_socket_type socket; 97 98public: 99 SC_HAS_PROCESS(SimpleATInitiator2); 100 SimpleATInitiator2(sc_core::sc_module_name name, 101 unsigned int nrOfTransactions = 0x5, 102 unsigned int baseAddress = 0) : 103 sc_core::sc_module(name), 104 socket("socket"), 105 ACCEPT_DELAY(10, sc_core::SC_NS), 106 mNrOfTransactions(nrOfTransactions), 107 mBaseAddress(baseAddress), 108 mTransactionCount(0), 109 mCurrentTransaction(0) 110 { 111 // register nb_transport method 112 socket.register_nb_transport_bw(this, &SimpleATInitiator2::myNBTransport); 113 114 // Initiator thread 115 SC_THREAD(run); 116 } 117 118 bool initTransaction(mytransaction_type*& trans) 119 { 120 if (mTransactionCount < mNrOfTransactions) { 121 trans = transPool.claim(); 122 trans->set_address(mBaseAddress + 4*mTransactionCount); 123 trans->setData(mTransactionCount); 124 trans->set_command(tlm::TLM_WRITE_COMMAND); 125 126 } else if (mTransactionCount < 2 * mNrOfTransactions) { 127 trans = transPool.claim(); 128 trans->set_address(mBaseAddress + 4*(mTransactionCount - mNrOfTransactions)); 129 trans->set_command(tlm::TLM_READ_COMMAND); 130 131 } else { 132 return false; 133 } 134 135 trans->set_data_length(4); 136 trans->set_streaming_width(4); 137 138 ++mTransactionCount; 139 return true; 140 } 141 142 void logStartTransation(mytransaction_type& trans) 143 { 144 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 145 std::cout << name() << ": Send write request: A = 0x" 146 << std::hex << (unsigned int)trans.get_address() 147 << ", D = 0x" << trans.getData() << std::dec 148 << " @ " << sc_core::sc_time_stamp() << std::endl; 149 150 } else { 151 std::cout << name() << ": Send read request: A = 0x" 152 << std::hex << (unsigned int)trans.get_address() << std::dec 153 << " @ " << sc_core::sc_time_stamp() << std::endl; 154 } 155 } 156 157 void logEndTransaction(mytransaction_type& trans) 158 { 159 if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { 160 std::cout << name() << ": Received error response @ " 161 << sc_core::sc_time_stamp() << std::endl; 162 163 } else { 164 std::cout << name() << ": Received ok response"; 165 if (trans.get_command() == tlm::TLM_READ_COMMAND) { 166 std::cout << ": D = 0x" << std::hex << trans.getData() << std::dec; 167 } 168 std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; 169 } 170 } 171 172 // 173 // Simple AT Initiator 174 // - Request must be accepted by the target before the next request can be 175 // send 176 // - Responses can come out of order 177 // - Responses will be accepted after fixed delay 178 // 179 void run() 180 { 181 phase_type phase; 182 sc_core::sc_time t; 183 184 mytransaction_type* ptrans; 185 while (initTransaction(ptrans)) { 186 // Create transaction and initialise phase and t 187 mytransaction_type& trans = *ptrans; 188 phase = tlm::BEGIN_REQ; 189 t = sc_core::SC_ZERO_TIME; 190 191 logStartTransation(trans); 192 193 switch (socket->nb_transport_fw(trans, phase, t)) { 194 case tlm::TLM_COMPLETED: 195 // Transaction Finished, wait for the returned delay 196 wait(t); 197 logEndTransaction(trans); 198 transPool.release(&trans); 199 break; 200 201 case tlm::TLM_ACCEPTED: 202 case tlm::TLM_UPDATED: 203 switch (phase) { 204 case tlm::BEGIN_REQ: 205 // Request phase not yet finished 206 // Wait until end of request phase before sending new request 207 208 // FIXME 209 mCurrentTransaction = &trans; 210 wait(mEndRequestPhase); 211 mCurrentTransaction = 0; 212 break; 213 214 case tlm::END_REQ: 215 // Request phase ended 216 if (t != sc_core::SC_ZERO_TIME) { 217 // Wait until end of request time before sending new request 218 wait(t); 219 } 220 break; 221 222 case tlm::BEGIN_RESP: 223 // Request phase ended and response phase already started 224 if (t != sc_core::SC_ZERO_TIME) { 225 // Wait until end of request time before sending new request 226 wait(t); 227 } 228 // Notify end of response phase after ACCEPT delay 229 t += ACCEPT_DELAY; 230 phase = tlm::END_RESP; 231 socket->nb_transport_fw(trans, phase, t); 232 logEndTransaction(trans); 233 transPool.release(&trans); 234 break; 235 236 case tlm::END_RESP: // fall-through 237 default: 238 // A target should never return with these phases 239 // If phase == END_RESP, nb_transport should have returned true 240 assert(0); exit(1); 241 break; 242 } 243 break; 244 245 default: 246 assert(0); exit(1); 247 }; 248 } 249 wait(); 250 251 } 252 253 sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) 254 { 255 switch (phase) { 256 case tlm::END_REQ: 257 assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? 258 // Request phase ended 259 mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); 260 return tlm::TLM_ACCEPTED; 261 262 case tlm::BEGIN_RESP: 263 { 264 assert(t == sc_core::SC_ZERO_TIME); // FIXME: can t != 0? 265 266 // Notify end of request phase if run thread is waiting for it 267 // FIXME 268 if (&trans == mCurrentTransaction) { 269 mEndRequestPhase.notify(sc_core::SC_ZERO_TIME); 270 } 271 272 assert(dynamic_cast<mytransaction_type*>(&trans)); 273 mytransaction_type* myTrans = static_cast<mytransaction_type*>(&trans); 274 assert(myTrans); 275 276 // Notify end of response phase after ACCEPT delay 277 t += ACCEPT_DELAY; 278 phase = tlm::END_RESP; 279 logEndTransaction(*myTrans); 280 transPool.release(myTrans); 281 282 return tlm::TLM_COMPLETED; 283 } 284 285 case tlm::BEGIN_REQ: // fall-through 286 case tlm::END_RESP: // fall-through 287 default: 288 // A target should never call nb_transport with these phases 289 assert(0); exit(1); 290// return tlm::TLM_COMPLETED; //unreachable code 291 }; 292 } 293 294private: 295 const sc_core::sc_time ACCEPT_DELAY; 296 297private: 298 unsigned int mNrOfTransactions; 299 unsigned int mBaseAddress; 300 SimplePool transPool; 301 unsigned int mTransactionCount; 302 sc_core::sc_event mEndRequestPhase; 303 transaction_type* mCurrentTransaction; 304}; 305 306#endif 307