tlm_to_gem5.cc (13821:f9252f27ded7) | tlm_to_gem5.cc (13823:040971e0f728) |
---|---|
1/* 2 * Copyright 2019 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright --- 46 unchanged lines hidden (view full) --- 55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 * 57 * Authors: Gabe Black 58 * Christian Menard 59 */ 60 61#include "systemc/tlm_bridge/tlm_to_gem5.hh" 62 | 1/* 2 * Copyright 2019 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright --- 46 unchanged lines hidden (view full) --- 55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 * 57 * Authors: Gabe Black 58 * Christian Menard 59 */ 60 61#include "systemc/tlm_bridge/tlm_to_gem5.hh" 62 |
63#include "params/TlmToGem5Bridge32.hh" 64#include "params/TlmToGem5Bridge64.hh" |
|
63#include "sim/system.hh" 64#include "systemc/ext/core/sc_module_name.hh" 65 66namespace sc_gem5 67{ 68 | 65#include "sim/system.hh" 66#include "systemc/ext/core/sc_module_name.hh" 67 68namespace sc_gem5 69{ 70 |
71template <unsigned int BITWIDTH> |
|
69void | 72void |
70TlmToGem5Bridge::sendEndReq(tlm::tlm_generic_payload &trans) | 73TlmToGem5Bridge<BITWIDTH>::sendEndReq(tlm::tlm_generic_payload &trans) |
71{ 72 tlm::tlm_phase phase = tlm::END_REQ; 73 auto delay = sc_core::SC_ZERO_TIME; 74 75 auto status = socket->nb_transport_bw(trans, phase, delay); 76 panic_if(status != tlm::TLM_ACCEPTED, 77 "Unexpected status after sending END_REQ"); 78} 79 | 74{ 75 tlm::tlm_phase phase = tlm::END_REQ; 76 auto delay = sc_core::SC_ZERO_TIME; 77 78 auto status = socket->nb_transport_bw(trans, phase, delay); 79 panic_if(status != tlm::TLM_ACCEPTED, 80 "Unexpected status after sending END_REQ"); 81} 82 |
83template <unsigned int BITWIDTH> |
|
80void | 84void |
81TlmToGem5Bridge::sendBeginResp(tlm::tlm_generic_payload &trans, 82 sc_core::sc_time &delay) | 85TlmToGem5Bridge<BITWIDTH>::sendBeginResp(tlm::tlm_generic_payload &trans, 86 sc_core::sc_time &delay) |
83{ 84 tlm::tlm_phase phase = tlm::BEGIN_RESP; 85 86 trans.set_response_status(tlm::TLM_OK_RESPONSE); 87 88 auto status = socket->nb_transport_bw(trans, phase, delay); 89 90 if (status == tlm::TLM_COMPLETED || 91 (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) { 92 // transaction completed -> no need to wait for tlm::END_RESP 93 responseInProgress = false; 94 } else if (status == tlm::TLM_ACCEPTED) { 95 // we need to wait for tlm::END_RESP 96 responseInProgress = true; 97 } else { 98 panic("Unexpected status after sending BEGIN_RESP"); 99 } 100} 101 | 87{ 88 tlm::tlm_phase phase = tlm::BEGIN_RESP; 89 90 trans.set_response_status(tlm::TLM_OK_RESPONSE); 91 92 auto status = socket->nb_transport_bw(trans, phase, delay); 93 94 if (status == tlm::TLM_COMPLETED || 95 (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) { 96 // transaction completed -> no need to wait for tlm::END_RESP 97 responseInProgress = false; 98 } else if (status == tlm::TLM_ACCEPTED) { 99 // we need to wait for tlm::END_RESP 100 responseInProgress = true; 101 } else { 102 panic("Unexpected status after sending BEGIN_RESP"); 103 } 104} 105 |
106template <unsigned int BITWIDTH> |
|
102void | 107void |
103TlmToGem5Bridge::handleBeginReq(tlm::tlm_generic_payload &trans) | 108TlmToGem5Bridge<BITWIDTH>::handleBeginReq(tlm::tlm_generic_payload &trans) |
104{ 105 sc_assert(!waitForRetry); 106 sc_assert(pendingRequest == nullptr); 107 sc_assert(pendingPacket == nullptr); 108 109 trans.acquire(); 110 111 PacketPtr pkt = nullptr; --- 19 unchanged lines hidden (view full) --- 131 trans.release(); 132 } else { // port is blocked -> wait for retry before sending END_REQ 133 waitForRetry = true; 134 pendingRequest = &trans; 135 pendingPacket = pkt; 136 } 137} 138 | 109{ 110 sc_assert(!waitForRetry); 111 sc_assert(pendingRequest == nullptr); 112 sc_assert(pendingPacket == nullptr); 113 114 trans.acquire(); 115 116 PacketPtr pkt = nullptr; --- 19 unchanged lines hidden (view full) --- 136 trans.release(); 137 } else { // port is blocked -> wait for retry before sending END_REQ 138 waitForRetry = true; 139 pendingRequest = &trans; 140 pendingPacket = pkt; 141 } 142} 143 |
144template <unsigned int BITWIDTH> |
|
139void | 145void |
140TlmToGem5Bridge::handleEndResp(tlm::tlm_generic_payload &trans) | 146TlmToGem5Bridge<BITWIDTH>::handleEndResp(tlm::tlm_generic_payload &trans) |
141{ 142 sc_assert(responseInProgress); 143 144 responseInProgress = false; 145 146 checkTransaction(trans); 147 148 if (needToSendRetry) { 149 bmp.sendRetryResp(); 150 needToSendRetry = false; 151 } 152} 153 | 147{ 148 sc_assert(responseInProgress); 149 150 responseInProgress = false; 151 152 checkTransaction(trans); 153 154 if (needToSendRetry) { 155 bmp.sendRetryResp(); 156 needToSendRetry = false; 157 } 158} 159 |
160template <unsigned int BITWIDTH> |
|
154PacketPtr | 161PacketPtr |
155TlmToGem5Bridge::generatePacket(tlm::tlm_generic_payload &trans) | 162TlmToGem5Bridge<BITWIDTH>::generatePacket(tlm::tlm_generic_payload &trans) |
156{ 157 MemCmd cmd; 158 159 switch (trans.get_command()) { 160 case tlm::TLM_READ_COMMAND: 161 cmd = MemCmd::ReadReq; 162 break; 163 case tlm::TLM_WRITE_COMMAND: --- 15 unchanged lines hidden (view full) --- 179 * the gem5 world as a response. 180 */ 181 auto pkt = new Packet(req, cmd); 182 pkt->dataStatic(trans.get_data_ptr()); 183 184 return pkt; 185} 186 | 163{ 164 MemCmd cmd; 165 166 switch (trans.get_command()) { 167 case tlm::TLM_READ_COMMAND: 168 cmd = MemCmd::ReadReq; 169 break; 170 case tlm::TLM_WRITE_COMMAND: --- 15 unchanged lines hidden (view full) --- 186 * the gem5 world as a response. 187 */ 188 auto pkt = new Packet(req, cmd); 189 pkt->dataStatic(trans.get_data_ptr()); 190 191 return pkt; 192} 193 |
194template <unsigned int BITWIDTH> |
|
187void | 195void |
188TlmToGem5Bridge::destroyPacket(PacketPtr pkt) | 196TlmToGem5Bridge<BITWIDTH>::destroyPacket(PacketPtr pkt) |
189{ 190 delete pkt; 191} 192 | 197{ 198 delete pkt; 199} 200 |
201template <unsigned int BITWIDTH> |
|
193void | 202void |
194TlmToGem5Bridge::checkTransaction(tlm::tlm_generic_payload &trans) | 203TlmToGem5Bridge<BITWIDTH>::checkTransaction(tlm::tlm_generic_payload &trans) |
195{ 196 if (trans.is_response_error()) { 197 std::stringstream ss; 198 ss << "Transaction returned with error, response status = " 199 << trans.get_response_string(); 200 SC_REPORT_ERROR("TLM-2", ss.str().c_str()); 201 } 202} 203 | 204{ 205 if (trans.is_response_error()) { 206 std::stringstream ss; 207 ss << "Transaction returned with error, response status = " 208 << trans.get_response_string(); 209 SC_REPORT_ERROR("TLM-2", ss.str().c_str()); 210 } 211} 212 |
213template <unsigned int BITWIDTH> |
|
204void | 214void |
205TlmToGem5Bridge::peq_cb(tlm::tlm_generic_payload &trans, 206 const tlm::tlm_phase &phase) | 215TlmToGem5Bridge<BITWIDTH>::peq_cb(tlm::tlm_generic_payload &trans, 216 const tlm::tlm_phase &phase) |
207{ 208 switch (phase) { 209 case tlm::BEGIN_REQ: 210 handleBeginReq(trans); 211 break; 212 case tlm::END_RESP: 213 handleEndResp(trans); 214 break; 215 default: 216 panic("unimplemented phase in callback"); 217 } 218} 219 | 217{ 218 switch (phase) { 219 case tlm::BEGIN_REQ: 220 handleBeginReq(trans); 221 break; 222 case tlm::END_RESP: 223 handleEndResp(trans); 224 break; 225 default: 226 panic("unimplemented phase in callback"); 227 } 228} 229 |
230template <unsigned int BITWIDTH> |
|
220tlm::tlm_sync_enum | 231tlm::tlm_sync_enum |
221TlmToGem5Bridge::nb_transport_fw( | 232TlmToGem5Bridge<BITWIDTH>::nb_transport_fw( |
222 tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, 223 sc_core::sc_time &delay) 224{ 225 unsigned len = trans.get_data_length(); 226 unsigned char *byteEnable = trans.get_byte_enable_ptr(); 227 unsigned width = trans.get_streaming_width(); 228 229 // check the transaction attributes for unsupported features ... --- 7 unchanged lines hidden (view full) --- 237 } 238 239 // ... and queue the valid transaction 240 trans.acquire(); 241 peq.notify(trans, phase, delay); 242 return tlm::TLM_ACCEPTED; 243} 244 | 233 tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, 234 sc_core::sc_time &delay) 235{ 236 unsigned len = trans.get_data_length(); 237 unsigned char *byteEnable = trans.get_byte_enable_ptr(); 238 unsigned width = trans.get_streaming_width(); 239 240 // check the transaction attributes for unsupported features ... --- 7 unchanged lines hidden (view full) --- 248 } 249 250 // ... and queue the valid transaction 251 trans.acquire(); 252 peq.notify(trans, phase, delay); 253 return tlm::TLM_ACCEPTED; 254} 255 |
256template <unsigned int BITWIDTH> |
|
245void | 257void |
246TlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans, 247 sc_core::sc_time &t) | 258TlmToGem5Bridge<BITWIDTH>::b_transport(tlm::tlm_generic_payload &trans, 259 sc_core::sc_time &t) |
248{ 249 Gem5SystemC::Gem5Extension *extension = nullptr; 250 trans.get_extension(extension); 251 252 PacketPtr pkt = nullptr; 253 254 // If there is an extension, this transaction was initiated by the gem5 255 // world and we can pipe through the original packet. --- 17 unchanged lines hidden (view full) --- 273 t += delay; 274 275 if (extension == nullptr) 276 destroyPacket(pkt); 277 278 trans.set_response_status(tlm::TLM_OK_RESPONSE); 279} 280 | 260{ 261 Gem5SystemC::Gem5Extension *extension = nullptr; 262 trans.get_extension(extension); 263 264 PacketPtr pkt = nullptr; 265 266 // If there is an extension, this transaction was initiated by the gem5 267 // world and we can pipe through the original packet. --- 17 unchanged lines hidden (view full) --- 285 t += delay; 286 287 if (extension == nullptr) 288 destroyPacket(pkt); 289 290 trans.set_response_status(tlm::TLM_OK_RESPONSE); 291} 292 |
293template <unsigned int BITWIDTH> |
|
281unsigned int | 294unsigned int |
282TlmToGem5Bridge::transport_dbg(tlm::tlm_generic_payload &trans) | 295TlmToGem5Bridge<BITWIDTH>::transport_dbg(tlm::tlm_generic_payload &trans) |
283{ 284 Gem5SystemC::Gem5Extension *extension = nullptr; 285 trans.get_extension(extension); 286 287 // If there is an extension, this transaction was initiated by the gem5 288 // world and we can pipe through the original packet. 289 if (extension != nullptr) { 290 extension->setPipeThrough(); --- 4 unchanged lines hidden (view full) --- 295 bmp.sendFunctional(pkt); 296 destroyPacket(pkt); 297 } 298 } 299 300 return trans.get_data_length(); 301} 302 | 296{ 297 Gem5SystemC::Gem5Extension *extension = nullptr; 298 trans.get_extension(extension); 299 300 // If there is an extension, this transaction was initiated by the gem5 301 // world and we can pipe through the original packet. 302 if (extension != nullptr) { 303 extension->setPipeThrough(); --- 4 unchanged lines hidden (view full) --- 308 bmp.sendFunctional(pkt); 309 destroyPacket(pkt); 310 } 311 } 312 313 return trans.get_data_length(); 314} 315 |
316template <unsigned int BITWIDTH> |
|
303bool | 317bool |
304TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, 305 tlm::tlm_dmi &dmi_data) | 318TlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, 319 tlm::tlm_dmi &dmi_data) |
306{ 307 return false; 308} 309 | 320{ 321 return false; 322} 323 |
324template <unsigned int BITWIDTH> |
|
310bool | 325bool |
311TlmToGem5Bridge::recvTimingResp(PacketPtr pkt) | 326TlmToGem5Bridge<BITWIDTH>::recvTimingResp(PacketPtr pkt) |
312{ 313 // exclusion rule 314 // We need to Wait for END_RESP before sending next BEGIN_RESP 315 if (responseInProgress) { 316 sc_assert(!needToSendRetry); 317 needToSendRetry = true; 318 return false; 319 } --- 29 unchanged lines hidden (view full) --- 349 sc_assert(extension->isPipeThrough()); 350 351 sendBeginResp(trans, delay); 352 trans.release(); 353 354 return true; 355} 356 | 327{ 328 // exclusion rule 329 // We need to Wait for END_RESP before sending next BEGIN_RESP 330 if (responseInProgress) { 331 sc_assert(!needToSendRetry); 332 needToSendRetry = true; 333 return false; 334 } --- 29 unchanged lines hidden (view full) --- 364 sc_assert(extension->isPipeThrough()); 365 366 sendBeginResp(trans, delay); 367 trans.release(); 368 369 return true; 370} 371 |
372template <unsigned int BITWIDTH> |
|
357void | 373void |
358TlmToGem5Bridge::recvReqRetry() | 374TlmToGem5Bridge<BITWIDTH>::recvReqRetry() |
359{ 360 sc_assert(waitForRetry); 361 sc_assert(pendingRequest != nullptr); 362 sc_assert(pendingPacket != nullptr); 363 364 if (bmp.sendTimingReq(pendingPacket)) { 365 waitForRetry = false; 366 pendingPacket = nullptr; 367 368 auto &trans = *pendingRequest; 369 sendEndReq(trans); 370 trans.release(); 371 372 pendingRequest = nullptr; 373 } 374} 375 | 375{ 376 sc_assert(waitForRetry); 377 sc_assert(pendingRequest != nullptr); 378 sc_assert(pendingPacket != nullptr); 379 380 if (bmp.sendTimingReq(pendingPacket)) { 381 waitForRetry = false; 382 pendingPacket = nullptr; 383 384 auto &trans = *pendingRequest; 385 sendEndReq(trans); 386 trans.release(); 387 388 pendingRequest = nullptr; 389 } 390} 391 |
392template <unsigned int BITWIDTH> |
|
376void | 393void |
377TlmToGem5Bridge::recvRangeChange() | 394TlmToGem5Bridge<BITWIDTH>::recvRangeChange() |
378{ 379 SC_REPORT_WARNING("TlmToGem5Bridge", 380 "received address range change but ignored it"); 381} 382 | 395{ 396 SC_REPORT_WARNING("TlmToGem5Bridge", 397 "received address range change but ignored it"); 398} 399 |
400template <unsigned int BITWIDTH> |
|
383::Port & | 401::Port & |
384TlmToGem5Bridge::gem5_getPort(const std::string &if_name, int idx) | 402TlmToGem5Bridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx) |
385{ 386 if (if_name == "gem5") 387 return bmp; 388 else if (if_name == "tlm") 389 return wrapper; 390 391 return sc_core::sc_module::gem5_getPort(if_name, idx); 392} 393 | 403{ 404 if (if_name == "gem5") 405 return bmp; 406 else if (if_name == "tlm") 407 return wrapper; 408 409 return sc_core::sc_module::gem5_getPort(if_name, idx); 410} 411 |
394TlmToGem5Bridge::TlmToGem5Bridge( | 412template <unsigned int BITWIDTH> 413TlmToGem5Bridge<BITWIDTH>::TlmToGem5Bridge( |
395 Params *params, const sc_core::sc_module_name &mn) : | 414 Params *params, const sc_core::sc_module_name &mn) : |
396 sc_core::sc_module(mn), peq(this, &TlmToGem5Bridge::peq_cb), | 415 TlmToGem5BridgeBase(mn), peq(this, &TlmToGem5Bridge<BITWIDTH>::peq_cb), |
397 waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr), 398 needToSendRetry(false), responseInProgress(false), 399 bmp(std::string(name()) + "master", *this), socket("tlm_socket"), 400 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), 401 system(params->system), 402 masterId(params->system->getGlobalMasterId( 403 std::string("[systemc].") + name())) 404{ 405} 406 | 416 waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr), 417 needToSendRetry(false), responseInProgress(false), 418 bmp(std::string(name()) + "master", *this), socket("tlm_socket"), 419 wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), 420 system(params->system), 421 masterId(params->system->getGlobalMasterId( 422 std::string("[systemc].") + name())) 423{ 424} 425 |
426template <unsigned int BITWIDTH> |
|
407void | 427void |
408TlmToGem5Bridge::before_end_of_elaboration() | 428TlmToGem5Bridge<BITWIDTH>::before_end_of_elaboration() |
409{ 410 /* 411 * Register the TLM non-blocking interface when using gem5 Timing mode and 412 * the TLM blocking interface when using the gem5 Atomic mode. 413 * Then the magic (TM) in simple_target_socket automatically transforms 414 * non-blocking in blocking transactions and vice versa. 415 * 416 * NOTE: The mode may change during execution. 417 */ 418 if (system->isTimingMode()) { 419 SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface"); 420 socket.register_nb_transport_fw( | 429{ 430 /* 431 * Register the TLM non-blocking interface when using gem5 Timing mode and 432 * the TLM blocking interface when using the gem5 Atomic mode. 433 * Then the magic (TM) in simple_target_socket automatically transforms 434 * non-blocking in blocking transactions and vice versa. 435 * 436 * NOTE: The mode may change during execution. 437 */ 438 if (system->isTimingMode()) { 439 SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface"); 440 socket.register_nb_transport_fw( |
421 this, &TlmToGem5Bridge::nb_transport_fw); | 441 this, &TlmToGem5Bridge<BITWIDTH>::nb_transport_fw); |
422 } else if (system->isAtomicMode()) { 423 SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface"); 424 socket.register_b_transport( | 442 } else if (system->isAtomicMode()) { 443 SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface"); 444 socket.register_b_transport( |
425 this, &TlmToGem5Bridge::b_transport); | 445 this, &TlmToGem5Bridge<BITWIDTH>::b_transport); |
426 } else { 427 panic("gem5 operates neither in Timing nor in Atomic mode"); 428 } 429 | 446 } else { 447 panic("gem5 operates neither in Timing nor in Atomic mode"); 448 } 449 |
430 socket.register_transport_dbg(this, &TlmToGem5Bridge::transport_dbg); | 450 socket.register_transport_dbg( 451 this, &TlmToGem5Bridge<BITWIDTH>::transport_dbg); |
431 432 sc_core::sc_module::before_end_of_elaboration(); 433} 434 435} // namespace sc_gem5 436 | 452 453 sc_core::sc_module::before_end_of_elaboration(); 454} 455 456} // namespace sc_gem5 457 |
437sc_gem5::TlmToGem5Bridge * 438TlmToGem5BridgeParams::create() | 458sc_gem5::TlmToGem5Bridge<32> * 459TlmToGem5Bridge32Params::create() |
439{ | 460{ |
440 return new sc_gem5::TlmToGem5Bridge( | 461 return new sc_gem5::TlmToGem5Bridge<32>( |
441 this, sc_core::sc_module_name(name.c_str())); 442} | 462 this, sc_core::sc_module_name(name.c_str())); 463} |
464 465sc_gem5::TlmToGem5Bridge<64> * 466TlmToGem5Bridge64Params::create() 467{ 468 return new sc_gem5::TlmToGem5Bridge<64>( 469 this, sc_core::sc_module_name(name.c_str())); 470} |
|