SimpleATInitiator2.h revision 12922
17008SN/A/***************************************************************************** 27008SN/A 37008SN/A Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 47008SN/A more contributor license agreements. See the NOTICE file distributed 57008SN/A with this work for additional information regarding copyright ownership. 67008SN/A Accellera licenses this file to you under the Apache License, Version 2.0 77008SN/A (the "License"); you may not use this file except in compliance with the 87008SN/A License. You may obtain a copy of the License at 97008SN/A 107008SN/A http://www.apache.org/licenses/LICENSE-2.0 117008SN/A 127008SN/A Unless required by applicable law or agreed to in writing, software 137008SN/A distributed under the License is distributed on an "AS IS" BASIS, 147008SN/A WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 157008SN/A implied. See the License for the specific language governing 167008SN/A permissions and limitations under the License. 177008SN/A 187008SN/A *****************************************************************************/ 197008SN/A 207008SN/A//==================================================================== 217008SN/A// Nov 06, 2008 227008SN/A// 237008SN/A// Updated by: 247008SN/A// Xiaopeng Qiu, JEDA Technologies, Inc 257008SN/A// Email: qiuxp@jedatechnologies.net 267008SN/A// 277008SN/A// To fix violations of TLM2.0 rules, which are detected by JEDA 286145SN/A// TLM2.0 checker. 2910441Snilay@cs.wisc.edu// 3010441Snilay@cs.wisc.edu//==================================================================== 316145SN/A 329505SN/A#ifndef __SIMPLE_AT_INITIATOR2_H__ 3310970Sdavid.hashe@amd.com#define __SIMPLE_AT_INITIATOR2_H__ 3410970Sdavid.hashe@amd.com 3510970Sdavid.hashe@amd.com#include "tlm.h" 366145SN/A#include "tlm_utils/simple_initiator_socket.h" 3710970Sdavid.hashe@amd.com//#include <systemc> 387039SN/A#include <cassert> 397039SN/A#include <queue> 4010970Sdavid.hashe@amd.com//#include <iostream> 4110970Sdavid.hashe@amd.com 427039SN/Aclass SimpleATInitiator2 : public sc_core::sc_module 436145SN/A{ 447039SN/Apublic: 4510314Snilay@cs.wisc.edu typedef tlm::tlm_generic_payload transaction_type; 466145SN/A typedef tlm::tlm_phase phase_type; 477039SN/A typedef tlm::tlm_sync_enum sync_enum_type; 4810314Snilay@cs.wisc.edu typedef tlm_utils::simple_initiator_socket<SimpleATInitiator2> initiator_socket_type; 496145SN/A 507039SN/Apublic: 5110314Snilay@cs.wisc.edu // extended transaction, holds tlm_generic_payload + data storage 526145SN/A template <typename DT> 5310970Sdavid.hashe@amd.com class MyTransaction : public transaction_type 5410970Sdavid.hashe@amd.com { 557039SN/A public: 567039SN/A MyTransaction() 577039SN/A { 589505SN/A this->set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 596145SN/A } 606145SN/A MyTransaction(tlm::tlm_mm_interface* mm) : transaction_type(mm) 6110441Snilay@cs.wisc.edu { 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