From e65a89e39b1c86e002e28a515508f5302a91a58f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 11 Mar 2019 16:02:26 -0700 Subject: [PATCH] systemc: Create unified gem5/TLM bridge SimObjects. These objects expose a standard TLM initiator or target socket with width 64, and a gem5 slave or master port. What goes in one type of port comes out the other with the appropriate conversion applied. Change-Id: I65e07f746d46d3db0197968b78fffc5ddaede9bf Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17232 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/tlm_bridge/SConscript | 5 + src/systemc/tlm_bridge/TlmBridge.py | 52 +++ src/systemc/tlm_bridge/gem5_to_tlm.cc | 422 ++++++++++++++++++++++++ src/systemc/tlm_bridge/gem5_to_tlm.hh | 189 +++++++++++ src/systemc/tlm_bridge/tlm_to_gem5.cc | 442 ++++++++++++++++++++++++++ src/systemc/tlm_bridge/tlm_to_gem5.hh | 170 ++++++++++ 6 files changed, 1280 insertions(+) create mode 100644 src/systemc/tlm_bridge/TlmBridge.py create mode 100644 src/systemc/tlm_bridge/gem5_to_tlm.cc create mode 100644 src/systemc/tlm_bridge/gem5_to_tlm.hh create mode 100644 src/systemc/tlm_bridge/tlm_to_gem5.cc create mode 100644 src/systemc/tlm_bridge/tlm_to_gem5.hh diff --git a/src/systemc/tlm_bridge/SConscript b/src/systemc/tlm_bridge/SConscript index 6d91436bb..df56fdfba 100644 --- a/src/systemc/tlm_bridge/SConscript +++ b/src/systemc/tlm_bridge/SConscript @@ -30,6 +30,11 @@ Import('*') if not env['USE_SYSTEMC']: Return() +SimObject('TlmBridge.py') + +Source('gem5_to_tlm.cc') +Source('tlm_to_gem5.cc') + Source('master_transactor.cc') Source('sc_ext.cc') Source('sc_master_port.cc') diff --git a/src/systemc/tlm_bridge/TlmBridge.py b/src/systemc/tlm_bridge/TlmBridge.py new file mode 100644 index 000000000..d2dff8600 --- /dev/null +++ b/src/systemc/tlm_bridge/TlmBridge.py @@ -0,0 +1,52 @@ +# Copyright 2019 Google, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +from m5.objects.SystemC import SystemC_ScModule +from m5.params import * +from m5.proxy import * + +class Gem5ToTlmBridge(SystemC_ScModule): + type = 'Gem5ToTlmBridge' + cxx_class = 'sc_gem5::Gem5ToTlmBridge' + cxx_header = 'systemc/tlm_bridge/gem5_to_tlm.hh' + + system = Param.System(Parent.any, "system") + + gem5 = SlavePort('gem5 slave port') + tlm = MasterPort('TLM initiator socket') + addr_ranges = VectorParam.AddrRange([], + 'Addresses served by this port\'s TLM side') + +class TlmToGem5Bridge(SystemC_ScModule): + type = 'TlmToGem5Bridge' + cxx_class = 'sc_gem5::TlmToGem5Bridge' + cxx_header = 'systemc/tlm_bridge/tlm_to_gem5.hh' + + system = Param.System(Parent.any, "system") + + gem5 = MasterPort('gem5 master port') + tlm = SlavePort('TLM target socket') diff --git a/src/systemc/tlm_bridge/gem5_to_tlm.cc b/src/systemc/tlm_bridge/gem5_to_tlm.cc new file mode 100644 index 000000000..06ed2abf3 --- /dev/null +++ b/src/systemc/tlm_bridge/gem5_to_tlm.cc @@ -0,0 +1,422 @@ +/* + * Copyright 2019 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Matthias Jung + * Abdul Mutaal Ahmad + * Christian Menard + */ + +#include "systemc/tlm_bridge/gem5_to_tlm.hh" + +#include "sim/system.hh" +#include "systemc/tlm_bridge/sc_ext.hh" +#include "systemc/tlm_bridge/sc_mm.hh" + +namespace sc_gem5 +{ + +/** + * Instantiate a tlm memory manager that takes care about all the + * tlm transactions in the system. + */ +Gem5SystemC::MemoryManager mm; + +/** + * Convert a gem5 packet to a TLM payload by copying all the relevant + * information to a previously allocated tlm payload + */ +void +packet2payload(PacketPtr packet, tlm::tlm_generic_payload &trans) +{ + trans.set_address(packet->getAddr()); + + /* Check if this transaction was allocated by mm */ + sc_assert(trans.has_mm()); + + unsigned int size = packet->getSize(); + unsigned char *data = packet->getPtr(); + + trans.set_data_length(size); + trans.set_streaming_width(size); + trans.set_data_ptr(data); + + if (packet->isRead()) { + trans.set_command(tlm::TLM_READ_COMMAND); + } else if (packet->isInvalidate()) { + /* Do nothing */ + } else if (packet->isWrite()) { + trans.set_command(tlm::TLM_WRITE_COMMAND); + } else { + SC_REPORT_FATAL("Gem5ToTlmBridge", "No R/W packet"); + } +} + +void +Gem5ToTlmBridge::pec(Gem5SystemC::PayloadEvent *pe, + tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase) +{ + sc_core::sc_time delay; + + if (phase == tlm::END_REQ || + (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) { + sc_assert(&trans == blockingRequest); + blockingRequest = nullptr; + + // Did another request arrive while blocked, schedule a retry. + if (needToSendRequestRetry) { + needToSendRequestRetry = false; + bsp.sendRetryReq(); + } + } + if (phase == tlm::BEGIN_RESP) { + auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans); + auto packet = extension.getPacket(); + + sc_assert(!blockingResponse); + + bool need_retry = false; + + /* + * If the packet was piped through and needs a response, we don't need + * to touch the packet and can forward it directly as a response. + * Otherwise, we need to make a response and send the transformed + * packet. + */ + if (extension.isPipeThrough()) { + if (packet->isResponse()) { + need_retry = !bsp.sendTimingResp(packet); + } + } else if (packet->needsResponse()) { + packet->makeResponse(); + need_retry = !bsp.sendTimingResp(packet); + } + + if (need_retry) { + blockingResponse = &trans; + } else { + if (phase == tlm::BEGIN_RESP) { + // Send END_RESP and we're finished: + tlm::tlm_phase fw_phase = tlm::END_RESP; + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + socket->nb_transport_fw(trans, fw_phase, delay); + // Release the transaction with all the extensions. + trans.release(); + } + } + } + delete pe; +} + +// Similar to TLM's blocking transport (LT) +Tick +Gem5ToTlmBridge::recvAtomic(PacketPtr packet) +{ + panic_if(packet->cacheResponding(), + "Should not see packets where cache is responding"); + + panic_if(!(packet->isRead() || packet->isWrite()), + "Should only see read and writes at TLM memory\n"); + + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + + // Prepare the transaction. + tlm::tlm_generic_payload *trans = mm.allocate(); + trans->acquire(); + packet2payload(packet, *trans); + + // Attach the packet pointer to the TLM transaction to keep track. + auto *extension = new Gem5SystemC::Gem5Extension(packet); + trans->set_auto_extension(extension); + + // Execute b_transport: + if (packet->cmd == MemCmd::SwapReq) { + SC_REPORT_FATAL("Gem5ToTlmBridge", "SwapReq not supported"); + } else if (packet->isRead()) { + socket->b_transport(*trans, delay); + } else if (packet->isInvalidate()) { + // do nothing + } else if (packet->isWrite()) { + socket->b_transport(*trans, delay); + } else { + SC_REPORT_FATAL("Gem5ToTlmBridge", "Typo of request not supported"); + } + + if (packet->needsResponse()) { + packet->makeResponse(); + } + + trans->release(); + + return delay.value(); +} + +void +Gem5ToTlmBridge::recvFunctionalSnoop(PacketPtr packet) +{ + // Snooping should be implemented with tlm_dbg_transport. + SC_REPORT_FATAL("Gem5ToTlmBridge", + "unimplemented func.: recvFunctionalSnoop"); +} + +// Similar to TLM's non-blocking transport (AT). +bool +Gem5ToTlmBridge::recvTimingReq(PacketPtr packet) +{ + panic_if(packet->cacheResponding(), + "Should not see packets where cache is responding"); + + panic_if(!(packet->isRead() || packet->isWrite()), + "Should only see read and writes at TLM memory\n"); + + + // We should never get a second request after noting that a retry is + // required. + sc_assert(!needToSendRequestRetry); + + // Remember if a request comes in while we're blocked so that a retry + // can be sent to gem5. + if (blockingRequest) { + needToSendRequestRetry = true; + return false; + } + + /* + * NOTE: normal tlm is blocking here. But in our case we return false + * and tell gem5 when a retry can be done. This is the main difference + * in the protocol: + * if (requestInProgress) + * { + * wait(endRequestEvent); + * } + * requestInProgress = trans; + */ + + // Prepare the transaction. + tlm::tlm_generic_payload *trans = mm.allocate(); + trans->acquire(); + packet2payload(packet, *trans); + + // Attach the packet pointer to the TLM transaction to keep track. + auto *extension = new Gem5SystemC::Gem5Extension(packet); + trans->set_auto_extension(extension); + + /* + * Pay for annotated transport delays. + * + * The header delay marks the point in time, when the packet first is seen + * by the transactor. This is the point in time when the transactor needs + * to send the BEGIN_REQ to the SystemC world. + * + * NOTE: We drop the payload delay here. Normally, the receiver would be + * responsible for handling the payload delay. In this case, however, + * the receiver is a SystemC module and has no notion of the gem5 + * transport protocol and we cannot simply forward the + * payload delay to the receiving module. Instead, we expect the + * receiving SystemC module to model the payload delay by deferring + * the END_REQ. This could lead to incorrect delays, if the XBar + * payload delay is longer than the time the receiver needs to accept + * the request (time between BEGIN_REQ and END_REQ). + * + * TODO: We could detect the case described above by remembering the + * payload delay and comparing it to the time between BEGIN_REQ and + * END_REQ. Then, a warning should be printed. + */ + auto delay = sc_core::sc_time::from_value(packet->payloadDelay); + // Reset the delays + packet->payloadDelay = 0; + packet->headerDelay = 0; + + // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC + // Standard Page 507 for a visualisation of the procedure. + tlm::tlm_phase phase = tlm::BEGIN_REQ; + tlm::tlm_sync_enum status; + status = socket->nb_transport_fw(*trans, phase, delay); + // Check returned value: + if (status == tlm::TLM_ACCEPTED) { + sc_assert(phase == tlm::BEGIN_REQ); + // Accepted but is now blocking until END_REQ (exclusion rule). + blockingRequest = trans; + } else if (status == tlm::TLM_UPDATED) { + // The Timing annotation must be honored: + sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP); + + auto *pe = new Gem5SystemC::PayloadEvent( + *this, &Gem5ToTlmBridge::pec, "PEQ"); + Tick nextEventTick = curTick() + delay.value(); + system->wakeupEventQueue(nextEventTick); + system->schedule(pe, nextEventTick); + } else if (status == tlm::TLM_COMPLETED) { + // Transaction is over nothing has do be done. + sc_assert(phase == tlm::END_RESP); + trans->release(); + } + + return true; +} + +bool +Gem5ToTlmBridge::recvTimingSnoopResp(PacketPtr packet) +{ + // Snooping should be implemented with tlm_dbg_transport. + SC_REPORT_FATAL("Gem5ToTlmBridge", + "unimplemented func.: recvTimingSnoopResp"); + return false; +} + +bool +Gem5ToTlmBridge::tryTiming(PacketPtr packet) +{ + panic("tryTiming(PacketPtr) isn't implemented."); +} + +void +Gem5ToTlmBridge::recvRespRetry() +{ + /* Retry a response */ + sc_assert(blockingResponse); + + tlm::tlm_generic_payload *trans = blockingResponse; + blockingResponse = nullptr; + PacketPtr packet = + Gem5SystemC::Gem5Extension::getExtension(trans).getPacket(); + + bool need_retry = !bsp.sendTimingResp(packet); + + sc_assert(!need_retry); + + sc_core::sc_time delay = sc_core::SC_ZERO_TIME; + tlm::tlm_phase phase = tlm::END_RESP; + socket->nb_transport_fw(*trans, phase, delay); + // Release transaction with all the extensions + trans->release(); +} + +// Similar to TLM's debug transport. +void +Gem5ToTlmBridge::recvFunctional(PacketPtr packet) +{ + // Prepare the transaction. + tlm::tlm_generic_payload *trans = mm.allocate(); + trans->acquire(); + packet2payload(packet, *trans); + + // Attach the packet pointer to the TLM transaction to keep track. + auto *extension = new Gem5SystemC::Gem5Extension(packet); + trans->set_auto_extension(extension); + + /* Execute Debug Transport: */ + unsigned int bytes = socket->transport_dbg(*trans); + if (bytes != trans->get_data_length()) { + SC_REPORT_FATAL("Gem5ToTlmBridge", + "debug transport was not completed"); + } + + trans->release(); +} + +tlm::tlm_sync_enum +Gem5ToTlmBridge::nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, sc_core::sc_time &delay) +{ + auto *pe = new Gem5SystemC::PayloadEvent( + *this, &Gem5ToTlmBridge::pec, "PE"); + Tick nextEventTick = curTick() + delay.value(); + system->wakeupEventQueue(nextEventTick); + system->schedule(pe, nextEventTick); + return tlm::TLM_ACCEPTED; +} + +Gem5ToTlmBridge::Gem5ToTlmBridge( + Params *params, const sc_core::sc_module_name &mn) : + sc_core::sc_module(mn), bsp(std::string(name()) + ".gem5", *this), + socket("tlm_socket"), + wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), + system(params->system), blockingRequest(nullptr), + needToSendRequestRetry(false), blockingResponse(nullptr), + addrRanges(params->addr_ranges.begin(), params->addr_ranges.end()) +{ +} + +::Port & +Gem5ToTlmBridge::gem5_getPort(const std::string &if_name, int idx) +{ + if (if_name == "gem5") + return bsp; + else if (if_name == "tlm") + return wrapper; + + return sc_core::sc_module::gem5_getPort(if_name, idx); +} + +void +Gem5ToTlmBridge::before_end_of_elaboration() +{ + bsp.sendRangeChange(); + + socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw); + sc_core::sc_module::before_end_of_elaboration(); +} + +} // namespace sc_gem5 + +sc_gem5::Gem5ToTlmBridge * +Gem5ToTlmBridgeParams::create() +{ + return new sc_gem5::Gem5ToTlmBridge( + this, sc_core::sc_module_name(name.c_str())); +} diff --git a/src/systemc/tlm_bridge/gem5_to_tlm.hh b/src/systemc/tlm_bridge/gem5_to_tlm.hh new file mode 100644 index 000000000..02deb6add --- /dev/null +++ b/src/systemc/tlm_bridge/gem5_to_tlm.hh @@ -0,0 +1,189 @@ +/* + * Copyright 2019 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Matthias Jung + * Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_GEM5_TO_TLM_HH__ +#define __SYSTEMC_TLM_BRIDGE_GEM5_TO_TLM_HH__ + +#include + +#include "mem/port.hh" +#include "params/Gem5ToTlmBridge.hh" +#include "sim/system.hh" +#include "systemc/ext/core/sc_module.hh" +#include "systemc/ext/core/sc_module_name.hh" +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" +#include "systemc/ext/tlm_utils/simple_initiator_socket.h" +#include "systemc/tlm_bridge/sc_peq.hh" +#include "systemc/tlm_port_wrapper.hh" + +namespace sc_gem5 +{ + +class Gem5ToTlmBridge : public sc_core::sc_module +{ + private: + class BridgeSlavePort : public SlavePort + { + protected: + Gem5ToTlmBridge &bridge; + + AddrRangeList + getAddrRanges() const override + { + return bridge.getAddrRanges(); + } + Tick + recvAtomic(PacketPtr pkt) override + { + return bridge.recvAtomic(pkt); + } + void + recvFunctional(PacketPtr pkt) override + { + return bridge.recvFunctional(pkt); + } + bool + recvTimingReq(PacketPtr pkt) override + { + return bridge.recvTimingReq(pkt); + } + bool + tryTiming(PacketPtr pkt) override + { + return bridge.tryTiming(pkt); + } + bool + recvTimingSnoopResp(PacketPtr pkt) override + { + return bridge.recvTimingSnoopResp(pkt); + } + void recvRespRetry() override { bridge.recvRespRetry(); } + + public: + BridgeSlavePort(const std::string &name_, Gem5ToTlmBridge &bridge_) : + SlavePort(name_, nullptr), bridge(bridge_) + {} + }; + + BridgeSlavePort bsp; + tlm_utils::simple_initiator_socket socket; + sc_gem5::TlmInitiatorWrapper<64> wrapper; + + System *system; + + /** + * A transaction after BEGIN_REQ has been sent but before END_REQ, which + * is blocking the request channel (Exlusion Rule, see IEEE1666) + */ + tlm::tlm_generic_payload *blockingRequest; + + /** + * Did another gem5 request arrive while currently blocked? + * This variable is needed when a retry should happen + */ + bool needToSendRequestRetry; + + /** + * A response which has been asked to retry by gem5 and so is blocking + * the response channel + */ + tlm::tlm_generic_payload *blockingResponse; + + AddrRangeList addrRanges; + + protected: + void pec(Gem5SystemC::PayloadEvent *pe, + tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + + // The gem5 port interface. + Tick recvAtomic(PacketPtr packet); + void recvFunctional(PacketPtr packet); + bool recvTimingReq(PacketPtr packet); + bool tryTiming(PacketPtr packet); + bool recvTimingSnoopResp(PacketPtr packet); + void recvRespRetry(); + void recvFunctionalSnoop(PacketPtr packet); + AddrRangeList getAddrRanges() const { return addrRanges; } + + // The TLM initiator interface. + tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &t); + + public: + ::Port &gem5_getPort(const std::string &if_name, int idx=-1) override; + + typedef Gem5ToTlmBridgeParams Params; + Gem5ToTlmBridge(Params *p, const sc_core::sc_module_name &mn); + + tlm_utils::simple_initiator_socket & + getSocket() + { + return socket; + } + + void before_end_of_elaboration() override; +}; + +} // namespace sc_gem5 + +#endif // __SYSTEMC_TLM_BRIDGE_GEM5_TO_TLM_HH__ diff --git a/src/systemc/tlm_bridge/tlm_to_gem5.cc b/src/systemc/tlm_bridge/tlm_to_gem5.cc new file mode 100644 index 000000000..9e704901f --- /dev/null +++ b/src/systemc/tlm_bridge/tlm_to_gem5.cc @@ -0,0 +1,442 @@ +/* + * Copyright 2019 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Christian Menard + */ + +#include "systemc/tlm_bridge/tlm_to_gem5.hh" + +#include "sim/system.hh" +#include "systemc/ext/core/sc_module_name.hh" + +namespace sc_gem5 +{ + +void +TlmToGem5Bridge::sendEndReq(tlm::tlm_generic_payload &trans) +{ + tlm::tlm_phase phase = tlm::END_REQ; + auto delay = sc_core::SC_ZERO_TIME; + + auto status = socket->nb_transport_bw(trans, phase, delay); + panic_if(status != tlm::TLM_ACCEPTED, + "Unexpected status after sending END_REQ"); +} + +void +TlmToGem5Bridge::sendBeginResp(tlm::tlm_generic_payload &trans, + sc_core::sc_time &delay) +{ + tlm::tlm_phase phase = tlm::BEGIN_RESP; + + trans.set_response_status(tlm::TLM_OK_RESPONSE); + + auto status = socket->nb_transport_bw(trans, phase, delay); + + if (status == tlm::TLM_COMPLETED || + (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) { + // transaction completed -> no need to wait for tlm::END_RESP + responseInProgress = false; + } else if (status == tlm::TLM_ACCEPTED) { + // we need to wait for tlm::END_RESP + responseInProgress = true; + } else { + panic("Unexpected status after sending BEGIN_RESP"); + } +} + +void +TlmToGem5Bridge::handleBeginReq(tlm::tlm_generic_payload &trans) +{ + sc_assert(!waitForRetry); + sc_assert(pendingRequest == nullptr); + sc_assert(pendingPacket == nullptr); + + trans.acquire(); + + PacketPtr pkt = nullptr; + + Gem5SystemC::Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. Otherwise, we + // generate a new packet based on the transaction. + if (extension != nullptr) { + extension->setPipeThrough(); + pkt = extension->getPacket(); + } else { + pkt = generatePacket(trans); + } + + auto tlmSenderState = new TlmSenderState(trans); + pkt->pushSenderState(tlmSenderState); + + if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately + sendEndReq(trans); + trans.release(); + } else { // port is blocked -> wait for retry before sending END_REQ + waitForRetry = true; + pendingRequest = &trans; + pendingPacket = pkt; + } +} + +void +TlmToGem5Bridge::handleEndResp(tlm::tlm_generic_payload &trans) +{ + sc_assert(responseInProgress); + + responseInProgress = false; + + checkTransaction(trans); + + if (needToSendRetry) { + bmp.sendRetryResp(); + needToSendRetry = false; + } +} + +PacketPtr +TlmToGem5Bridge::generatePacket(tlm::tlm_generic_payload &trans) +{ + MemCmd cmd; + + switch (trans.get_command()) { + case tlm::TLM_READ_COMMAND: + cmd = MemCmd::ReadReq; + break; + case tlm::TLM_WRITE_COMMAND: + cmd = MemCmd::WriteReq; + break; + case tlm::TLM_IGNORE_COMMAND: + return nullptr; + default: + SC_REPORT_FATAL("TlmToGem5Bridge", + "received transaction with unsupported command"); + } + + Request::Flags flags; + auto req = std::make_shared( + trans.get_address(), trans.get_data_length(), flags, masterId); + + /* + * Allocate a new Packet. The packet will be deleted when it returns from + * the gem5 world as a response. + */ + auto pkt = new Packet(req, cmd); + pkt->dataStatic(trans.get_data_ptr()); + + return pkt; +} + +void +TlmToGem5Bridge::destroyPacket(PacketPtr pkt) +{ + delete pkt; +} + +void +TlmToGem5Bridge::checkTransaction(tlm::tlm_generic_payload &trans) +{ + if (trans.is_response_error()) { + std::stringstream ss; + ss << "Transaction returned with error, response status = " + << trans.get_response_string(); + SC_REPORT_ERROR("TLM-2", ss.str().c_str()); + } +} + +void +TlmToGem5Bridge::peq_cb(tlm::tlm_generic_payload &trans, + const tlm::tlm_phase &phase) +{ + switch (phase) { + case tlm::BEGIN_REQ: + handleBeginReq(trans); + break; + case tlm::END_RESP: + handleEndResp(trans); + break; + default: + panic("unimplemented phase in callback"); + } +} + +tlm::tlm_sync_enum +TlmToGem5Bridge::nb_transport_fw( + tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, + sc_core::sc_time &delay) +{ + unsigned len = trans.get_data_length(); + unsigned char *byteEnable = trans.get_byte_enable_ptr(); + unsigned width = trans.get_streaming_width(); + + // check the transaction attributes for unsupported features ... + if (byteEnable != 0) { + trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); + return tlm::TLM_COMPLETED; + } + if (width < len) { // is this a burst request? + trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); + return tlm::TLM_COMPLETED; + } + + // ... and queue the valid transaction + trans.acquire(); + peq.notify(trans, phase, delay); + return tlm::TLM_ACCEPTED; +} + +void +TlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans, + sc_core::sc_time &t) +{ + Gem5SystemC::Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + PacketPtr pkt = nullptr; + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. + if (extension != nullptr) { + extension->setPipeThrough(); + pkt = extension->getPacket(); + } else { + pkt = generatePacket(trans); + } + + Tick ticks = bmp.sendAtomic(pkt); + + // send an atomic request to gem5 + panic_if(pkt->needsResponse() && !pkt->isResponse(), + "Packet sending failed!\n"); + + auto delay = + sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS); + + // update time + t += delay; + + if (extension == nullptr) + destroyPacket(pkt); + + trans.set_response_status(tlm::TLM_OK_RESPONSE); +} + +unsigned int +TlmToGem5Bridge::transport_dbg(tlm::tlm_generic_payload &trans) +{ + Gem5SystemC::Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // If there is an extension, this transaction was initiated by the gem5 + // world and we can pipe through the original packet. + if (extension != nullptr) { + extension->setPipeThrough(); + bmp.sendFunctional(extension->getPacket()); + } else { + auto pkt = generatePacket(trans); + if (pkt) { + bmp.sendFunctional(pkt); + destroyPacket(pkt); + } + } + + return trans.get_data_length(); +} + +bool +TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, + tlm::tlm_dmi &dmi_data) +{ + return false; +} + +bool +TlmToGem5Bridge::recvTimingResp(PacketPtr pkt) +{ + // exclusion rule + // We need to Wait for END_RESP before sending next BEGIN_RESP + if (responseInProgress) { + sc_assert(!needToSendRetry); + needToSendRetry = true; + return false; + } + + sc_assert(pkt->isResponse()); + + /* + * Pay for annotated transport delays. + * + * See recvTimingReq in sc_slave_port.cc for a detailed description. + */ + auto delay = sc_core::sc_time::from_value(pkt->payloadDelay); + // reset the delays + pkt->payloadDelay = 0; + pkt->headerDelay = 0; + + auto tlmSenderState = dynamic_cast(pkt->popSenderState()); + sc_assert(tlmSenderState != nullptr); + + auto &trans = tlmSenderState->trans; + + Gem5SystemC::Gem5Extension *extension = nullptr; + trans.get_extension(extension); + + // clean up + delete tlmSenderState; + + // If there is an extension the packet was piped through and we must not + // delete it. The packet travels back with the transaction. + if (extension == nullptr) + destroyPacket(pkt); + else + sc_assert(extension->isPipeThrough()); + + sendBeginResp(trans, delay); + trans.release(); + + return true; +} + +void +TlmToGem5Bridge::recvReqRetry() +{ + sc_assert(waitForRetry); + sc_assert(pendingRequest != nullptr); + sc_assert(pendingPacket != nullptr); + + if (bmp.sendTimingReq(pendingPacket)) { + waitForRetry = false; + pendingPacket = nullptr; + + auto &trans = *pendingRequest; + sendEndReq(trans); + trans.release(); + + pendingRequest = nullptr; + } +} + +void +TlmToGem5Bridge::recvRangeChange() +{ + SC_REPORT_WARNING("TlmToGem5Bridge", + "received address range change but ignored it"); +} + +::Port & +TlmToGem5Bridge::gem5_getPort(const std::string &if_name, int idx) +{ + if (if_name == "gem5") + return bmp; + else if (if_name == "tlm") + return wrapper; + + return sc_core::sc_module::gem5_getPort(if_name, idx); +} + +TlmToGem5Bridge::TlmToGem5Bridge( + Params *params, const sc_core::sc_module_name &mn) : + sc_core::sc_module(mn), peq(this, &TlmToGem5Bridge::peq_cb), + waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr), + needToSendRetry(false), responseInProgress(false), + bmp(std::string(name()) + "master", *this), socket("tlm_socket"), + wrapper(socket, std::string(name()) + ".tlm", InvalidPortID), + system(params->system), + masterId(params->system->getGlobalMasterId( + std::string("[systemc].") + name())) +{ +} + +void +TlmToGem5Bridge::before_end_of_elaboration() +{ + /* + * Register the TLM non-blocking interface when using gem5 Timing mode and + * the TLM blocking interface when using the gem5 Atomic mode. + * Then the magic (TM) in simple_target_socket automatically transforms + * non-blocking in blocking transactions and vice versa. + * + * NOTE: The mode may change during execution. + */ + if (system->isTimingMode()) { + SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface"); + socket.register_nb_transport_fw( + this, &TlmToGem5Bridge::nb_transport_fw); + } else if (system->isAtomicMode()) { + SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface"); + socket.register_b_transport( + this, &TlmToGem5Bridge::b_transport); + } else { + panic("gem5 operates neither in Timing nor in Atomic mode"); + } + + socket.register_transport_dbg(this, &TlmToGem5Bridge::transport_dbg); + + sc_core::sc_module::before_end_of_elaboration(); +} + +} // namespace sc_gem5 + +sc_gem5::TlmToGem5Bridge * +TlmToGem5BridgeParams::create() +{ + return new sc_gem5::TlmToGem5Bridge( + this, sc_core::sc_module_name(name.c_str())); +} diff --git a/src/systemc/tlm_bridge/tlm_to_gem5.hh b/src/systemc/tlm_bridge/tlm_to_gem5.hh new file mode 100644 index 000000000..1d6fa13d0 --- /dev/null +++ b/src/systemc/tlm_bridge/tlm_to_gem5.hh @@ -0,0 +1,170 @@ +/* + * Copyright 2019 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + * Christian Menard + */ + +#ifndef __SYSTEMC_TLM_BRIDGE_TLM_TO_GEM5_HH__ +#define __SYSTEMC_TLM_BRIDGE_TLM_TO_GEM5_HH__ + +#include "mem/port.hh" +#include "params/TlmToGem5Bridge.hh" +#include "systemc/ext/core/sc_module.hh" +#include "systemc/ext/core/sc_module_name.hh" +#include "systemc/ext/tlm_core/2/generic_payload/gp.hh" +#include "systemc/ext/tlm_utils/peq_with_cb_and_phase.h" +#include "systemc/ext/tlm_utils/simple_target_socket.h" +#include "systemc/tlm_bridge/sc_ext.hh" +#include "systemc/tlm_port_wrapper.hh" + +namespace sc_gem5 +{ + +class TlmToGem5Bridge : public sc_core::sc_module +{ + private: + struct TlmSenderState : public Packet::SenderState + { + tlm::tlm_generic_payload &trans; + TlmSenderState(tlm::tlm_generic_payload &trans) : trans(trans) {} + }; + + class BridgeMasterPort : public MasterPort + { + protected: + TlmToGem5Bridge &bridge; + + bool + recvTimingResp(PacketPtr pkt) override + { + return bridge.recvTimingResp(pkt); + } + void recvReqRetry() override { bridge.recvReqRetry(); } + void recvRangeChange() override { bridge.recvRangeChange(); } + + public: + BridgeMasterPort(const std::string &name_, TlmToGem5Bridge &bridge_) : + MasterPort(name_, nullptr), bridge(bridge_) + {} + }; + + tlm_utils::peq_with_cb_and_phase peq; + + bool waitForRetry; + tlm::tlm_generic_payload *pendingRequest; + PacketPtr pendingPacket; + + bool needToSendRetry; + + bool responseInProgress; + + BridgeMasterPort bmp; + tlm_utils::simple_target_socket socket; + sc_gem5::TlmTargetWrapper<64> wrapper; + + System *system; + + void sendEndReq(tlm::tlm_generic_payload &trans); + void sendBeginResp(tlm::tlm_generic_payload &trans, + sc_core::sc_time &delay); + + void handleBeginReq(tlm::tlm_generic_payload &trans); + void handleEndResp(tlm::tlm_generic_payload &trans); + + PacketPtr generatePacket(tlm::tlm_generic_payload &trans); + void destroyPacket(PacketPtr pkt); + + void checkTransaction(tlm::tlm_generic_payload &trans); + + protected: + // payload event call back + void peq_cb(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase); + + // The TLM target interface + tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload &trans, + tlm::tlm_phase &phase, + sc_core::sc_time &t); + void b_transport(tlm::tlm_generic_payload &trans, sc_core::sc_time &t); + unsigned int transport_dbg(tlm::tlm_generic_payload &trans); + bool get_direct_mem_ptr(tlm::tlm_generic_payload &trans, + tlm::tlm_dmi &dmi_data); + + // Gem5 port interface. + bool recvTimingResp(PacketPtr pkt); + void recvReqRetry(); + void recvRangeChange(); + + public: + ::Port &gem5_getPort(const std::string &if_name, int idx=-1) override; + + typedef TlmToGem5BridgeParams Params; + TlmToGem5Bridge(Params *p, const sc_core::sc_module_name &mn); + + tlm_utils::simple_target_socket & + getSocket() + { + return socket; + } + + void before_end_of_elaboration() override; + + const MasterID masterId; +}; + +} // namespace sc_gem5 + +#endif // __SYSTEMC_TLM_BRIDGE_TLM_TO_GEM5_HH__ -- 2.30.2