gem5_to_tlm.cc revision 13821
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
6613821Sgabeblack@google.com#include "sim/system.hh"
6713821Sgabeblack@google.com#include "systemc/tlm_bridge/sc_ext.hh"
6813821Sgabeblack@google.com#include "systemc/tlm_bridge/sc_mm.hh"
6913821Sgabeblack@google.com
7013821Sgabeblack@google.comnamespace sc_gem5
7113821Sgabeblack@google.com{
7213821Sgabeblack@google.com
7313821Sgabeblack@google.com/**
7413821Sgabeblack@google.com * Instantiate a tlm memory manager that takes care about all the
7513821Sgabeblack@google.com * tlm transactions in the system.
7613821Sgabeblack@google.com */
7713821Sgabeblack@google.comGem5SystemC::MemoryManager mm;
7813821Sgabeblack@google.com
7913821Sgabeblack@google.com/**
8013821Sgabeblack@google.com * Convert a gem5 packet to a TLM payload by copying all the relevant
8113821Sgabeblack@google.com * information to a previously allocated tlm payload
8213821Sgabeblack@google.com */
8313821Sgabeblack@google.comvoid
8413821Sgabeblack@google.compacket2payload(PacketPtr packet, tlm::tlm_generic_payload &trans)
8513821Sgabeblack@google.com{
8613821Sgabeblack@google.com    trans.set_address(packet->getAddr());
8713821Sgabeblack@google.com
8813821Sgabeblack@google.com    /* Check if this transaction was allocated by mm */
8913821Sgabeblack@google.com    sc_assert(trans.has_mm());
9013821Sgabeblack@google.com
9113821Sgabeblack@google.com    unsigned int size = packet->getSize();
9213821Sgabeblack@google.com    unsigned char *data = packet->getPtr<unsigned char>();
9313821Sgabeblack@google.com
9413821Sgabeblack@google.com    trans.set_data_length(size);
9513821Sgabeblack@google.com    trans.set_streaming_width(size);
9613821Sgabeblack@google.com    trans.set_data_ptr(data);
9713821Sgabeblack@google.com
9813821Sgabeblack@google.com    if (packet->isRead()) {
9913821Sgabeblack@google.com        trans.set_command(tlm::TLM_READ_COMMAND);
10013821Sgabeblack@google.com    } else if (packet->isInvalidate()) {
10113821Sgabeblack@google.com        /* Do nothing */
10213821Sgabeblack@google.com    } else if (packet->isWrite()) {
10313821Sgabeblack@google.com        trans.set_command(tlm::TLM_WRITE_COMMAND);
10413821Sgabeblack@google.com    } else {
10513821Sgabeblack@google.com        SC_REPORT_FATAL("Gem5ToTlmBridge", "No R/W packet");
10613821Sgabeblack@google.com    }
10713821Sgabeblack@google.com}
10813821Sgabeblack@google.com
10913821Sgabeblack@google.comvoid
11013821Sgabeblack@google.comGem5ToTlmBridge::pec(Gem5SystemC::PayloadEvent<Gem5ToTlmBridge> *pe,
11113821Sgabeblack@google.com        tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
11213821Sgabeblack@google.com{
11313821Sgabeblack@google.com    sc_core::sc_time delay;
11413821Sgabeblack@google.com
11513821Sgabeblack@google.com    if (phase == tlm::END_REQ ||
11613821Sgabeblack@google.com            (&trans == blockingRequest && phase == tlm::BEGIN_RESP)) {
11713821Sgabeblack@google.com        sc_assert(&trans == blockingRequest);
11813821Sgabeblack@google.com        blockingRequest = nullptr;
11913821Sgabeblack@google.com
12013821Sgabeblack@google.com        // Did another request arrive while blocked, schedule a retry.
12113821Sgabeblack@google.com        if (needToSendRequestRetry) {
12213821Sgabeblack@google.com            needToSendRequestRetry = false;
12313821Sgabeblack@google.com            bsp.sendRetryReq();
12413821Sgabeblack@google.com        }
12513821Sgabeblack@google.com    }
12613821Sgabeblack@google.com    if (phase == tlm::BEGIN_RESP) {
12713821Sgabeblack@google.com        auto &extension = Gem5SystemC::Gem5Extension::getExtension(trans);
12813821Sgabeblack@google.com        auto packet = extension.getPacket();
12913821Sgabeblack@google.com
13013821Sgabeblack@google.com        sc_assert(!blockingResponse);
13113821Sgabeblack@google.com
13213821Sgabeblack@google.com        bool need_retry = false;
13313821Sgabeblack@google.com
13413821Sgabeblack@google.com        /*
13513821Sgabeblack@google.com         * If the packet was piped through and needs a response, we don't need
13613821Sgabeblack@google.com         * to touch the packet and can forward it directly as a response.
13713821Sgabeblack@google.com         * Otherwise, we need to make a response and send the transformed
13813821Sgabeblack@google.com         * packet.
13913821Sgabeblack@google.com         */
14013821Sgabeblack@google.com        if (extension.isPipeThrough()) {
14113821Sgabeblack@google.com            if (packet->isResponse()) {
14213821Sgabeblack@google.com                need_retry = !bsp.sendTimingResp(packet);
14313821Sgabeblack@google.com            }
14413821Sgabeblack@google.com        } else if (packet->needsResponse()) {
14513821Sgabeblack@google.com            packet->makeResponse();
14613821Sgabeblack@google.com            need_retry = !bsp.sendTimingResp(packet);
14713821Sgabeblack@google.com        }
14813821Sgabeblack@google.com
14913821Sgabeblack@google.com        if (need_retry) {
15013821Sgabeblack@google.com            blockingResponse = &trans;
15113821Sgabeblack@google.com        } else {
15213821Sgabeblack@google.com            if (phase == tlm::BEGIN_RESP) {
15313821Sgabeblack@google.com                // Send END_RESP and we're finished:
15413821Sgabeblack@google.com                tlm::tlm_phase fw_phase = tlm::END_RESP;
15513821Sgabeblack@google.com                sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
15613821Sgabeblack@google.com                socket->nb_transport_fw(trans, fw_phase, delay);
15713821Sgabeblack@google.com                // Release the transaction with all the extensions.
15813821Sgabeblack@google.com                trans.release();
15913821Sgabeblack@google.com            }
16013821Sgabeblack@google.com        }
16113821Sgabeblack@google.com    }
16213821Sgabeblack@google.com    delete pe;
16313821Sgabeblack@google.com}
16413821Sgabeblack@google.com
16513821Sgabeblack@google.com// Similar to TLM's blocking transport (LT)
16613821Sgabeblack@google.comTick
16713821Sgabeblack@google.comGem5ToTlmBridge::recvAtomic(PacketPtr packet)
16813821Sgabeblack@google.com{
16913821Sgabeblack@google.com    panic_if(packet->cacheResponding(),
17013821Sgabeblack@google.com             "Should not see packets where cache is responding");
17113821Sgabeblack@google.com
17213821Sgabeblack@google.com    panic_if(!(packet->isRead() || packet->isWrite()),
17313821Sgabeblack@google.com             "Should only see read and writes at TLM memory\n");
17413821Sgabeblack@google.com
17513821Sgabeblack@google.com    sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
17613821Sgabeblack@google.com
17713821Sgabeblack@google.com    // Prepare the transaction.
17813821Sgabeblack@google.com    tlm::tlm_generic_payload *trans = mm.allocate();
17913821Sgabeblack@google.com    trans->acquire();
18013821Sgabeblack@google.com    packet2payload(packet, *trans);
18113821Sgabeblack@google.com
18213821Sgabeblack@google.com    // Attach the packet pointer to the TLM transaction to keep track.
18313821Sgabeblack@google.com    auto *extension = new Gem5SystemC::Gem5Extension(packet);
18413821Sgabeblack@google.com    trans->set_auto_extension(extension);
18513821Sgabeblack@google.com
18613821Sgabeblack@google.com    // Execute b_transport:
18713821Sgabeblack@google.com    if (packet->cmd == MemCmd::SwapReq) {
18813821Sgabeblack@google.com        SC_REPORT_FATAL("Gem5ToTlmBridge", "SwapReq not supported");
18913821Sgabeblack@google.com    } else if (packet->isRead()) {
19013821Sgabeblack@google.com        socket->b_transport(*trans, delay);
19113821Sgabeblack@google.com    } else if (packet->isInvalidate()) {
19213821Sgabeblack@google.com        // do nothing
19313821Sgabeblack@google.com    } else if (packet->isWrite()) {
19413821Sgabeblack@google.com        socket->b_transport(*trans, delay);
19513821Sgabeblack@google.com    } else {
19613821Sgabeblack@google.com        SC_REPORT_FATAL("Gem5ToTlmBridge", "Typo of request not supported");
19713821Sgabeblack@google.com    }
19813821Sgabeblack@google.com
19913821Sgabeblack@google.com    if (packet->needsResponse()) {
20013821Sgabeblack@google.com        packet->makeResponse();
20113821Sgabeblack@google.com    }
20213821Sgabeblack@google.com
20313821Sgabeblack@google.com    trans->release();
20413821Sgabeblack@google.com
20513821Sgabeblack@google.com    return delay.value();
20613821Sgabeblack@google.com}
20713821Sgabeblack@google.com
20813821Sgabeblack@google.comvoid
20913821Sgabeblack@google.comGem5ToTlmBridge::recvFunctionalSnoop(PacketPtr packet)
21013821Sgabeblack@google.com{
21113821Sgabeblack@google.com    // Snooping should be implemented with tlm_dbg_transport.
21213821Sgabeblack@google.com    SC_REPORT_FATAL("Gem5ToTlmBridge",
21313821Sgabeblack@google.com            "unimplemented func.: recvFunctionalSnoop");
21413821Sgabeblack@google.com}
21513821Sgabeblack@google.com
21613821Sgabeblack@google.com// Similar to TLM's non-blocking transport (AT).
21713821Sgabeblack@google.combool
21813821Sgabeblack@google.comGem5ToTlmBridge::recvTimingReq(PacketPtr packet)
21913821Sgabeblack@google.com{
22013821Sgabeblack@google.com    panic_if(packet->cacheResponding(),
22113821Sgabeblack@google.com             "Should not see packets where cache is responding");
22213821Sgabeblack@google.com
22313821Sgabeblack@google.com    panic_if(!(packet->isRead() || packet->isWrite()),
22413821Sgabeblack@google.com             "Should only see read and writes at TLM memory\n");
22513821Sgabeblack@google.com
22613821Sgabeblack@google.com
22713821Sgabeblack@google.com    // We should never get a second request after noting that a retry is
22813821Sgabeblack@google.com    // required.
22913821Sgabeblack@google.com    sc_assert(!needToSendRequestRetry);
23013821Sgabeblack@google.com
23113821Sgabeblack@google.com    // Remember if a request comes in while we're blocked so that a retry
23213821Sgabeblack@google.com    // can be sent to gem5.
23313821Sgabeblack@google.com    if (blockingRequest) {
23413821Sgabeblack@google.com        needToSendRequestRetry = true;
23513821Sgabeblack@google.com        return false;
23613821Sgabeblack@google.com    }
23713821Sgabeblack@google.com
23813821Sgabeblack@google.com    /*
23913821Sgabeblack@google.com     * NOTE: normal tlm is blocking here. But in our case we return false
24013821Sgabeblack@google.com     * and tell gem5 when a retry can be done. This is the main difference
24113821Sgabeblack@google.com     * in the protocol:
24213821Sgabeblack@google.com     * if (requestInProgress)
24313821Sgabeblack@google.com     * {
24413821Sgabeblack@google.com     *     wait(endRequestEvent);
24513821Sgabeblack@google.com     * }
24613821Sgabeblack@google.com     * requestInProgress = trans;
24713821Sgabeblack@google.com     */
24813821Sgabeblack@google.com
24913821Sgabeblack@google.com    // Prepare the transaction.
25013821Sgabeblack@google.com    tlm::tlm_generic_payload *trans = mm.allocate();
25113821Sgabeblack@google.com    trans->acquire();
25213821Sgabeblack@google.com    packet2payload(packet, *trans);
25313821Sgabeblack@google.com
25413821Sgabeblack@google.com    // Attach the packet pointer to the TLM transaction to keep track.
25513821Sgabeblack@google.com    auto *extension = new Gem5SystemC::Gem5Extension(packet);
25613821Sgabeblack@google.com    trans->set_auto_extension(extension);
25713821Sgabeblack@google.com
25813821Sgabeblack@google.com    /*
25913821Sgabeblack@google.com     * Pay for annotated transport delays.
26013821Sgabeblack@google.com     *
26113821Sgabeblack@google.com     * The header delay marks the point in time, when the packet first is seen
26213821Sgabeblack@google.com     * by the transactor. This is the point in time when the transactor needs
26313821Sgabeblack@google.com     * to send the BEGIN_REQ to the SystemC world.
26413821Sgabeblack@google.com     *
26513821Sgabeblack@google.com     * NOTE: We drop the payload delay here. Normally, the receiver would be
26613821Sgabeblack@google.com     *       responsible for handling the payload delay. In this case, however,
26713821Sgabeblack@google.com     *       the receiver is a SystemC module and has no notion of the gem5
26813821Sgabeblack@google.com     *       transport protocol and we cannot simply forward the
26913821Sgabeblack@google.com     *       payload delay to the receiving module. Instead, we expect the
27013821Sgabeblack@google.com     *       receiving SystemC module to model the payload delay by deferring
27113821Sgabeblack@google.com     *       the END_REQ. This could lead to incorrect delays, if the XBar
27213821Sgabeblack@google.com     *       payload delay is longer than the time the receiver needs to accept
27313821Sgabeblack@google.com     *       the request (time between BEGIN_REQ and END_REQ).
27413821Sgabeblack@google.com     *
27513821Sgabeblack@google.com     * TODO: We could detect the case described above by remembering the
27613821Sgabeblack@google.com     *       payload delay and comparing it to the time between BEGIN_REQ and
27713821Sgabeblack@google.com     *       END_REQ. Then, a warning should be printed.
27813821Sgabeblack@google.com     */
27913821Sgabeblack@google.com    auto delay = sc_core::sc_time::from_value(packet->payloadDelay);
28013821Sgabeblack@google.com    // Reset the delays
28113821Sgabeblack@google.com    packet->payloadDelay = 0;
28213821Sgabeblack@google.com    packet->headerDelay = 0;
28313821Sgabeblack@google.com
28413821Sgabeblack@google.com    // Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC
28513821Sgabeblack@google.com    // Standard Page 507 for a visualisation of the procedure.
28613821Sgabeblack@google.com    tlm::tlm_phase phase = tlm::BEGIN_REQ;
28713821Sgabeblack@google.com    tlm::tlm_sync_enum status;
28813821Sgabeblack@google.com    status = socket->nb_transport_fw(*trans, phase, delay);
28913821Sgabeblack@google.com    // Check returned value:
29013821Sgabeblack@google.com    if (status == tlm::TLM_ACCEPTED) {
29113821Sgabeblack@google.com        sc_assert(phase == tlm::BEGIN_REQ);
29213821Sgabeblack@google.com        // Accepted but is now blocking until END_REQ (exclusion rule).
29313821Sgabeblack@google.com        blockingRequest = trans;
29413821Sgabeblack@google.com    } else if (status == tlm::TLM_UPDATED) {
29513821Sgabeblack@google.com        // The Timing annotation must be honored:
29613821Sgabeblack@google.com        sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP);
29713821Sgabeblack@google.com
29813821Sgabeblack@google.com        auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>(
29913821Sgabeblack@google.com                *this, &Gem5ToTlmBridge::pec, "PEQ");
30013821Sgabeblack@google.com        Tick nextEventTick = curTick() + delay.value();
30113821Sgabeblack@google.com        system->wakeupEventQueue(nextEventTick);
30213821Sgabeblack@google.com        system->schedule(pe, nextEventTick);
30313821Sgabeblack@google.com    } else if (status == tlm::TLM_COMPLETED) {
30413821Sgabeblack@google.com        // Transaction is over nothing has do be done.
30513821Sgabeblack@google.com        sc_assert(phase == tlm::END_RESP);
30613821Sgabeblack@google.com        trans->release();
30713821Sgabeblack@google.com    }
30813821Sgabeblack@google.com
30913821Sgabeblack@google.com    return true;
31013821Sgabeblack@google.com}
31113821Sgabeblack@google.com
31213821Sgabeblack@google.combool
31313821Sgabeblack@google.comGem5ToTlmBridge::recvTimingSnoopResp(PacketPtr packet)
31413821Sgabeblack@google.com{
31513821Sgabeblack@google.com    // Snooping should be implemented with tlm_dbg_transport.
31613821Sgabeblack@google.com    SC_REPORT_FATAL("Gem5ToTlmBridge",
31713821Sgabeblack@google.com            "unimplemented func.: recvTimingSnoopResp");
31813821Sgabeblack@google.com    return false;
31913821Sgabeblack@google.com}
32013821Sgabeblack@google.com
32113821Sgabeblack@google.combool
32213821Sgabeblack@google.comGem5ToTlmBridge::tryTiming(PacketPtr packet)
32313821Sgabeblack@google.com{
32413821Sgabeblack@google.com    panic("tryTiming(PacketPtr) isn't implemented.");
32513821Sgabeblack@google.com}
32613821Sgabeblack@google.com
32713821Sgabeblack@google.comvoid
32813821Sgabeblack@google.comGem5ToTlmBridge::recvRespRetry()
32913821Sgabeblack@google.com{
33013821Sgabeblack@google.com    /* Retry a response */
33113821Sgabeblack@google.com    sc_assert(blockingResponse);
33213821Sgabeblack@google.com
33313821Sgabeblack@google.com    tlm::tlm_generic_payload *trans = blockingResponse;
33413821Sgabeblack@google.com    blockingResponse = nullptr;
33513821Sgabeblack@google.com    PacketPtr packet =
33613821Sgabeblack@google.com        Gem5SystemC::Gem5Extension::getExtension(trans).getPacket();
33713821Sgabeblack@google.com
33813821Sgabeblack@google.com    bool need_retry = !bsp.sendTimingResp(packet);
33913821Sgabeblack@google.com
34013821Sgabeblack@google.com    sc_assert(!need_retry);
34113821Sgabeblack@google.com
34213821Sgabeblack@google.com    sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
34313821Sgabeblack@google.com    tlm::tlm_phase phase = tlm::END_RESP;
34413821Sgabeblack@google.com    socket->nb_transport_fw(*trans, phase, delay);
34513821Sgabeblack@google.com    // Release transaction with all the extensions
34613821Sgabeblack@google.com    trans->release();
34713821Sgabeblack@google.com}
34813821Sgabeblack@google.com
34913821Sgabeblack@google.com// Similar to TLM's debug transport.
35013821Sgabeblack@google.comvoid
35113821Sgabeblack@google.comGem5ToTlmBridge::recvFunctional(PacketPtr packet)
35213821Sgabeblack@google.com{
35313821Sgabeblack@google.com    // Prepare the transaction.
35413821Sgabeblack@google.com    tlm::tlm_generic_payload *trans = mm.allocate();
35513821Sgabeblack@google.com    trans->acquire();
35613821Sgabeblack@google.com    packet2payload(packet, *trans);
35713821Sgabeblack@google.com
35813821Sgabeblack@google.com    // Attach the packet pointer to the TLM transaction to keep track.
35913821Sgabeblack@google.com    auto *extension = new Gem5SystemC::Gem5Extension(packet);
36013821Sgabeblack@google.com    trans->set_auto_extension(extension);
36113821Sgabeblack@google.com
36213821Sgabeblack@google.com    /* Execute Debug Transport: */
36313821Sgabeblack@google.com    unsigned int bytes = socket->transport_dbg(*trans);
36413821Sgabeblack@google.com    if (bytes != trans->get_data_length()) {
36513821Sgabeblack@google.com        SC_REPORT_FATAL("Gem5ToTlmBridge",
36613821Sgabeblack@google.com                "debug transport was not completed");
36713821Sgabeblack@google.com    }
36813821Sgabeblack@google.com
36913821Sgabeblack@google.com    trans->release();
37013821Sgabeblack@google.com}
37113821Sgabeblack@google.com
37213821Sgabeblack@google.comtlm::tlm_sync_enum
37313821Sgabeblack@google.comGem5ToTlmBridge::nb_transport_bw(tlm::tlm_generic_payload &trans,
37413821Sgabeblack@google.com    tlm::tlm_phase &phase, sc_core::sc_time &delay)
37513821Sgabeblack@google.com{
37613821Sgabeblack@google.com    auto *pe = new Gem5SystemC::PayloadEvent<Gem5ToTlmBridge>(
37713821Sgabeblack@google.com            *this, &Gem5ToTlmBridge::pec, "PE");
37813821Sgabeblack@google.com    Tick nextEventTick = curTick() + delay.value();
37913821Sgabeblack@google.com    system->wakeupEventQueue(nextEventTick);
38013821Sgabeblack@google.com    system->schedule(pe, nextEventTick);
38113821Sgabeblack@google.com    return tlm::TLM_ACCEPTED;
38213821Sgabeblack@google.com}
38313821Sgabeblack@google.com
38413821Sgabeblack@google.comGem5ToTlmBridge::Gem5ToTlmBridge(
38513821Sgabeblack@google.com        Params *params, const sc_core::sc_module_name &mn) :
38613821Sgabeblack@google.com    sc_core::sc_module(mn), bsp(std::string(name()) + ".gem5", *this),
38713821Sgabeblack@google.com    socket("tlm_socket"),
38813821Sgabeblack@google.com    wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
38913821Sgabeblack@google.com    system(params->system), blockingRequest(nullptr),
39013821Sgabeblack@google.com    needToSendRequestRetry(false), blockingResponse(nullptr),
39113821Sgabeblack@google.com    addrRanges(params->addr_ranges.begin(), params->addr_ranges.end())
39213821Sgabeblack@google.com{
39313821Sgabeblack@google.com}
39413821Sgabeblack@google.com
39513821Sgabeblack@google.com::Port &
39613821Sgabeblack@google.comGem5ToTlmBridge::gem5_getPort(const std::string &if_name, int idx)
39713821Sgabeblack@google.com{
39813821Sgabeblack@google.com    if (if_name == "gem5")
39913821Sgabeblack@google.com        return bsp;
40013821Sgabeblack@google.com    else if (if_name == "tlm")
40113821Sgabeblack@google.com        return wrapper;
40213821Sgabeblack@google.com
40313821Sgabeblack@google.com    return sc_core::sc_module::gem5_getPort(if_name, idx);
40413821Sgabeblack@google.com}
40513821Sgabeblack@google.com
40613821Sgabeblack@google.comvoid
40713821Sgabeblack@google.comGem5ToTlmBridge::before_end_of_elaboration()
40813821Sgabeblack@google.com{
40913821Sgabeblack@google.com    bsp.sendRangeChange();
41013821Sgabeblack@google.com
41113821Sgabeblack@google.com    socket.register_nb_transport_bw(this, &Gem5ToTlmBridge::nb_transport_bw);
41213821Sgabeblack@google.com    sc_core::sc_module::before_end_of_elaboration();
41313821Sgabeblack@google.com}
41413821Sgabeblack@google.com
41513821Sgabeblack@google.com} // namespace sc_gem5
41613821Sgabeblack@google.com
41713821Sgabeblack@google.comsc_gem5::Gem5ToTlmBridge *
41813821Sgabeblack@google.comGem5ToTlmBridgeParams::create()
41913821Sgabeblack@google.com{
42013821Sgabeblack@google.com    return new sc_gem5::Gem5ToTlmBridge(
42113821Sgabeblack@google.com            this, sc_core::sc_module_name(name.c_str()));
42213821Sgabeblack@google.com}
423