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) 2016, Dresden University of Technology (TU Dresden)
2813821Sgabeblack@google.com * All rights reserved.
2913821Sgabeblack@google.com *
3013821Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
3113821Sgabeblack@google.com * modification, are permitted provided that the following conditions are
3213821Sgabeblack@google.com * met:
3313821Sgabeblack@google.com *
3413821Sgabeblack@google.com * 1. Redistributions of source code must retain the above copyright notice,
3513821Sgabeblack@google.com *    this list of conditions and the following disclaimer.
3613821Sgabeblack@google.com *
3713821Sgabeblack@google.com * 2. Redistributions in binary form must reproduce the above copyright
3813821Sgabeblack@google.com *    notice, this list of conditions and the following disclaimer in the
3913821Sgabeblack@google.com *    documentation and/or other materials provided with the distribution.
4013821Sgabeblack@google.com *
4113821Sgabeblack@google.com * 3. Neither the name of the copyright holder nor the names of its
4213821Sgabeblack@google.com *    contributors may be used to endorse or promote products derived from
4313821Sgabeblack@google.com *    this software without specific prior written permission.
4413821Sgabeblack@google.com *
4513821Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4613821Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
4713821Sgabeblack@google.com * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4813821Sgabeblack@google.com * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
4913821Sgabeblack@google.com * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
5013821Sgabeblack@google.com * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5113821Sgabeblack@google.com * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
5213821Sgabeblack@google.com * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5313821Sgabeblack@google.com * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
5413821Sgabeblack@google.com * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5513821Sgabeblack@google.com * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5613821Sgabeblack@google.com *
5713821Sgabeblack@google.com * Authors: Gabe Black
5813821Sgabeblack@google.com *          Christian Menard
5913821Sgabeblack@google.com */
6013821Sgabeblack@google.com
6113821Sgabeblack@google.com#include "systemc/tlm_bridge/tlm_to_gem5.hh"
6213821Sgabeblack@google.com
6313823Sgabeblack@google.com#include "params/TlmToGem5Bridge32.hh"
6413823Sgabeblack@google.com#include "params/TlmToGem5Bridge64.hh"
6513821Sgabeblack@google.com#include "sim/system.hh"
6613821Sgabeblack@google.com#include "systemc/ext/core/sc_module_name.hh"
6713846Sgabeblack@google.com#include "systemc/ext/core/sc_time.hh"
6813821Sgabeblack@google.com
6913821Sgabeblack@google.comnamespace sc_gem5
7013821Sgabeblack@google.com{
7113821Sgabeblack@google.com
7214275Sgabeblack@google.comPacketPtr
7314275Sgabeblack@google.compayload2packet(MasterID masterId, tlm::tlm_generic_payload &trans)
7414275Sgabeblack@google.com{
7514275Sgabeblack@google.com    MemCmd cmd;
7614275Sgabeblack@google.com
7714275Sgabeblack@google.com    switch (trans.get_command()) {
7814275Sgabeblack@google.com        case tlm::TLM_READ_COMMAND:
7914275Sgabeblack@google.com            cmd = MemCmd::ReadReq;
8014275Sgabeblack@google.com            break;
8114275Sgabeblack@google.com        case tlm::TLM_WRITE_COMMAND:
8214275Sgabeblack@google.com            cmd = MemCmd::WriteReq;
8314275Sgabeblack@google.com            break;
8414275Sgabeblack@google.com        case tlm::TLM_IGNORE_COMMAND:
8514275Sgabeblack@google.com            return nullptr;
8614275Sgabeblack@google.com        default:
8714275Sgabeblack@google.com            SC_REPORT_FATAL("TlmToGem5Bridge",
8814275Sgabeblack@google.com                            "received transaction with unsupported command");
8914275Sgabeblack@google.com    }
9014275Sgabeblack@google.com
9114275Sgabeblack@google.com    Request::Flags flags;
9214275Sgabeblack@google.com    auto req = std::make_shared<Request>(
9314275Sgabeblack@google.com        trans.get_address(), trans.get_data_length(), flags, masterId);
9414275Sgabeblack@google.com
9514275Sgabeblack@google.com    /*
9614275Sgabeblack@google.com     * Allocate a new Packet. The packet will be deleted when it returns from
9714275Sgabeblack@google.com     * the gem5 world as a response.
9814275Sgabeblack@google.com     */
9914275Sgabeblack@google.com    auto pkt = new Packet(req, cmd);
10014275Sgabeblack@google.com    pkt->dataStatic(trans.get_data_ptr());
10114275Sgabeblack@google.com
10214275Sgabeblack@google.com    return pkt;
10314275Sgabeblack@google.com}
10414275Sgabeblack@google.com
10513823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
10613821Sgabeblack@google.comvoid
10713823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::sendEndReq(tlm::tlm_generic_payload &trans)
10813821Sgabeblack@google.com{
10913821Sgabeblack@google.com    tlm::tlm_phase phase = tlm::END_REQ;
11013821Sgabeblack@google.com    auto delay = sc_core::SC_ZERO_TIME;
11113821Sgabeblack@google.com
11213821Sgabeblack@google.com    auto status = socket->nb_transport_bw(trans, phase, delay);
11313821Sgabeblack@google.com    panic_if(status != tlm::TLM_ACCEPTED,
11413821Sgabeblack@google.com             "Unexpected status after sending END_REQ");
11513821Sgabeblack@google.com}
11613821Sgabeblack@google.com
11713823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
11813821Sgabeblack@google.comvoid
11913823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::sendBeginResp(tlm::tlm_generic_payload &trans,
12013823Sgabeblack@google.com                                         sc_core::sc_time &delay)
12113821Sgabeblack@google.com{
12213821Sgabeblack@google.com    tlm::tlm_phase phase = tlm::BEGIN_RESP;
12313821Sgabeblack@google.com
12413821Sgabeblack@google.com    trans.set_response_status(tlm::TLM_OK_RESPONSE);
12513821Sgabeblack@google.com
12613821Sgabeblack@google.com    auto status = socket->nb_transport_bw(trans, phase, delay);
12713821Sgabeblack@google.com
12813821Sgabeblack@google.com    if (status == tlm::TLM_COMPLETED ||
12913821Sgabeblack@google.com        (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
13013821Sgabeblack@google.com        // transaction completed -> no need to wait for tlm::END_RESP
13113821Sgabeblack@google.com        responseInProgress = false;
13213821Sgabeblack@google.com    } else if (status == tlm::TLM_ACCEPTED) {
13313821Sgabeblack@google.com        // we need to wait for tlm::END_RESP
13413821Sgabeblack@google.com        responseInProgress = true;
13513821Sgabeblack@google.com    } else {
13613821Sgabeblack@google.com        panic("Unexpected status after sending BEGIN_RESP");
13713821Sgabeblack@google.com    }
13813821Sgabeblack@google.com}
13913821Sgabeblack@google.com
14013823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
14113821Sgabeblack@google.comvoid
14213823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::handleBeginReq(tlm::tlm_generic_payload &trans)
14313821Sgabeblack@google.com{
14413821Sgabeblack@google.com    sc_assert(!waitForRetry);
14513821Sgabeblack@google.com    sc_assert(pendingRequest == nullptr);
14613821Sgabeblack@google.com    sc_assert(pendingPacket == nullptr);
14713821Sgabeblack@google.com
14813821Sgabeblack@google.com    trans.acquire();
14913821Sgabeblack@google.com
15013821Sgabeblack@google.com    PacketPtr pkt = nullptr;
15113821Sgabeblack@google.com
15213821Sgabeblack@google.com    Gem5SystemC::Gem5Extension *extension = nullptr;
15313821Sgabeblack@google.com    trans.get_extension(extension);
15413821Sgabeblack@google.com
15513821Sgabeblack@google.com    // If there is an extension, this transaction was initiated by the gem5
15613821Sgabeblack@google.com    // world and we can pipe through the original packet. Otherwise, we
15713821Sgabeblack@google.com    // generate a new packet based on the transaction.
15813821Sgabeblack@google.com    if (extension != nullptr) {
15913821Sgabeblack@google.com        extension->setPipeThrough();
16013821Sgabeblack@google.com        pkt = extension->getPacket();
16113821Sgabeblack@google.com    } else {
16214275Sgabeblack@google.com        pkt = payload2packet(masterId, trans);
16313821Sgabeblack@google.com    }
16413821Sgabeblack@google.com
16513821Sgabeblack@google.com    auto tlmSenderState = new TlmSenderState(trans);
16613821Sgabeblack@google.com    pkt->pushSenderState(tlmSenderState);
16713821Sgabeblack@google.com
16813821Sgabeblack@google.com    if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
16913821Sgabeblack@google.com        sendEndReq(trans);
17013821Sgabeblack@google.com        trans.release();
17113821Sgabeblack@google.com    } else { // port is blocked -> wait for retry before sending END_REQ
17213821Sgabeblack@google.com        waitForRetry = true;
17313821Sgabeblack@google.com        pendingRequest = &trans;
17413821Sgabeblack@google.com        pendingPacket = pkt;
17513821Sgabeblack@google.com    }
17613821Sgabeblack@google.com}
17713821Sgabeblack@google.com
17813823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
17913821Sgabeblack@google.comvoid
18013823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::handleEndResp(tlm::tlm_generic_payload &trans)
18113821Sgabeblack@google.com{
18213821Sgabeblack@google.com    sc_assert(responseInProgress);
18313821Sgabeblack@google.com
18413821Sgabeblack@google.com    responseInProgress = false;
18513821Sgabeblack@google.com
18613821Sgabeblack@google.com    checkTransaction(trans);
18713821Sgabeblack@google.com
18813821Sgabeblack@google.com    if (needToSendRetry) {
18913821Sgabeblack@google.com        bmp.sendRetryResp();
19013821Sgabeblack@google.com        needToSendRetry = false;
19113821Sgabeblack@google.com    }
19213821Sgabeblack@google.com}
19313821Sgabeblack@google.com
19413823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
19513821Sgabeblack@google.comvoid
19613823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::destroyPacket(PacketPtr pkt)
19713821Sgabeblack@google.com{
19813821Sgabeblack@google.com    delete pkt;
19913821Sgabeblack@google.com}
20013821Sgabeblack@google.com
20113823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
20213821Sgabeblack@google.comvoid
20313823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::checkTransaction(tlm::tlm_generic_payload &trans)
20413821Sgabeblack@google.com{
20513821Sgabeblack@google.com    if (trans.is_response_error()) {
20613821Sgabeblack@google.com        std::stringstream ss;
20713821Sgabeblack@google.com        ss << "Transaction returned with error, response status = "
20813821Sgabeblack@google.com           << trans.get_response_string();
20913821Sgabeblack@google.com        SC_REPORT_ERROR("TLM-2", ss.str().c_str());
21013821Sgabeblack@google.com    }
21113821Sgabeblack@google.com}
21213821Sgabeblack@google.com
21313823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
21413821Sgabeblack@google.comvoid
21513846Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::invalidateDmi(const ::MemBackdoor &backdoor)
21613846Sgabeblack@google.com{
21713846Sgabeblack@google.com    socket->invalidate_direct_mem_ptr(
21813846Sgabeblack@google.com            backdoor.range().start(), backdoor.range().end());
21913846Sgabeblack@google.com}
22013846Sgabeblack@google.com
22113846Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
22213846Sgabeblack@google.comvoid
22313823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::peq_cb(tlm::tlm_generic_payload &trans,
22413823Sgabeblack@google.com                                  const tlm::tlm_phase &phase)
22513821Sgabeblack@google.com{
22613821Sgabeblack@google.com    switch (phase) {
22713821Sgabeblack@google.com        case tlm::BEGIN_REQ:
22813821Sgabeblack@google.com            handleBeginReq(trans);
22913821Sgabeblack@google.com            break;
23013821Sgabeblack@google.com        case tlm::END_RESP:
23113821Sgabeblack@google.com            handleEndResp(trans);
23213821Sgabeblack@google.com            break;
23313821Sgabeblack@google.com        default:
23413821Sgabeblack@google.com            panic("unimplemented phase in callback");
23513821Sgabeblack@google.com    }
23613821Sgabeblack@google.com}
23713821Sgabeblack@google.com
23813823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
23913821Sgabeblack@google.comtlm::tlm_sync_enum
24013823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::nb_transport_fw(
24113821Sgabeblack@google.com        tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
24213821Sgabeblack@google.com        sc_core::sc_time &delay)
24313821Sgabeblack@google.com{
24413821Sgabeblack@google.com    unsigned len = trans.get_data_length();
24513821Sgabeblack@google.com    unsigned char *byteEnable = trans.get_byte_enable_ptr();
24613821Sgabeblack@google.com    unsigned width = trans.get_streaming_width();
24713821Sgabeblack@google.com
24813821Sgabeblack@google.com    // check the transaction attributes for unsupported features ...
24913821Sgabeblack@google.com    if (byteEnable != 0) {
25013821Sgabeblack@google.com        trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
25113821Sgabeblack@google.com        return tlm::TLM_COMPLETED;
25213821Sgabeblack@google.com    }
25313821Sgabeblack@google.com    if (width < len) { // is this a burst request?
25413821Sgabeblack@google.com        trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
25513821Sgabeblack@google.com        return tlm::TLM_COMPLETED;
25613821Sgabeblack@google.com    }
25713821Sgabeblack@google.com
25813821Sgabeblack@google.com    // ... and queue the valid transaction
25913821Sgabeblack@google.com    trans.acquire();
26013821Sgabeblack@google.com    peq.notify(trans, phase, delay);
26113821Sgabeblack@google.com    return tlm::TLM_ACCEPTED;
26213821Sgabeblack@google.com}
26313821Sgabeblack@google.com
26413823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
26513821Sgabeblack@google.comvoid
26613823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::b_transport(tlm::tlm_generic_payload &trans,
26713823Sgabeblack@google.com                                       sc_core::sc_time &t)
26813821Sgabeblack@google.com{
26913821Sgabeblack@google.com    Gem5SystemC::Gem5Extension *extension = nullptr;
27013821Sgabeblack@google.com    trans.get_extension(extension);
27113821Sgabeblack@google.com
27213821Sgabeblack@google.com    PacketPtr pkt = nullptr;
27313821Sgabeblack@google.com
27413821Sgabeblack@google.com    // If there is an extension, this transaction was initiated by the gem5
27513821Sgabeblack@google.com    // world and we can pipe through the original packet.
27613821Sgabeblack@google.com    if (extension != nullptr) {
27713821Sgabeblack@google.com        extension->setPipeThrough();
27813821Sgabeblack@google.com        pkt = extension->getPacket();
27913821Sgabeblack@google.com    } else {
28014275Sgabeblack@google.com        pkt = payload2packet(masterId, trans);
28113821Sgabeblack@google.com    }
28213821Sgabeblack@google.com
28313846Sgabeblack@google.com    MemBackdoorPtr backdoor = nullptr;
28413846Sgabeblack@google.com    Tick ticks = bmp.sendAtomicBackdoor(pkt, backdoor);
28513846Sgabeblack@google.com    if (backdoor)
28613846Sgabeblack@google.com        trans.set_dmi_allowed(true);
28713821Sgabeblack@google.com
28813821Sgabeblack@google.com    // send an atomic request to gem5
28913821Sgabeblack@google.com    panic_if(pkt->needsResponse() && !pkt->isResponse(),
29013821Sgabeblack@google.com             "Packet sending failed!\n");
29113821Sgabeblack@google.com
29213821Sgabeblack@google.com    auto delay =
29313821Sgabeblack@google.com      sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS);
29413821Sgabeblack@google.com
29513821Sgabeblack@google.com    // update time
29613821Sgabeblack@google.com    t += delay;
29713821Sgabeblack@google.com
29813821Sgabeblack@google.com    if (extension == nullptr)
29913821Sgabeblack@google.com        destroyPacket(pkt);
30013821Sgabeblack@google.com
30113821Sgabeblack@google.com    trans.set_response_status(tlm::TLM_OK_RESPONSE);
30213821Sgabeblack@google.com}
30313821Sgabeblack@google.com
30413823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
30513821Sgabeblack@google.comunsigned int
30613823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::transport_dbg(tlm::tlm_generic_payload &trans)
30713821Sgabeblack@google.com{
30813821Sgabeblack@google.com    Gem5SystemC::Gem5Extension *extension = nullptr;
30913821Sgabeblack@google.com    trans.get_extension(extension);
31013821Sgabeblack@google.com
31113821Sgabeblack@google.com    // If there is an extension, this transaction was initiated by the gem5
31213821Sgabeblack@google.com    // world and we can pipe through the original packet.
31313821Sgabeblack@google.com    if (extension != nullptr) {
31413821Sgabeblack@google.com        extension->setPipeThrough();
31513821Sgabeblack@google.com        bmp.sendFunctional(extension->getPacket());
31613821Sgabeblack@google.com    } else {
31714275Sgabeblack@google.com        auto pkt = payload2packet(masterId, trans);
31813821Sgabeblack@google.com        if (pkt) {
31913821Sgabeblack@google.com            bmp.sendFunctional(pkt);
32013821Sgabeblack@google.com            destroyPacket(pkt);
32113821Sgabeblack@google.com        }
32213821Sgabeblack@google.com    }
32313821Sgabeblack@google.com
32413821Sgabeblack@google.com    return trans.get_data_length();
32513821Sgabeblack@google.com}
32613821Sgabeblack@google.com
32713823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
32813821Sgabeblack@google.combool
32913823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
33013823Sgabeblack@google.com                                              tlm::tlm_dmi &dmi_data)
33113821Sgabeblack@google.com{
33213846Sgabeblack@google.com    Gem5SystemC::Gem5Extension *extension = nullptr;
33313846Sgabeblack@google.com    trans.get_extension(extension);
33413846Sgabeblack@google.com
33513846Sgabeblack@google.com    PacketPtr pkt = nullptr;
33613846Sgabeblack@google.com
33713846Sgabeblack@google.com    // If there is an extension, this transaction was initiated by the gem5
33813846Sgabeblack@google.com    // world and we can pipe through the original packet.
33913846Sgabeblack@google.com    if (extension != nullptr) {
34013846Sgabeblack@google.com        extension->setPipeThrough();
34113846Sgabeblack@google.com        pkt = extension->getPacket();
34213846Sgabeblack@google.com    } else {
34314275Sgabeblack@google.com        pkt = payload2packet(masterId, trans);
34413846Sgabeblack@google.com        pkt->req->setFlags(Request::NO_ACCESS);
34513846Sgabeblack@google.com    }
34613846Sgabeblack@google.com
34713846Sgabeblack@google.com    MemBackdoorPtr backdoor = nullptr;
34813846Sgabeblack@google.com    bmp.sendAtomicBackdoor(pkt, backdoor);
34913846Sgabeblack@google.com    if (backdoor) {
35013846Sgabeblack@google.com        trans.set_dmi_allowed(true);
35113846Sgabeblack@google.com        dmi_data.set_dmi_ptr(backdoor->ptr());
35213846Sgabeblack@google.com        dmi_data.set_start_address(backdoor->range().start());
35313846Sgabeblack@google.com        dmi_data.set_end_address(backdoor->range().end());
35413846Sgabeblack@google.com
35513846Sgabeblack@google.com        typedef tlm::tlm_dmi::dmi_access_e access_t;
35613846Sgabeblack@google.com        access_t access = tlm::tlm_dmi::DMI_ACCESS_NONE;
35713846Sgabeblack@google.com        if (backdoor->readable())
35813846Sgabeblack@google.com            access = (access_t)(access | tlm::tlm_dmi::DMI_ACCESS_READ);
35913846Sgabeblack@google.com        if (backdoor->writeable())
36013846Sgabeblack@google.com            access = (access_t)(access | tlm::tlm_dmi::DMI_ACCESS_WRITE);
36113846Sgabeblack@google.com        dmi_data.set_granted_access(access);
36213846Sgabeblack@google.com
36313846Sgabeblack@google.com        backdoor->addInvalidationCallback(
36413846Sgabeblack@google.com            [this](const MemBackdoor &backdoor)
36513846Sgabeblack@google.com            {
36613846Sgabeblack@google.com                invalidateDmi(backdoor);
36713846Sgabeblack@google.com            }
36813846Sgabeblack@google.com        );
36913846Sgabeblack@google.com    }
37013846Sgabeblack@google.com
37113846Sgabeblack@google.com    if (extension == nullptr)
37213846Sgabeblack@google.com        destroyPacket(pkt);
37313846Sgabeblack@google.com
37413846Sgabeblack@google.com    trans.set_response_status(tlm::TLM_OK_RESPONSE);
37513846Sgabeblack@google.com
37613846Sgabeblack@google.com    return backdoor != nullptr;
37713821Sgabeblack@google.com}
37813821Sgabeblack@google.com
37913823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
38013821Sgabeblack@google.combool
38113823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::recvTimingResp(PacketPtr pkt)
38213821Sgabeblack@google.com{
38313821Sgabeblack@google.com    // exclusion rule
38413821Sgabeblack@google.com    // We need to Wait for END_RESP before sending next BEGIN_RESP
38513821Sgabeblack@google.com    if (responseInProgress) {
38613821Sgabeblack@google.com        sc_assert(!needToSendRetry);
38713821Sgabeblack@google.com        needToSendRetry = true;
38813821Sgabeblack@google.com        return false;
38913821Sgabeblack@google.com    }
39013821Sgabeblack@google.com
39113821Sgabeblack@google.com    sc_assert(pkt->isResponse());
39213821Sgabeblack@google.com
39313821Sgabeblack@google.com    /*
39413821Sgabeblack@google.com     * Pay for annotated transport delays.
39513821Sgabeblack@google.com     *
39613821Sgabeblack@google.com     * See recvTimingReq in sc_slave_port.cc for a detailed description.
39713821Sgabeblack@google.com     */
39813821Sgabeblack@google.com    auto delay = sc_core::sc_time::from_value(pkt->payloadDelay);
39913821Sgabeblack@google.com    // reset the delays
40013821Sgabeblack@google.com    pkt->payloadDelay = 0;
40113821Sgabeblack@google.com    pkt->headerDelay = 0;
40213821Sgabeblack@google.com
40313821Sgabeblack@google.com    auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
40413821Sgabeblack@google.com    sc_assert(tlmSenderState != nullptr);
40513821Sgabeblack@google.com
40613821Sgabeblack@google.com    auto &trans = tlmSenderState->trans;
40713821Sgabeblack@google.com
40813821Sgabeblack@google.com    Gem5SystemC::Gem5Extension *extension = nullptr;
40913821Sgabeblack@google.com    trans.get_extension(extension);
41013821Sgabeblack@google.com
41113821Sgabeblack@google.com    // clean up
41213821Sgabeblack@google.com    delete tlmSenderState;
41313821Sgabeblack@google.com
41413821Sgabeblack@google.com    // If there is an extension the packet was piped through and we must not
41513821Sgabeblack@google.com    // delete it. The packet travels back with the transaction.
41613821Sgabeblack@google.com    if (extension == nullptr)
41713821Sgabeblack@google.com        destroyPacket(pkt);
41813821Sgabeblack@google.com    else
41913821Sgabeblack@google.com        sc_assert(extension->isPipeThrough());
42013821Sgabeblack@google.com
42113821Sgabeblack@google.com    sendBeginResp(trans, delay);
42213821Sgabeblack@google.com    trans.release();
42313821Sgabeblack@google.com
42413821Sgabeblack@google.com    return true;
42513821Sgabeblack@google.com}
42613821Sgabeblack@google.com
42713823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
42813821Sgabeblack@google.comvoid
42913823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::recvReqRetry()
43013821Sgabeblack@google.com{
43113821Sgabeblack@google.com    sc_assert(waitForRetry);
43213821Sgabeblack@google.com    sc_assert(pendingRequest != nullptr);
43313821Sgabeblack@google.com    sc_assert(pendingPacket != nullptr);
43413821Sgabeblack@google.com
43513821Sgabeblack@google.com    if (bmp.sendTimingReq(pendingPacket)) {
43613821Sgabeblack@google.com        waitForRetry = false;
43713821Sgabeblack@google.com        pendingPacket = nullptr;
43813821Sgabeblack@google.com
43913821Sgabeblack@google.com        auto &trans = *pendingRequest;
44013821Sgabeblack@google.com        sendEndReq(trans);
44113821Sgabeblack@google.com        trans.release();
44213821Sgabeblack@google.com
44313821Sgabeblack@google.com        pendingRequest = nullptr;
44413821Sgabeblack@google.com    }
44513821Sgabeblack@google.com}
44613821Sgabeblack@google.com
44713823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
44813821Sgabeblack@google.comvoid
44913823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::recvRangeChange()
45013821Sgabeblack@google.com{
45113821Sgabeblack@google.com    SC_REPORT_WARNING("TlmToGem5Bridge",
45213821Sgabeblack@google.com                      "received address range change but ignored it");
45313821Sgabeblack@google.com}
45413821Sgabeblack@google.com
45513823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
45613821Sgabeblack@google.com::Port &
45713823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx)
45813821Sgabeblack@google.com{
45913821Sgabeblack@google.com    if (if_name == "gem5")
46013821Sgabeblack@google.com        return bmp;
46113821Sgabeblack@google.com    else if (if_name == "tlm")
46213821Sgabeblack@google.com        return wrapper;
46313821Sgabeblack@google.com
46413821Sgabeblack@google.com    return sc_core::sc_module::gem5_getPort(if_name, idx);
46513821Sgabeblack@google.com}
46613821Sgabeblack@google.com
46713823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
46813823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::TlmToGem5Bridge(
46913821Sgabeblack@google.com        Params *params, const sc_core::sc_module_name &mn) :
47013823Sgabeblack@google.com    TlmToGem5BridgeBase(mn), peq(this, &TlmToGem5Bridge<BITWIDTH>::peq_cb),
47113821Sgabeblack@google.com    waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr),
47213821Sgabeblack@google.com    needToSendRetry(false), responseInProgress(false),
47313821Sgabeblack@google.com    bmp(std::string(name()) + "master", *this), socket("tlm_socket"),
47413821Sgabeblack@google.com    wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
47513821Sgabeblack@google.com    system(params->system),
47613821Sgabeblack@google.com    masterId(params->system->getGlobalMasterId(
47713821Sgabeblack@google.com                std::string("[systemc].") + name()))
47813821Sgabeblack@google.com{
47913821Sgabeblack@google.com}
48013821Sgabeblack@google.com
48113823Sgabeblack@google.comtemplate <unsigned int BITWIDTH>
48213821Sgabeblack@google.comvoid
48313823Sgabeblack@google.comTlmToGem5Bridge<BITWIDTH>::before_end_of_elaboration()
48413821Sgabeblack@google.com{
48513821Sgabeblack@google.com    /*
48613821Sgabeblack@google.com     * Register the TLM non-blocking interface when using gem5 Timing mode and
48713821Sgabeblack@google.com     * the TLM blocking interface when using the gem5 Atomic mode.
48813821Sgabeblack@google.com     * Then the magic (TM) in simple_target_socket automatically transforms
48913821Sgabeblack@google.com     * non-blocking in blocking transactions and vice versa.
49013821Sgabeblack@google.com     *
49113821Sgabeblack@google.com     * NOTE: The mode may change during execution.
49213821Sgabeblack@google.com     */
49313821Sgabeblack@google.com    if (system->isTimingMode()) {
49413821Sgabeblack@google.com        SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface");
49513821Sgabeblack@google.com        socket.register_nb_transport_fw(
49613823Sgabeblack@google.com                this, &TlmToGem5Bridge<BITWIDTH>::nb_transport_fw);
49713821Sgabeblack@google.com    } else if (system->isAtomicMode()) {
49813821Sgabeblack@google.com        SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface");
49913821Sgabeblack@google.com        socket.register_b_transport(
50013823Sgabeblack@google.com                this, &TlmToGem5Bridge<BITWIDTH>::b_transport);
50113846Sgabeblack@google.com        socket.register_get_direct_mem_ptr(
50213846Sgabeblack@google.com                this, &TlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr);
50313821Sgabeblack@google.com    } else {
50413821Sgabeblack@google.com        panic("gem5 operates neither in Timing nor in Atomic mode");
50513821Sgabeblack@google.com    }
50613821Sgabeblack@google.com
50713823Sgabeblack@google.com    socket.register_transport_dbg(
50813823Sgabeblack@google.com            this, &TlmToGem5Bridge<BITWIDTH>::transport_dbg);
50913821Sgabeblack@google.com
51013821Sgabeblack@google.com    sc_core::sc_module::before_end_of_elaboration();
51113821Sgabeblack@google.com}
51213821Sgabeblack@google.com
51313821Sgabeblack@google.com} // namespace sc_gem5
51413821Sgabeblack@google.com
51513823Sgabeblack@google.comsc_gem5::TlmToGem5Bridge<32> *
51613823Sgabeblack@google.comTlmToGem5Bridge32Params::create()
51713821Sgabeblack@google.com{
51813823Sgabeblack@google.com    return new sc_gem5::TlmToGem5Bridge<32>(
51913821Sgabeblack@google.com            this, sc_core::sc_module_name(name.c_str()));
52013821Sgabeblack@google.com}
52113823Sgabeblack@google.com
52213823Sgabeblack@google.comsc_gem5::TlmToGem5Bridge<64> *
52313823Sgabeblack@google.comTlmToGem5Bridge64Params::create()
52413823Sgabeblack@google.com{
52513823Sgabeblack@google.com    return new sc_gem5::TlmToGem5Bridge<64>(
52613823Sgabeblack@google.com            this, sc_core::sc_module_name(name.c_str()));
52713823Sgabeblack@google.com}
528