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