tlm_to_gem5.cc revision 13821:f9252f27ded7
15083Sgblack@eecs.umich.edu/*
25083Sgblack@eecs.umich.edu * Copyright 2019 Google, Inc.
35083Sgblack@eecs.umich.edu *
47087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
57087Snate@binkert.org * modification, are permitted provided that the following conditions are
67087Snate@binkert.org * met: redistributions of source code must retain the above copyright
77087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
87087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
97087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
107087Snate@binkert.org * documentation and/or other materials provided with the distribution;
117087Snate@binkert.org * neither the name of the copyright holders nor the names of its
125083Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
137087Snate@binkert.org * this software without specific prior written permission.
147087Snate@binkert.org *
157087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
177087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
187087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
197087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
207087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
215083Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
227087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
235083Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245083Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
255083Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265083Sgblack@eecs.umich.edu *
275083Sgblack@eecs.umich.edu * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
285083Sgblack@eecs.umich.edu * All rights reserved.
295083Sgblack@eecs.umich.edu *
305083Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
315083Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
325083Sgblack@eecs.umich.edu * met:
335083Sgblack@eecs.umich.edu *
345083Sgblack@eecs.umich.edu * 1. Redistributions of source code must retain the above copyright notice,
355083Sgblack@eecs.umich.edu *    this list of conditions and the following disclaimer.
365083Sgblack@eecs.umich.edu *
375083Sgblack@eecs.umich.edu * 2. Redistributions in binary form must reproduce the above copyright
385083Sgblack@eecs.umich.edu *    notice, this list of conditions and the following disclaimer in the
395083Sgblack@eecs.umich.edu *    documentation and/or other materials provided with the distribution.
405083Sgblack@eecs.umich.edu *
415083Sgblack@eecs.umich.edu * 3. Neither the name of the copyright holder nor the names of its
425083Sgblack@eecs.umich.edu *    contributors may be used to endorse or promote products derived from
435083Sgblack@eecs.umich.edu *    this software without specific prior written permission.
445083Sgblack@eecs.umich.edu *
455083Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
465083Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
475083Sgblack@eecs.umich.edu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
485083Sgblack@eecs.umich.edu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
495083Sgblack@eecs.umich.edu * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
505083Sgblack@eecs.umich.edu * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
515083Sgblack@eecs.umich.edu * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
525083Sgblack@eecs.umich.edu * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
535083Sgblack@eecs.umich.edu * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
545083Sgblack@eecs.umich.edu * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
555083Sgblack@eecs.umich.edu * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
565083Sgblack@eecs.umich.edu *
575083Sgblack@eecs.umich.edu * Authors: Gabe Black
585083Sgblack@eecs.umich.edu *          Christian Menard
595083Sgblack@eecs.umich.edu */
605083Sgblack@eecs.umich.edu
615083Sgblack@eecs.umich.edu#include "systemc/tlm_bridge/tlm_to_gem5.hh"
625083Sgblack@eecs.umich.edu
635083Sgblack@eecs.umich.edu#include "sim/system.hh"
645083Sgblack@eecs.umich.edu#include "systemc/ext/core/sc_module_name.hh"
655083Sgblack@eecs.umich.edu
665083Sgblack@eecs.umich.edunamespace sc_gem5
675083Sgblack@eecs.umich.edu{
685083Sgblack@eecs.umich.edu
695083Sgblack@eecs.umich.eduvoid
705083Sgblack@eecs.umich.eduTlmToGem5Bridge::sendEndReq(tlm::tlm_generic_payload &trans)
715083Sgblack@eecs.umich.edu{
725083Sgblack@eecs.umich.edu    tlm::tlm_phase phase = tlm::END_REQ;
735083Sgblack@eecs.umich.edu    auto delay = sc_core::SC_ZERO_TIME;
745083Sgblack@eecs.umich.edu
755083Sgblack@eecs.umich.edu    auto status = socket->nb_transport_bw(trans, phase, delay);
765083Sgblack@eecs.umich.edu    panic_if(status != tlm::TLM_ACCEPTED,
775083Sgblack@eecs.umich.edu             "Unexpected status after sending END_REQ");
785083Sgblack@eecs.umich.edu}
797620Sgblack@eecs.umich.edu
806345Sgblack@eecs.umich.eduvoid
815083Sgblack@eecs.umich.eduTlmToGem5Bridge::sendBeginResp(tlm::tlm_generic_payload &trans,
825083Sgblack@eecs.umich.edu                               sc_core::sc_time &delay)
835083Sgblack@eecs.umich.edu{
845083Sgblack@eecs.umich.edu    tlm::tlm_phase phase = tlm::BEGIN_RESP;
855083Sgblack@eecs.umich.edu
865083Sgblack@eecs.umich.edu    trans.set_response_status(tlm::TLM_OK_RESPONSE);
875083Sgblack@eecs.umich.edu
885083Sgblack@eecs.umich.edu    auto status = socket->nb_transport_bw(trans, phase, delay);
897620Sgblack@eecs.umich.edu
906345Sgblack@eecs.umich.edu    if (status == tlm::TLM_COMPLETED ||
915083Sgblack@eecs.umich.edu        (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
927620Sgblack@eecs.umich.edu        // transaction completed -> no need to wait for tlm::END_RESP
935083Sgblack@eecs.umich.edu        responseInProgress = false;
945083Sgblack@eecs.umich.edu    } else if (status == tlm::TLM_ACCEPTED) {
955083Sgblack@eecs.umich.edu        // we need to wait for tlm::END_RESP
967626Sgblack@eecs.umich.edu        responseInProgress = true;
975083Sgblack@eecs.umich.edu    } else {
985083Sgblack@eecs.umich.edu        panic("Unexpected status after sending BEGIN_RESP");
995083Sgblack@eecs.umich.edu    }
1005083Sgblack@eecs.umich.edu}
1015083Sgblack@eecs.umich.edu
1025083Sgblack@eecs.umich.eduvoid
1035083Sgblack@eecs.umich.eduTlmToGem5Bridge::handleBeginReq(tlm::tlm_generic_payload &trans)
1045083Sgblack@eecs.umich.edu{
1055083Sgblack@eecs.umich.edu    sc_assert(!waitForRetry);
1065083Sgblack@eecs.umich.edu    sc_assert(pendingRequest == nullptr);
1075083Sgblack@eecs.umich.edu    sc_assert(pendingPacket == nullptr);
1085083Sgblack@eecs.umich.edu
1095083Sgblack@eecs.umich.edu    trans.acquire();
1105083Sgblack@eecs.umich.edu
1115083Sgblack@eecs.umich.edu    PacketPtr pkt = nullptr;
1125083Sgblack@eecs.umich.edu
1135083Sgblack@eecs.umich.edu    Gem5SystemC::Gem5Extension *extension = nullptr;
1145083Sgblack@eecs.umich.edu    trans.get_extension(extension);
1155083Sgblack@eecs.umich.edu
1165083Sgblack@eecs.umich.edu    // If there is an extension, this transaction was initiated by the gem5
1175083Sgblack@eecs.umich.edu    // world and we can pipe through the original packet. Otherwise, we
1185083Sgblack@eecs.umich.edu    // generate a new packet based on the transaction.
1195083Sgblack@eecs.umich.edu    if (extension != nullptr) {
1205083Sgblack@eecs.umich.edu        extension->setPipeThrough();
1215083Sgblack@eecs.umich.edu        pkt = extension->getPacket();
1225083Sgblack@eecs.umich.edu    } else {
1235083Sgblack@eecs.umich.edu        pkt = generatePacket(trans);
1245083Sgblack@eecs.umich.edu    }
1255083Sgblack@eecs.umich.edu
1265083Sgblack@eecs.umich.edu    auto tlmSenderState = new TlmSenderState(trans);
1275083Sgblack@eecs.umich.edu    pkt->pushSenderState(tlmSenderState);
1285083Sgblack@eecs.umich.edu
1295083Sgblack@eecs.umich.edu    if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
1305083Sgblack@eecs.umich.edu        sendEndReq(trans);
1315083Sgblack@eecs.umich.edu        trans.release();
1325083Sgblack@eecs.umich.edu    } else { // port is blocked -> wait for retry before sending END_REQ
1335083Sgblack@eecs.umich.edu        waitForRetry = true;
1345083Sgblack@eecs.umich.edu        pendingRequest = &trans;
1355083Sgblack@eecs.umich.edu        pendingPacket = pkt;
1365083Sgblack@eecs.umich.edu    }
1375083Sgblack@eecs.umich.edu}
1385083Sgblack@eecs.umich.edu
1395083Sgblack@eecs.umich.eduvoid
1405083Sgblack@eecs.umich.eduTlmToGem5Bridge::handleEndResp(tlm::tlm_generic_payload &trans)
1415083Sgblack@eecs.umich.edu{
1425083Sgblack@eecs.umich.edu    sc_assert(responseInProgress);
1435083Sgblack@eecs.umich.edu
1445083Sgblack@eecs.umich.edu    responseInProgress = false;
1455083Sgblack@eecs.umich.edu
1465083Sgblack@eecs.umich.edu    checkTransaction(trans);
1475083Sgblack@eecs.umich.edu
1485083Sgblack@eecs.umich.edu    if (needToSendRetry) {
1495083Sgblack@eecs.umich.edu        bmp.sendRetryResp();
1505083Sgblack@eecs.umich.edu        needToSendRetry = false;
1515083Sgblack@eecs.umich.edu    }
1525083Sgblack@eecs.umich.edu}
1535083Sgblack@eecs.umich.edu
1545083Sgblack@eecs.umich.eduPacketPtr
1555083Sgblack@eecs.umich.eduTlmToGem5Bridge::generatePacket(tlm::tlm_generic_payload &trans)
1565083Sgblack@eecs.umich.edu{
1575083Sgblack@eecs.umich.edu    MemCmd cmd;
1585083Sgblack@eecs.umich.edu
1595083Sgblack@eecs.umich.edu    switch (trans.get_command()) {
1605083Sgblack@eecs.umich.edu        case tlm::TLM_READ_COMMAND:
1615083Sgblack@eecs.umich.edu            cmd = MemCmd::ReadReq;
1625083Sgblack@eecs.umich.edu            break;
1635083Sgblack@eecs.umich.edu        case tlm::TLM_WRITE_COMMAND:
1645083Sgblack@eecs.umich.edu            cmd = MemCmd::WriteReq;
1655083Sgblack@eecs.umich.edu            break;
1665083Sgblack@eecs.umich.edu        case tlm::TLM_IGNORE_COMMAND:
1675083Sgblack@eecs.umich.edu            return nullptr;
1685083Sgblack@eecs.umich.edu        default:
1695083Sgblack@eecs.umich.edu            SC_REPORT_FATAL("TlmToGem5Bridge",
1705083Sgblack@eecs.umich.edu                            "received transaction with unsupported command");
1715083Sgblack@eecs.umich.edu    }
1725083Sgblack@eecs.umich.edu
1735083Sgblack@eecs.umich.edu    Request::Flags flags;
1745083Sgblack@eecs.umich.edu    auto req = std::make_shared<Request>(
1755083Sgblack@eecs.umich.edu        trans.get_address(), trans.get_data_length(), flags, masterId);
1765083Sgblack@eecs.umich.edu
1775083Sgblack@eecs.umich.edu    /*
1785083Sgblack@eecs.umich.edu     * Allocate a new Packet. The packet will be deleted when it returns from
1795083Sgblack@eecs.umich.edu     * the gem5 world as a response.
1805083Sgblack@eecs.umich.edu     */
1815083Sgblack@eecs.umich.edu    auto pkt = new Packet(req, cmd);
1825083Sgblack@eecs.umich.edu    pkt->dataStatic(trans.get_data_ptr());
1835083Sgblack@eecs.umich.edu
1845083Sgblack@eecs.umich.edu    return pkt;
1855083Sgblack@eecs.umich.edu}
1865083Sgblack@eecs.umich.edu
1875083Sgblack@eecs.umich.eduvoid
1885083Sgblack@eecs.umich.eduTlmToGem5Bridge::destroyPacket(PacketPtr pkt)
1895083Sgblack@eecs.umich.edu{
1905083Sgblack@eecs.umich.edu    delete pkt;
1915083Sgblack@eecs.umich.edu}
1925083Sgblack@eecs.umich.edu
1935083Sgblack@eecs.umich.eduvoid
1945083Sgblack@eecs.umich.eduTlmToGem5Bridge::checkTransaction(tlm::tlm_generic_payload &trans)
1955083Sgblack@eecs.umich.edu{
1965083Sgblack@eecs.umich.edu    if (trans.is_response_error()) {
1975083Sgblack@eecs.umich.edu        std::stringstream ss;
1985083Sgblack@eecs.umich.edu        ss << "Transaction returned with error, response status = "
1995083Sgblack@eecs.umich.edu           << trans.get_response_string();
2007620Sgblack@eecs.umich.edu        SC_REPORT_ERROR("TLM-2", ss.str().c_str());
2017620Sgblack@eecs.umich.edu    }
2025083Sgblack@eecs.umich.edu}
2035083Sgblack@eecs.umich.edu
2045083Sgblack@eecs.umich.eduvoid
2055083Sgblack@eecs.umich.eduTlmToGem5Bridge::peq_cb(tlm::tlm_generic_payload &trans,
2065083Sgblack@eecs.umich.edu                        const tlm::tlm_phase &phase)
2075083Sgblack@eecs.umich.edu{
2085083Sgblack@eecs.umich.edu    switch (phase) {
2095083Sgblack@eecs.umich.edu        case tlm::BEGIN_REQ:
2105083Sgblack@eecs.umich.edu            handleBeginReq(trans);
2115083Sgblack@eecs.umich.edu            break;
2126345Sgblack@eecs.umich.edu        case tlm::END_RESP:
2135083Sgblack@eecs.umich.edu            handleEndResp(trans);
2146345Sgblack@eecs.umich.edu            break;
2155083Sgblack@eecs.umich.edu        default:
2168588Sgblack@eecs.umich.edu            panic("unimplemented phase in callback");
2178588Sgblack@eecs.umich.edu    }
2189010Snilay@cs.wisc.edu}
2199010Snilay@cs.wisc.edu
2205083Sgblack@eecs.umich.edutlm::tlm_sync_enum
2215083Sgblack@eecs.umich.eduTlmToGem5Bridge::nb_transport_fw(
2228588Sgblack@eecs.umich.edu        tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
2235083Sgblack@eecs.umich.edu        sc_core::sc_time &delay)
2245083Sgblack@eecs.umich.edu{
2255083Sgblack@eecs.umich.edu    unsigned len = trans.get_data_length();
2265083Sgblack@eecs.umich.edu    unsigned char *byteEnable = trans.get_byte_enable_ptr();
2275083Sgblack@eecs.umich.edu    unsigned width = trans.get_streaming_width();
2285083Sgblack@eecs.umich.edu
2295083Sgblack@eecs.umich.edu    // check the transaction attributes for unsupported features ...
2305083Sgblack@eecs.umich.edu    if (byteEnable != 0) {
2316345Sgblack@eecs.umich.edu        trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
2326345Sgblack@eecs.umich.edu        return tlm::TLM_COMPLETED;
2335083Sgblack@eecs.umich.edu    }
2345083Sgblack@eecs.umich.edu    if (width < len) { // is this a burst request?
2355083Sgblack@eecs.umich.edu        trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
2365083Sgblack@eecs.umich.edu        return tlm::TLM_COMPLETED;
2375083Sgblack@eecs.umich.edu    }
2385083Sgblack@eecs.umich.edu
2395083Sgblack@eecs.umich.edu    // ... and queue the valid transaction
2405083Sgblack@eecs.umich.edu    trans.acquire();
2415083Sgblack@eecs.umich.edu    peq.notify(trans, phase, delay);
2425083Sgblack@eecs.umich.edu    return tlm::TLM_ACCEPTED;
2435083Sgblack@eecs.umich.edu}
2445083Sgblack@eecs.umich.edu
2455083Sgblack@eecs.umich.eduvoid
2465083Sgblack@eecs.umich.eduTlmToGem5Bridge::b_transport(tlm::tlm_generic_payload &trans,
2475083Sgblack@eecs.umich.edu                             sc_core::sc_time &t)
2485083Sgblack@eecs.umich.edu{
2495083Sgblack@eecs.umich.edu    Gem5SystemC::Gem5Extension *extension = nullptr;
2505083Sgblack@eecs.umich.edu    trans.get_extension(extension);
2515083Sgblack@eecs.umich.edu
2525083Sgblack@eecs.umich.edu    PacketPtr pkt = nullptr;
2535083Sgblack@eecs.umich.edu
2545083Sgblack@eecs.umich.edu    // If there is an extension, this transaction was initiated by the gem5
2555083Sgblack@eecs.umich.edu    // world and we can pipe through the original packet.
2565083Sgblack@eecs.umich.edu    if (extension != nullptr) {
2575083Sgblack@eecs.umich.edu        extension->setPipeThrough();
2585083Sgblack@eecs.umich.edu        pkt = extension->getPacket();
2595083Sgblack@eecs.umich.edu    } else {
2605083Sgblack@eecs.umich.edu        pkt = generatePacket(trans);
2615083Sgblack@eecs.umich.edu    }
2625083Sgblack@eecs.umich.edu
2635083Sgblack@eecs.umich.edu    Tick ticks = bmp.sendAtomic(pkt);
2645083Sgblack@eecs.umich.edu
2655083Sgblack@eecs.umich.edu    // send an atomic request to gem5
2665083Sgblack@eecs.umich.edu    panic_if(pkt->needsResponse() && !pkt->isResponse(),
2675083Sgblack@eecs.umich.edu             "Packet sending failed!\n");
2685083Sgblack@eecs.umich.edu
2695083Sgblack@eecs.umich.edu    auto delay =
2705083Sgblack@eecs.umich.edu      sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS);
2715083Sgblack@eecs.umich.edu
2725083Sgblack@eecs.umich.edu    // update time
2735083Sgblack@eecs.umich.edu    t += delay;
2745083Sgblack@eecs.umich.edu
2755083Sgblack@eecs.umich.edu    if (extension == nullptr)
2766345Sgblack@eecs.umich.edu        destroyPacket(pkt);
2775083Sgblack@eecs.umich.edu
2785083Sgblack@eecs.umich.edu    trans.set_response_status(tlm::TLM_OK_RESPONSE);
2795083Sgblack@eecs.umich.edu}
2805083Sgblack@eecs.umich.edu
2815083Sgblack@eecs.umich.eduunsigned int
2825083Sgblack@eecs.umich.eduTlmToGem5Bridge::transport_dbg(tlm::tlm_generic_payload &trans)
2835083Sgblack@eecs.umich.edu{
2845083Sgblack@eecs.umich.edu    Gem5SystemC::Gem5Extension *extension = nullptr;
2855083Sgblack@eecs.umich.edu    trans.get_extension(extension);
2865083Sgblack@eecs.umich.edu
2879010Snilay@cs.wisc.edu    // If there is an extension, this transaction was initiated by the gem5
2889010Snilay@cs.wisc.edu    // world and we can pipe through the original packet.
2899010Snilay@cs.wisc.edu    if (extension != nullptr) {
2909010Snilay@cs.wisc.edu        extension->setPipeThrough();
2919010Snilay@cs.wisc.edu        bmp.sendFunctional(extension->getPacket());
2929010Snilay@cs.wisc.edu    } else {
2939010Snilay@cs.wisc.edu        auto pkt = generatePacket(trans);
2945083Sgblack@eecs.umich.edu        if (pkt) {
2959010Snilay@cs.wisc.edu            bmp.sendFunctional(pkt);
2965083Sgblack@eecs.umich.edu            destroyPacket(pkt);
2975083Sgblack@eecs.umich.edu        }
2985083Sgblack@eecs.umich.edu    }
2995083Sgblack@eecs.umich.edu
300    return trans.get_data_length();
301}
302
303bool
304TlmToGem5Bridge::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
305                                    tlm::tlm_dmi &dmi_data)
306{
307    return false;
308}
309
310bool
311TlmToGem5Bridge::recvTimingResp(PacketPtr pkt)
312{
313    // exclusion rule
314    // We need to Wait for END_RESP before sending next BEGIN_RESP
315    if (responseInProgress) {
316        sc_assert(!needToSendRetry);
317        needToSendRetry = true;
318        return false;
319    }
320
321    sc_assert(pkt->isResponse());
322
323    /*
324     * Pay for annotated transport delays.
325     *
326     * See recvTimingReq in sc_slave_port.cc for a detailed description.
327     */
328    auto delay = sc_core::sc_time::from_value(pkt->payloadDelay);
329    // reset the delays
330    pkt->payloadDelay = 0;
331    pkt->headerDelay = 0;
332
333    auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
334    sc_assert(tlmSenderState != nullptr);
335
336    auto &trans = tlmSenderState->trans;
337
338    Gem5SystemC::Gem5Extension *extension = nullptr;
339    trans.get_extension(extension);
340
341    // clean up
342    delete tlmSenderState;
343
344    // If there is an extension the packet was piped through and we must not
345    // delete it. The packet travels back with the transaction.
346    if (extension == nullptr)
347        destroyPacket(pkt);
348    else
349        sc_assert(extension->isPipeThrough());
350
351    sendBeginResp(trans, delay);
352    trans.release();
353
354    return true;
355}
356
357void
358TlmToGem5Bridge::recvReqRetry()
359{
360    sc_assert(waitForRetry);
361    sc_assert(pendingRequest != nullptr);
362    sc_assert(pendingPacket != nullptr);
363
364    if (bmp.sendTimingReq(pendingPacket)) {
365        waitForRetry = false;
366        pendingPacket = nullptr;
367
368        auto &trans = *pendingRequest;
369        sendEndReq(trans);
370        trans.release();
371
372        pendingRequest = nullptr;
373    }
374}
375
376void
377TlmToGem5Bridge::recvRangeChange()
378{
379    SC_REPORT_WARNING("TlmToGem5Bridge",
380                      "received address range change but ignored it");
381}
382
383::Port &
384TlmToGem5Bridge::gem5_getPort(const std::string &if_name, int idx)
385{
386    if (if_name == "gem5")
387        return bmp;
388    else if (if_name == "tlm")
389        return wrapper;
390
391    return sc_core::sc_module::gem5_getPort(if_name, idx);
392}
393
394TlmToGem5Bridge::TlmToGem5Bridge(
395        Params *params, const sc_core::sc_module_name &mn) :
396    sc_core::sc_module(mn), peq(this, &TlmToGem5Bridge::peq_cb),
397    waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr),
398    needToSendRetry(false), responseInProgress(false),
399    bmp(std::string(name()) + "master", *this), socket("tlm_socket"),
400    wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
401    system(params->system),
402    masterId(params->system->getGlobalMasterId(
403                std::string("[systemc].") + name()))
404{
405}
406
407void
408TlmToGem5Bridge::before_end_of_elaboration()
409{
410    /*
411     * Register the TLM non-blocking interface when using gem5 Timing mode and
412     * the TLM blocking interface when using the gem5 Atomic mode.
413     * Then the magic (TM) in simple_target_socket automatically transforms
414     * non-blocking in blocking transactions and vice versa.
415     *
416     * NOTE: The mode may change during execution.
417     */
418    if (system->isTimingMode()) {
419        SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface");
420        socket.register_nb_transport_fw(
421                this, &TlmToGem5Bridge::nb_transport_fw);
422    } else if (system->isAtomicMode()) {
423        SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface");
424        socket.register_b_transport(
425                this, &TlmToGem5Bridge::b_transport);
426    } else {
427        panic("gem5 operates neither in Timing nor in Atomic mode");
428    }
429
430    socket.register_transport_dbg(this, &TlmToGem5Bridge::transport_dbg);
431
432    sc_core::sc_module::before_end_of_elaboration();
433}
434
435} // namespace sc_gem5
436
437sc_gem5::TlmToGem5Bridge *
438TlmToGem5BridgeParams::create()
439{
440    return new sc_gem5::TlmToGem5Bridge(
441            this, sc_core::sc_module_name(name.c_str()));
442}
443