SimpleLTInitiator1_DMI.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//==================================================================== 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_LT_INITIATOR1_DMI_H__ 33#define __SIMPLE_LT_INITIATOR1_DMI_H__ 34 35#include "tlm.h" 36#include <systemc> 37#include <cassert> 38#include <iostream> 39#include <iomanip> 40 41class SimpleLTInitiator1_dmi : 42 public sc_core::sc_module, 43 public virtual tlm::tlm_bw_transport_if<> 44{ 45public: 46 typedef tlm::tlm_generic_payload transaction_type; 47 typedef tlm::tlm_dmi dmi_type; 48 typedef tlm::tlm_phase phase_type; 49 typedef tlm::tlm_sync_enum sync_enum_type; 50 typedef tlm::tlm_fw_transport_if<> fw_interface_type; 51 typedef tlm::tlm_bw_transport_if<> bw_interface_type; 52 typedef tlm::tlm_initiator_socket<> initiator_socket_type; 53 54public: 55 initiator_socket_type socket; 56 57public: 58 SC_HAS_PROCESS(SimpleLTInitiator1_dmi); 59 SimpleLTInitiator1_dmi(sc_core::sc_module_name name, 60 unsigned int nrOfTransactions = 0x5, 61 unsigned int baseAddress = 0x0) : 62 sc_core::sc_module(name), 63 socket("socket"), 64 mNrOfTransactions(nrOfTransactions), 65 mBaseAddress(baseAddress), 66 mTransactionCount(0) 67 { 68 invalidate(mDMIData); 69 70 // Bind this initiator's interface to the initiator socket 71 socket(*this); 72 73 // Initiator thread 74 SC_THREAD(run); 75 } 76 77 bool initTransaction(transaction_type& trans) 78 { 79 // initialize DMI hint: 80 trans.set_dmi_allowed(false); 81 82 if (mTransactionCount < mNrOfTransactions) { 83 trans.set_address(mBaseAddress + 4*mTransactionCount); 84 mData = mTransactionCount; 85 trans.set_command(tlm::TLM_WRITE_COMMAND); 86 87 } else if (mTransactionCount < 2 * mNrOfTransactions) { 88 trans.set_address(mBaseAddress + 4*(mTransactionCount-mNrOfTransactions)); 89 mData = 0; 90 trans.set_command(tlm::TLM_READ_COMMAND); 91 92 } else { 93 return false; 94 } 95 96 trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData)); 97 trans.set_data_length(4); 98 trans.set_streaming_width(4); 99 100 ++mTransactionCount; 101 return true; 102 } 103 104 void logStartTransation(transaction_type& trans) 105 { 106 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 107 std::cout << name() << ": Send write request: A = 0x" 108 << std::hex << (unsigned int)trans.get_address() 109 << ", D = 0x" << mData << std::dec 110 << " @ " << sc_core::sc_time_stamp() << std::endl; 111 112 } else { 113 std::cout << name() << ": Send read request: A = 0x" 114 << std::hex << (unsigned int)trans.get_address() << std::dec 115 << " @ " << sc_core::sc_time_stamp() << std::endl; 116 } 117 } 118 119 void logEndTransaction(transaction_type& trans) 120 { 121 if (trans.get_response_status() != tlm::TLM_OK_RESPONSE) { 122 std::cout << name() << ": Received error response @ " 123 << sc_core::sc_time_stamp() << std::endl; 124 125 } else { 126 std::cout << name() << ": Received ok response"; 127 if (trans.get_command() == tlm::TLM_READ_COMMAND) { 128 std::cout << ": D = 0x" << std::hex << mData << std::dec; 129 } 130 std::cout << " @ " << sc_core::sc_time_stamp() << std::endl; 131 } 132 } 133 134 void run() 135 { 136 transaction_type trans; 137 phase_type phase; 138 sc_core::sc_time t; 139 140 while (initTransaction(trans)) { 141 // Create transaction and initialise phase and t 142 phase = tlm::BEGIN_REQ; 143 t = sc_core::SC_ZERO_TIME; 144 145 logStartTransation(trans); 146 147 /////////////////////////////////////////////////////////// 148 // DMI handling: 149 // We use the DMI hint to check if it makes sense to ask for 150 // DMI pointers. The pattern is: 151 // - if the address is covered by a DMI region do a DMI access 152 // - otherwise do a normal transaction 153 // -> check if we get a DMI hint and acquire the DMI pointers if it is 154 // set 155 /////////////////////////////////////////////////////////// 156 157 // Check if the address is covered by our DMI region 158 if ( (trans.get_address() >= mDMIData.get_start_address()) && 159 (trans.get_address() <= mDMIData.get_end_address()) ) { 160 // We can handle the data here. As the logEndTransaction is assuming 161 // something to happen in the data structure, we really need to 162 // do this: 163 trans.set_response_status(tlm::TLM_OK_RESPONSE); 164 sc_dt::uint64 tmp = trans.get_address() - mDMIData.get_start_address(); 165 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 166 *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp] = mData; 167 168 } else { 169 mData = *(unsigned int*)&mDMIData.get_dmi_ptr()[tmp]; 170 } 171 172 // Do the wait immediately. Note that doing the wait here eats almost 173 // all the performance anyway, so we only gain something if we're 174 // using temporal decoupling. 175 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { 176 wait(mDMIData.get_write_latency()); 177 178 } else { 179 wait(mDMIData.get_read_latency()); 180 } 181 182 logEndTransaction(trans); 183 184 } else { // we need a full transaction 185 sc_dt::uint64 addr = trans.get_address(); //Save address before it is mutated 186 socket->b_transport(trans, t); 187 wait(t); 188 logEndTransaction(trans); 189 190 // Acquire DMI pointer on is available: 191 if (trans.is_dmi_allowed()) 192 { 193 dmi_type tmp; 194 tmp.init(); 195 trans.set_address(addr); //restore address, in case it was mutated. 196 trans.set_write(); 197 if ( socket->get_direct_mem_ptr(trans, tmp) 198 && tmp.is_write_allowed() ) 199 { 200 mDMIData = tmp; 201 } 202 } 203 } 204 } 205 wait(); 206 } 207 208 sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) 209 { 210 // We should never be called 211 assert(0); 212 return tlm::TLM_COMPLETED; 213 } 214 215 void invalidate(dmi_type& dmiData) 216 { 217 dmiData.set_start_address(1); 218 dmiData.set_end_address(0); 219 } 220 221 // Invalidate DMI pointer(s) 222 void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, 223 sc_dt::uint64 end_range) 224 { 225 // do the invalidation if there is an address range overlap 226 if (start_range <= mDMIData.get_end_address ()&& 227 end_range >= mDMIData.get_start_address()) { 228 std::cout << name() << ": got DMI pointer invalidation" 229 << " @ " << sc_core::sc_time_stamp() << std::endl; 230 231 invalidate(mDMIData); 232 } else { 233 std::cout << name() << ": ignored DMI invalidation for addresses " 234 << std::hex << start_range << ", " 235 << end_range << std::dec 236 << " @ " << sc_core::sc_time_stamp() << std::endl; 237 } 238 } 239 240 // Test for transport_dbg: 241 // FIXME: use a configurable address 242 void end_of_simulation() 243 { 244 std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl 245 << std::endl; 246 unsigned char data[32]; 247 248 transaction_type trans; 249 trans.set_address(mBaseAddress); 250 trans.set_data_length(32); 251 trans.set_data_ptr(data); 252 trans.set_read(); 253 254 unsigned int n = socket->transport_dbg(trans); 255 256 std::cout << "Mem @" << std::hex << mBaseAddress << std::endl; 257 unsigned int j = 0; 258 259 if (n > 0) 260 { 261 // always align endianness, so that we don't get a diff when 262 // printing the raw data 263 int e_start = 0; 264 int e_end = 4; 265 int e_increment = 1; 266 if (!tlm::host_has_little_endianness()) 267 { 268 e_start = 3; 269 e_end = -1; 270 e_increment = -1; 271 } 272 273 for (unsigned int i=0; i<n; i+=4) 274 { 275 for (int k=e_start; k!=e_end; k+=e_increment) 276 { 277 std::cout << std::setw(2) << std::setfill('0') 278 << (int)data[i+k]; 279 j++; 280 if (j==16) { 281 j=0; 282 std::cout << std::endl; 283 } else { 284 std::cout << " "; 285 } 286 } 287 } 288 } 289 else 290 { 291 std::cout << "ERROR: debug transaction didn't give data." << std::endl; 292 } 293 std::cout << std::dec << std::endl; 294 } 295private: 296 dmi_type mDMIData; 297 298 sc_core::sc_event mEndEvent; 299 unsigned int mNrOfTransactions; 300 unsigned int mBaseAddress; 301 unsigned int mTransactionCount; 302 unsigned int mData; 303}; 304 305#endif 306