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