gem5_to_tlm.cc revision 13846
113821Sgabeblack@google.com/* 213821Sgabeblack@google.com * Copyright 2019 Google, Inc. 313821Sgabeblack@google.com * 413821Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 513821Sgabeblack@google.com * modification, are permitted provided that the following conditions are 613821Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 713821Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 813821Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 913821Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1013821Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1113821Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1213821Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1313821Sgabeblack@google.com * this software without specific prior written permission. 1413821Sgabeblack@google.com * 1513821Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1613821Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1713821Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1813821Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1913821Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2013821Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2113821Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2213821Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2313821Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2413821Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2513821Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2613821Sgabeblack@google.com * 2713821Sgabeblack@google.com * Copyright (c) 2015, University of Kaiserslautern 2813821Sgabeblack@google.com * Copyright (c) 2016, Dresden University of Technology (TU Dresden) 2913821Sgabeblack@google.com * All rights reserved. 3013821Sgabeblack@google.com * 3113821Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 3213821Sgabeblack@google.com * modification, are permitted provided that the following conditions are 3313821Sgabeblack@google.com * met: 3413821Sgabeblack@google.com * 3513821Sgabeblack@google.com * 1. Redistributions of source code must retain the above copyright notice, 3613821Sgabeblack@google.com * this list of conditions and the following disclaimer. 3713821Sgabeblack@google.com * 3813821Sgabeblack@google.com * 2. Redistributions in binary form must reproduce the above copyright 3913821Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 4013821Sgabeblack@google.com * documentation and/or other materials provided with the distribution. 4113821Sgabeblack@google.com * 4213821Sgabeblack@google.com * 3. Neither the name of the copyright holder nor the names of its 4313821Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 4413821Sgabeblack@google.com * this software without specific prior written permission. 4513821Sgabeblack@google.com * 4613821Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 4713821Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 4813821Sgabeblack@google.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4913821Sgabeblack@google.com * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 5013821Sgabeblack@google.com * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 5113821Sgabeblack@google.com * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 5213821Sgabeblack@google.com * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 5313821Sgabeblack@google.com * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 5413821Sgabeblack@google.com * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 5513821Sgabeblack@google.com * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 5613821Sgabeblack@google.com * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5713821Sgabeblack@google.com * 5813821Sgabeblack@google.com * Authors: Gabe Black 5913821Sgabeblack@google.com * Matthias Jung 6013821Sgabeblack@google.com * Abdul Mutaal Ahmad 6113821Sgabeblack@google.com * Christian Menard 6213821Sgabeblack@google.com */ 6313821Sgabeblack@google.com 6413821Sgabeblack@google.com#include "systemc/tlm_bridge/gem5_to_tlm.hh" 6513821Sgabeblack@google.com 6613823Sgabeblack@google.com#include "params/Gem5ToTlmBridge32.hh" 6713823Sgabeblack@google.com#include "params/Gem5ToTlmBridge64.hh" 6813821Sgabeblack@google.com#include "sim/system.hh" 6913821Sgabeblack@google.com#include "systemc/tlm_bridge/sc_ext.hh" 7013821Sgabeblack@google.com#include "systemc/tlm_bridge/sc_mm.hh" 7113821Sgabeblack@google.com 7213821Sgabeblack@google.comnamespace sc_gem5 7313821Sgabeblack@google.com{ 7413821Sgabeblack@google.com 7513821Sgabeblack@google.com/** 7613821Sgabeblack@google.com * Instantiate a tlm memory manager that takes care about all the 7713821Sgabeblack@google.com * tlm transactions in the system. 7813821Sgabeblack@google.com */ 7913821Sgabeblack@google.comGem5SystemC::MemoryManager mm; 8013821Sgabeblack@google.com 8113821Sgabeblack@google.com/** 8213821Sgabeblack@google.com * Convert a gem5 packet to a TLM payload by copying all the relevant 8313846Sgabeblack@google.com * information to new tlm payload. 8413821Sgabeblack@google.com */ 8513846Sgabeblack@google.comtlm::tlm_generic_payload * 8613846Sgabeblack@google.compacket2payload(PacketPtr packet) 8713821Sgabeblack@google.com{ 8813846Sgabeblack@google.com tlm::tlm_generic_payload *trans = mm.allocate(); 8913846Sgabeblack@google.com trans->acquire(); 9013846Sgabeblack@google.com 9113846Sgabeblack@google.com trans->set_address(packet->getAddr()); 9213821Sgabeblack@google.com 9313821Sgabeblack@google.com /* Check if this transaction was allocated by mm */ 9413846Sgabeblack@google.com sc_assert(trans->has_mm()); 9513821Sgabeblack@google.com 9613821Sgabeblack@google.com unsigned int size = packet->getSize(); 9713821Sgabeblack@google.com unsigned char *data = packet->getPtr<unsigned char>(); 9813821Sgabeblack@google.com 9913846Sgabeblack@google.com trans->set_data_length(size); 10013846Sgabeblack@google.com trans->set_streaming_width(size); 10113846Sgabeblack@google.com trans->set_data_ptr(data); 10213821Sgabeblack@google.com 10313846Sgabeblack@google.com if ((packet->req->getFlags() & Request::NO_ACCESS) != 0) { 10413846Sgabeblack@google.com /* Do nothing */ 10513846Sgabeblack@google.com trans->set_command(tlm::TLM_IGNORE_COMMAND); 10613846Sgabeblack@google.com } else if (packet->isRead()) { 10713846Sgabeblack@google.com trans->set_command(tlm::TLM_READ_COMMAND); 10813821Sgabeblack@google.com } else if (packet->isInvalidate()) { 10913821Sgabeblack@google.com /* Do nothing */ 11013846Sgabeblack@google.com trans->set_command(tlm::TLM_IGNORE_COMMAND); 11113821Sgabeblack@google.com } else if (packet->isWrite()) { 11213846Sgabeblack@google.com trans->set_command(tlm::TLM_WRITE_COMMAND); 11313821Sgabeblack@google.com } else { 11413821Sgabeblack@google.com SC_REPORT_FATAL("Gem5ToTlmBridge", "No R/W packet"); 11513821Sgabeblack@google.com } 11613846Sgabeblack@google.com 11713846Sgabeblack@google.com // Attach the packet pointer to the TLM transaction to keep track. 11813846Sgabeblack@google.com auto *extension = new Gem5SystemC::Gem5Extension(packet); 11913846Sgabeblack@google.com trans->set_auto_extension(extension); 12013846Sgabeblack@google.com 12113846Sgabeblack@google.com return trans; 12213821Sgabeblack@google.com} 12313821Sgabeblack@google.com 12413823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 12513821Sgabeblack@google.comvoid 12613823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::pec( 12713823Sgabeblack@google.com Gem5SystemC::PayloadEvent<Gem5ToTlmBridge<BITWIDTH>> *pe, 12813821Sgabeblack@google.com tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) 12913821Sgabeblack@google.com{ 13013821Sgabeblack@google.com sc_core::sc_time delay; 13113821Sgabeblack@google.com 13213821Sgabeblack@google.com if (phase == tlm::END_REQ || 13313821Sgabeblack@google.com (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) { 13413821Sgabeblack@google.com sc_assert(&trans == blockingRequest); 13513821Sgabeblack@google.com blockingRequest = nullptr; 13613821Sgabeblack@google.com 13713821Sgabeblack@google.com // Did another request arrive while blocked, schedule a retry. 13813821Sgabeblack@google.com if (needToSendRequestRetry) { 13913821Sgabeblack@google.com needToSendRequestRetry = false; 14013821Sgabeblack@google.com bsp.sendRetryReq(); 14113821Sgabeblack@google.com } 14213821Sgabeblack@google.com } 14313821Sgabeblack@google.com if (phase == tlm::BEGIN_RESP) { 14413821Sgabeblack@google.com auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans); 14513821Sgabeblack@google.com auto packet = extension.getPacket(); 14613821Sgabeblack@google.com 14713821Sgabeblack@google.com sc_assert(!blockingResponse); 14813821Sgabeblack@google.com 14913821Sgabeblack@google.com bool need_retry = false; 15013821Sgabeblack@google.com 15113821Sgabeblack@google.com /* 15213821Sgabeblack@google.com * If the packet was piped through and needs a response, we don't need 15313821Sgabeblack@google.com * to touch the packet and can forward it directly as a response. 15413821Sgabeblack@google.com * Otherwise, we need to make a response and send the transformed 15513821Sgabeblack@google.com * packet. 15613821Sgabeblack@google.com */ 15713821Sgabeblack@google.com if (extension.isPipeThrough()) { 15813821Sgabeblack@google.com if (packet->isResponse()) { 15913821Sgabeblack@google.com need_retry = !bsp.sendTimingResp(packet); 16013821Sgabeblack@google.com } 16113821Sgabeblack@google.com } else if (packet->needsResponse()) { 16213821Sgabeblack@google.com packet->makeResponse(); 16313821Sgabeblack@google.com need_retry = !bsp.sendTimingResp(packet); 16413821Sgabeblack@google.com } 16513821Sgabeblack@google.com 16613821Sgabeblack@google.com if (need_retry) { 16713821Sgabeblack@google.com blockingResponse = &trans; 16813821Sgabeblack@google.com } else { 16913821Sgabeblack@google.com if (phase == tlm::BEGIN_RESP) { 17013821Sgabeblack@google.com // Send END_RESP and we're finished: 17113821Sgabeblack@google.com tlm::tlm_phase fw_phase = tlm::END_RESP; 17213821Sgabeblack@google.com sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 17313821Sgabeblack@google.com socket->nb_transport_fw(trans, fw_phase, delay); 17413821Sgabeblack@google.com // Release the transaction with all the extensions. 17513821Sgabeblack@google.com trans.release(); 17613821Sgabeblack@google.com } 17713821Sgabeblack@google.com } 17813821Sgabeblack@google.com } 17913821Sgabeblack@google.com delete pe; 18013821Sgabeblack@google.com} 18113821Sgabeblack@google.com 18213846Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 18313846Sgabeblack@google.comMemBackdoorPtr 18413846Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::getBackdoor(tlm::tlm_generic_payload &trans) 18513846Sgabeblack@google.com{ 18613846Sgabeblack@google.com sc_dt::uint64 start = trans.get_address(); 18713846Sgabeblack@google.com sc_dt::uint64 end = start + trans.get_data_length(); 18813846Sgabeblack@google.com 18913846Sgabeblack@google.com // Check for a back door we already know about. 19013846Sgabeblack@google.com AddrRange r(start, end); 19113846Sgabeblack@google.com auto it = backdoorMap.contains(r); 19213846Sgabeblack@google.com if (it != backdoorMap.end()) 19313846Sgabeblack@google.com return it->second; 19413846Sgabeblack@google.com 19513846Sgabeblack@google.com // If not, ask the target for one. 19613846Sgabeblack@google.com tlm::tlm_dmi dmi_data; 19713846Sgabeblack@google.com if (!socket->get_direct_mem_ptr(trans, dmi_data)) 19813846Sgabeblack@google.com return nullptr; 19913846Sgabeblack@google.com 20013846Sgabeblack@google.com // If the target gave us one, translate it to a gem5 MemBackdoor and 20113846Sgabeblack@google.com // store it in our cache. 20213846Sgabeblack@google.com AddrRange dmi_r(dmi_data.get_start_address(), dmi_data.get_end_address()); 20313846Sgabeblack@google.com auto backdoor = new MemBackdoor( 20413846Sgabeblack@google.com dmi_r, dmi_data.get_dmi_ptr(), MemBackdoor::NoAccess); 20513846Sgabeblack@google.com backdoor->readable(dmi_data.is_read_allowed()); 20613846Sgabeblack@google.com backdoor->writeable(dmi_data.is_write_allowed()); 20713846Sgabeblack@google.com 20813846Sgabeblack@google.com backdoorMap.insert(dmi_r, backdoor); 20913846Sgabeblack@google.com 21013846Sgabeblack@google.com return backdoor; 21113846Sgabeblack@google.com} 21213846Sgabeblack@google.com 21313821Sgabeblack@google.com// Similar to TLM's blocking transport (LT) 21413823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 21513821Sgabeblack@google.comTick 21613823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvAtomic(PacketPtr packet) 21713821Sgabeblack@google.com{ 21813821Sgabeblack@google.com panic_if(packet->cacheResponding(), 21913821Sgabeblack@google.com "Should not see packets where cache is responding"); 22013821Sgabeblack@google.com 22113846Sgabeblack@google.com // Prepare the transaction. 22213846Sgabeblack@google.com auto *trans = packet2payload(packet); 22313846Sgabeblack@google.com 22413846Sgabeblack@google.com sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 22513846Sgabeblack@google.com 22613846Sgabeblack@google.com if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) { 22713846Sgabeblack@google.com // Execute b_transport: 22813846Sgabeblack@google.com socket->b_transport(*trans, delay); 22913846Sgabeblack@google.com } 23013846Sgabeblack@google.com 23113846Sgabeblack@google.com if (packet->needsResponse()) 23213846Sgabeblack@google.com packet->makeResponse(); 23313846Sgabeblack@google.com 23413846Sgabeblack@google.com trans->release(); 23513846Sgabeblack@google.com 23613846Sgabeblack@google.com return delay.value(); 23713846Sgabeblack@google.com} 23813846Sgabeblack@google.com 23913846Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 24013846Sgabeblack@google.comTick 24113846Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvAtomicBackdoor( 24213846Sgabeblack@google.com PacketPtr packet, MemBackdoorPtr &backdoor) 24313846Sgabeblack@google.com{ 24413846Sgabeblack@google.com panic_if(packet->cacheResponding(), 24513846Sgabeblack@google.com "Should not see packets where cache is responding"); 24613821Sgabeblack@google.com 24713821Sgabeblack@google.com sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 24813821Sgabeblack@google.com 24913821Sgabeblack@google.com // Prepare the transaction. 25013846Sgabeblack@google.com auto *trans = packet2payload(packet); 25113821Sgabeblack@google.com 25213846Sgabeblack@google.com if (trans->get_command() != tlm::TLM_IGNORE_COMMAND) { 25313846Sgabeblack@google.com // Execute b_transport: 25413821Sgabeblack@google.com socket->b_transport(*trans, delay); 25513846Sgabeblack@google.com // If the hint said we could use DMI, set that up. 25613846Sgabeblack@google.com if (trans->is_dmi_allowed()) 25713846Sgabeblack@google.com backdoor = getBackdoor(*trans); 25813821Sgabeblack@google.com } else { 25913846Sgabeblack@google.com // There's no transaction to piggy back on, so just request the 26013846Sgabeblack@google.com // backdoor normally. 26113846Sgabeblack@google.com backdoor = getBackdoor(*trans); 26213821Sgabeblack@google.com } 26313821Sgabeblack@google.com 26413846Sgabeblack@google.com if (packet->needsResponse()) 26513821Sgabeblack@google.com packet->makeResponse(); 26613821Sgabeblack@google.com 26713821Sgabeblack@google.com trans->release(); 26813821Sgabeblack@google.com 26913821Sgabeblack@google.com return delay.value(); 27013821Sgabeblack@google.com} 27113821Sgabeblack@google.com 27213823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 27313821Sgabeblack@google.comvoid 27413823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvFunctionalSnoop(PacketPtr packet) 27513821Sgabeblack@google.com{ 27613821Sgabeblack@google.com // Snooping should be implemented with tlm_dbg_transport. 27713821Sgabeblack@google.com SC_REPORT_FATAL("Gem5ToTlmBridge", 27813821Sgabeblack@google.com "unimplemented func.: recvFunctionalSnoop"); 27913821Sgabeblack@google.com} 28013821Sgabeblack@google.com 28113821Sgabeblack@google.com// Similar to TLM's non-blocking transport (AT). 28213823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 28313821Sgabeblack@google.combool 28413823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvTimingReq(PacketPtr packet) 28513821Sgabeblack@google.com{ 28613821Sgabeblack@google.com panic_if(packet->cacheResponding(), 28713821Sgabeblack@google.com "Should not see packets where cache is responding"); 28813821Sgabeblack@google.com 28913821Sgabeblack@google.com panic_if(!(packet->isRead() || packet->isWrite()), 29013821Sgabeblack@google.com "Should only see read and writes at TLM memory\n"); 29113821Sgabeblack@google.com 29213821Sgabeblack@google.com 29313821Sgabeblack@google.com // We should never get a second request after noting that a retry is 29413821Sgabeblack@google.com // required. 29513821Sgabeblack@google.com sc_assert(!needToSendRequestRetry); 29613821Sgabeblack@google.com 29713821Sgabeblack@google.com // Remember if a request comes in while we're blocked so that a retry 29813821Sgabeblack@google.com // can be sent to gem5. 29913821Sgabeblack@google.com if (blockingRequest) { 30013821Sgabeblack@google.com needToSendRequestRetry = true; 30113821Sgabeblack@google.com return false; 30213821Sgabeblack@google.com } 30313821Sgabeblack@google.com 30413821Sgabeblack@google.com /* 30513821Sgabeblack@google.com * NOTE: normal tlm is blocking here. But in our case we return false 30613821Sgabeblack@google.com * and tell gem5 when a retry can be done. This is the main difference 30713821Sgabeblack@google.com * in the protocol: 30813821Sgabeblack@google.com * if (requestInProgress) 30913821Sgabeblack@google.com * { 31013821Sgabeblack@google.com * wait(endRequestEvent); 31113821Sgabeblack@google.com * } 31213821Sgabeblack@google.com * requestInProgress = trans; 31313821Sgabeblack@google.com */ 31413821Sgabeblack@google.com 31513821Sgabeblack@google.com // Prepare the transaction. 31613846Sgabeblack@google.com auto *trans = packet2payload(packet); 31713821Sgabeblack@google.com 31813821Sgabeblack@google.com /* 31913821Sgabeblack@google.com * Pay for annotated transport delays. 32013821Sgabeblack@google.com * 32113821Sgabeblack@google.com * The header delay marks the point in time, when the packet first is seen 32213821Sgabeblack@google.com * by the transactor. This is the point in time when the transactor needs 32313821Sgabeblack@google.com * to send the BEGIN_REQ to the SystemC world. 32413821Sgabeblack@google.com * 32513821Sgabeblack@google.com * NOTE: We drop the payload delay here. Normally, the receiver would be 32613821Sgabeblack@google.com * responsible for handling the payload delay. In this case, however, 32713821Sgabeblack@google.com * the receiver is a SystemC module and has no notion of the gem5 32813821Sgabeblack@google.com * transport protocol and we cannot simply forward the 32913821Sgabeblack@google.com * payload delay to the receiving module. Instead, we expect the 33013821Sgabeblack@google.com * receiving SystemC module to model the payload delay by deferring 33113821Sgabeblack@google.com * the END_REQ. This could lead to incorrect delays, if the XBar 33213821Sgabeblack@google.com * payload delay is longer than the time the receiver needs to accept 33313821Sgabeblack@google.com * the request (time between BEGIN_REQ and END_REQ). 33413821Sgabeblack@google.com * 33513821Sgabeblack@google.com * TODO: We could detect the case described above by remembering the 33613821Sgabeblack@google.com * payload delay and comparing it to the time between BEGIN_REQ and 33713821Sgabeblack@google.com * END_REQ. Then, a warning should be printed. 33813821Sgabeblack@google.com */ 33913821Sgabeblack@google.com auto delay = sc_core::sc_time::from_value(packet->payloadDelay); 34013821Sgabeblack@google.com // Reset the delays 34113821Sgabeblack@google.com packet->payloadDelay = 0; 34213821Sgabeblack@google.com packet->headerDelay = 0; 34313821Sgabeblack@google.com 34413821Sgabeblack@google.com // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC 34513821Sgabeblack@google.com // Standard Page 507 for a visualisation of the procedure. 34613821Sgabeblack@google.com tlm::tlm_phase phase = tlm::BEGIN_REQ; 34713821Sgabeblack@google.com tlm::tlm_sync_enum status; 34813821Sgabeblack@google.com status = socket->nb_transport_fw(*trans, phase, delay); 34913821Sgabeblack@google.com // Check returned value: 35013821Sgabeblack@google.com if (status == tlm::TLM_ACCEPTED) { 35113821Sgabeblack@google.com sc_assert(phase == tlm::BEGIN_REQ); 35213821Sgabeblack@google.com // Accepted but is now blocking until END_REQ (exclusion rule). 35313821Sgabeblack@google.com blockingRequest = trans; 35413821Sgabeblack@google.com } else if (status == tlm::TLM_UPDATED) { 35513821Sgabeblack@google.com // The Timing annotation must be honored: 35613821Sgabeblack@google.com sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP); 35713821Sgabeblack@google.com 35813821Sgabeblack@google.com auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 35913821Sgabeblack@google.com *this, &Gem5ToTlmBridge::pec, "PEQ"); 36013821Sgabeblack@google.com Tick nextEventTick = curTick() + delay.value(); 36113821Sgabeblack@google.com system->wakeupEventQueue(nextEventTick); 36213821Sgabeblack@google.com system->schedule(pe, nextEventTick); 36313821Sgabeblack@google.com } else if (status == tlm::TLM_COMPLETED) { 36413821Sgabeblack@google.com // Transaction is over nothing has do be done. 36513821Sgabeblack@google.com sc_assert(phase == tlm::END_RESP); 36613821Sgabeblack@google.com trans->release(); 36713821Sgabeblack@google.com } 36813821Sgabeblack@google.com 36913821Sgabeblack@google.com return true; 37013821Sgabeblack@google.com} 37113821Sgabeblack@google.com 37213823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 37313821Sgabeblack@google.combool 37413823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvTimingSnoopResp(PacketPtr packet) 37513821Sgabeblack@google.com{ 37613821Sgabeblack@google.com // Snooping should be implemented with tlm_dbg_transport. 37713821Sgabeblack@google.com SC_REPORT_FATAL("Gem5ToTlmBridge", 37813821Sgabeblack@google.com "unimplemented func.: recvTimingSnoopResp"); 37913821Sgabeblack@google.com return false; 38013821Sgabeblack@google.com} 38113821Sgabeblack@google.com 38213823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 38313821Sgabeblack@google.combool 38413823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::tryTiming(PacketPtr packet) 38513821Sgabeblack@google.com{ 38613821Sgabeblack@google.com panic("tryTiming(PacketPtr) isn't implemented."); 38713821Sgabeblack@google.com} 38813821Sgabeblack@google.com 38913823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 39013821Sgabeblack@google.comvoid 39113823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvRespRetry() 39213821Sgabeblack@google.com{ 39313821Sgabeblack@google.com /* Retry a response */ 39413821Sgabeblack@google.com sc_assert(blockingResponse); 39513821Sgabeblack@google.com 39613821Sgabeblack@google.com tlm::tlm_generic_payload *trans = blockingResponse; 39713821Sgabeblack@google.com blockingResponse = nullptr; 39813821Sgabeblack@google.com PacketPtr packet = 39913821Sgabeblack@google.com Gem5SystemC::Gem5Extension::getExtension(trans).getPacket(); 40013821Sgabeblack@google.com 40113821Sgabeblack@google.com bool need_retry = !bsp.sendTimingResp(packet); 40213821Sgabeblack@google.com 40313821Sgabeblack@google.com sc_assert(!need_retry); 40413821Sgabeblack@google.com 40513821Sgabeblack@google.com sc_core::sc_time delay = sc_core::SC_ZERO_TIME; 40613821Sgabeblack@google.com tlm::tlm_phase phase = tlm::END_RESP; 40713821Sgabeblack@google.com socket->nb_transport_fw(*trans, phase, delay); 40813821Sgabeblack@google.com // Release transaction with all the extensions 40913821Sgabeblack@google.com trans->release(); 41013821Sgabeblack@google.com} 41113821Sgabeblack@google.com 41213821Sgabeblack@google.com// Similar to TLM's debug transport. 41313823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 41413821Sgabeblack@google.comvoid 41513823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::recvFunctional(PacketPtr packet) 41613821Sgabeblack@google.com{ 41713821Sgabeblack@google.com // Prepare the transaction. 41813846Sgabeblack@google.com auto *trans = packet2payload(packet); 41913821Sgabeblack@google.com 42013821Sgabeblack@google.com /* Execute Debug Transport: */ 42113821Sgabeblack@google.com unsigned int bytes = socket->transport_dbg(*trans); 42213821Sgabeblack@google.com if (bytes != trans->get_data_length()) { 42313821Sgabeblack@google.com SC_REPORT_FATAL("Gem5ToTlmBridge", 42413821Sgabeblack@google.com "debug transport was not completed"); 42513821Sgabeblack@google.com } 42613821Sgabeblack@google.com 42713821Sgabeblack@google.com trans->release(); 42813821Sgabeblack@google.com} 42913821Sgabeblack@google.com 43013823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 43113821Sgabeblack@google.comtlm::tlm_sync_enum 43213823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::nb_transport_bw(tlm::tlm_generic_payload &trans, 43313821Sgabeblack@google.com tlm::tlm_phase &phase, sc_core::sc_time &delay) 43413821Sgabeblack@google.com{ 43513821Sgabeblack@google.com auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>( 43613821Sgabeblack@google.com *this, &Gem5ToTlmBridge::pec, "PE"); 43713821Sgabeblack@google.com Tick nextEventTick = curTick() + delay.value(); 43813821Sgabeblack@google.com system->wakeupEventQueue(nextEventTick); 43913821Sgabeblack@google.com system->schedule(pe, nextEventTick); 44013821Sgabeblack@google.com return tlm::TLM_ACCEPTED; 44113821Sgabeblack@google.com} 44213821Sgabeblack@google.com 44313823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 44413846Sgabeblack@google.comvoid 44513846Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::invalidate_direct_mem_ptr( 44613846Sgabeblack@google.com sc_dt::uint64 start_range, sc_dt::uint64 end_range) 44713846Sgabeblack@google.com{ 44813846Sgabeblack@google.com AddrRange r(start_range, end_range); 44913846Sgabeblack@google.com 45013846Sgabeblack@google.com for (;;) { 45113846Sgabeblack@google.com auto it = backdoorMap.intersects(r); 45213846Sgabeblack@google.com if (it == backdoorMap.end()) 45313846Sgabeblack@google.com break; 45413846Sgabeblack@google.com 45513846Sgabeblack@google.com it->second->invalidate(); 45613846Sgabeblack@google.com delete it->second; 45713846Sgabeblack@google.com backdoorMap.erase(it); 45813846Sgabeblack@google.com }; 45913846Sgabeblack@google.com} 46013846Sgabeblack@google.com 46113846Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 46213823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::Gem5ToTlmBridge( 46313821Sgabeblack@google.com Params *params, const sc_core::sc_module_name &mn) : 46413823Sgabeblack@google.com Gem5ToTlmBridgeBase(mn), bsp(std::string(name()) + ".gem5", *this), 46513821Sgabeblack@google.com socket("tlm_socket"), 46613821Sgabeblack@google.com wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), 46713821Sgabeblack@google.com system(params->system), blockingRequest(nullptr), 46813821Sgabeblack@google.com needToSendRequestRetry(false), blockingResponse(nullptr), 46913821Sgabeblack@google.com addrRanges(params->addr_ranges.begin(), params->addr_ranges.end()) 47013821Sgabeblack@google.com{ 47113821Sgabeblack@google.com} 47213821Sgabeblack@google.com 47313823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 47413821Sgabeblack@google.com::Port & 47513823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx) 47613821Sgabeblack@google.com{ 47713821Sgabeblack@google.com if (if_name == "gem5") 47813821Sgabeblack@google.com return bsp; 47913821Sgabeblack@google.com else if (if_name == "tlm") 48013821Sgabeblack@google.com return wrapper; 48113821Sgabeblack@google.com 48213821Sgabeblack@google.com return sc_core::sc_module::gem5_getPort(if_name, idx); 48313821Sgabeblack@google.com} 48413821Sgabeblack@google.com 48513823Sgabeblack@google.comtemplate <unsigned int BITWIDTH> 48613821Sgabeblack@google.comvoid 48713823Sgabeblack@google.comGem5ToTlmBridge<BITWIDTH>::before_end_of_elaboration() 48813821Sgabeblack@google.com{ 48913821Sgabeblack@google.com bsp.sendRangeChange(); 49013821Sgabeblack@google.com 49113821Sgabeblack@google.com socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw); 49213846Sgabeblack@google.com socket.register_invalidate_direct_mem_ptr( 49313846Sgabeblack@google.com this, &Gem5ToTlmBridge::invalidate_direct_mem_ptr); 49413821Sgabeblack@google.com sc_core::sc_module::before_end_of_elaboration(); 49513821Sgabeblack@google.com} 49613821Sgabeblack@google.com 49713821Sgabeblack@google.com} // namespace sc_gem5 49813821Sgabeblack@google.com 49913823Sgabeblack@google.comsc_gem5::Gem5ToTlmBridge<32> * 50013823Sgabeblack@google.comGem5ToTlmBridge32Params::create() 50113821Sgabeblack@google.com{ 50213823Sgabeblack@google.com return new sc_gem5::Gem5ToTlmBridge<32>( 50313821Sgabeblack@google.com this, sc_core::sc_module_name(name.c_str())); 50413821Sgabeblack@google.com} 50513823Sgabeblack@google.com 50613823Sgabeblack@google.comsc_gem5::Gem5ToTlmBridge<64> * 50713823Sgabeblack@google.comGem5ToTlmBridge64Params::create() 50813823Sgabeblack@google.com{ 50913823Sgabeblack@google.com return new sc_gem5::Gem5ToTlmBridge<64>( 51013823Sgabeblack@google.com this, sc_core::sc_module_name(name.c_str())); 51113823Sgabeblack@google.com} 512