112047Schristian.menard@tu-dresden.de/*
212047Schristian.menard@tu-dresden.de * Copyright (c) 2015, University of Kaiserslautern
312047Schristian.menard@tu-dresden.de * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
412047Schristian.menard@tu-dresden.de * All rights reserved.
512047Schristian.menard@tu-dresden.de *
612047Schristian.menard@tu-dresden.de * Redistribution and use in source and binary forms, with or without
712047Schristian.menard@tu-dresden.de * modification, are permitted provided that the following conditions are
812047Schristian.menard@tu-dresden.de * met:
912047Schristian.menard@tu-dresden.de *
1012047Schristian.menard@tu-dresden.de * 1. Redistributions of source code must retain the above copyright notice,
1112047Schristian.menard@tu-dresden.de *    this list of conditions and the following disclaimer.
1212047Schristian.menard@tu-dresden.de *
1312047Schristian.menard@tu-dresden.de * 2. Redistributions in binary form must reproduce the above copyright
1412047Schristian.menard@tu-dresden.de *    notice, this list of conditions and the following disclaimer in the
1512047Schristian.menard@tu-dresden.de *    documentation and/or other materials provided with the distribution.
1612047Schristian.menard@tu-dresden.de *
1712047Schristian.menard@tu-dresden.de * 3. Neither the name of the copyright holder nor the names of its
1812047Schristian.menard@tu-dresden.de *    contributors may be used to endorse or promote products derived from
1912047Schristian.menard@tu-dresden.de *    this software without specific prior written permission.
2012047Schristian.menard@tu-dresden.de *
2112047Schristian.menard@tu-dresden.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2212047Schristian.menard@tu-dresden.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2312047Schristian.menard@tu-dresden.de * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2412047Schristian.menard@tu-dresden.de * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
2512047Schristian.menard@tu-dresden.de * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2612047Schristian.menard@tu-dresden.de * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2712047Schristian.menard@tu-dresden.de * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2812047Schristian.menard@tu-dresden.de * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2912047Schristian.menard@tu-dresden.de * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3012047Schristian.menard@tu-dresden.de * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3112047Schristian.menard@tu-dresden.de * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3212047Schristian.menard@tu-dresden.de *
3312047Schristian.menard@tu-dresden.de * Authors: Matthias Jung
3412047Schristian.menard@tu-dresden.de *          Abdul Mutaal Ahmad
3512047Schristian.menard@tu-dresden.de *          Christian Menard
3612047Schristian.menard@tu-dresden.de */
3712047Schristian.menard@tu-dresden.de
3812047Schristian.menard@tu-dresden.de#include "sc_ext.hh"
3912047Schristian.menard@tu-dresden.de#include "sc_mm.hh"
4012047Schristian.menard@tu-dresden.de#include "sc_slave_port.hh"
4112047Schristian.menard@tu-dresden.de#include "slave_transactor.hh"
4212047Schristian.menard@tu-dresden.de
4312047Schristian.menard@tu-dresden.denamespace Gem5SystemC
4412047Schristian.menard@tu-dresden.de{
4512047Schristian.menard@tu-dresden.de
4612047Schristian.menard@tu-dresden.de/**
4712047Schristian.menard@tu-dresden.de * Instantiate a tlm memory manager that takes care about all the
4812047Schristian.menard@tu-dresden.de * tlm transactions in the system
4912047Schristian.menard@tu-dresden.de */
5012047Schristian.menard@tu-dresden.deMemoryManager mm;
5112047Schristian.menard@tu-dresden.de
5212047Schristian.menard@tu-dresden.de/**
5312047Schristian.menard@tu-dresden.de * Convert a gem5 packet to a TLM payload by copying all the relevant
5412047Schristian.menard@tu-dresden.de * information to a previously allocated tlm payload
5512047Schristian.menard@tu-dresden.de */
5612047Schristian.menard@tu-dresden.devoid
5712047Schristian.menard@tu-dresden.depacket2payload(PacketPtr packet, tlm::tlm_generic_payload &trans)
5812047Schristian.menard@tu-dresden.de{
5912047Schristian.menard@tu-dresden.de    trans.set_address(packet->getAddr());
6012047Schristian.menard@tu-dresden.de
6112047Schristian.menard@tu-dresden.de    /* Check if this transaction was allocated by mm */
6212047Schristian.menard@tu-dresden.de    sc_assert(trans.has_mm());
6312047Schristian.menard@tu-dresden.de
6412047Schristian.menard@tu-dresden.de    unsigned int size = packet->getSize();
6512047Schristian.menard@tu-dresden.de    unsigned char *data = packet->getPtr<unsigned char>();
6612047Schristian.menard@tu-dresden.de
6712047Schristian.menard@tu-dresden.de    trans.set_data_length(size);
6812047Schristian.menard@tu-dresden.de    trans.set_streaming_width(size);
6912047Schristian.menard@tu-dresden.de    trans.set_data_ptr(data);
7012047Schristian.menard@tu-dresden.de
7112047Schristian.menard@tu-dresden.de    if (packet->isRead()) {
7212047Schristian.menard@tu-dresden.de        trans.set_command(tlm::TLM_READ_COMMAND);
7312047Schristian.menard@tu-dresden.de    }
7412047Schristian.menard@tu-dresden.de    else if (packet->isInvalidate()) {
7512047Schristian.menard@tu-dresden.de        /* Do nothing */
7612047Schristian.menard@tu-dresden.de    } else if (packet->isWrite()) {
7712047Schristian.menard@tu-dresden.de        trans.set_command(tlm::TLM_WRITE_COMMAND);
7812047Schristian.menard@tu-dresden.de    } else {
7912047Schristian.menard@tu-dresden.de        SC_REPORT_FATAL("SCSlavePort", "No R/W packet");
8012047Schristian.menard@tu-dresden.de    }
8112047Schristian.menard@tu-dresden.de}
8212047Schristian.menard@tu-dresden.de
8312047Schristian.menard@tu-dresden.de/**
8412047Schristian.menard@tu-dresden.de * Similar to TLM's blocking transport (LT)
8512047Schristian.menard@tu-dresden.de */
8612047Schristian.menard@tu-dresden.deTick
8712047Schristian.menard@tu-dresden.deSCSlavePort::recvAtomic(PacketPtr packet)
8812047Schristian.menard@tu-dresden.de{
8912047Schristian.menard@tu-dresden.de    CAUGHT_UP;
9012047Schristian.menard@tu-dresden.de    SC_REPORT_INFO("SCSlavePort", "recvAtomic hasn't been tested much");
9112047Schristian.menard@tu-dresden.de
9212047Schristian.menard@tu-dresden.de    panic_if(packet->cacheResponding(), "Should not see packets where cache "
9312047Schristian.menard@tu-dresden.de             "is responding");
9412047Schristian.menard@tu-dresden.de
9512047Schristian.menard@tu-dresden.de    panic_if(!(packet->isRead() || packet->isWrite()),
9612047Schristian.menard@tu-dresden.de             "Should only see read and writes at TLM memory\n");
9712047Schristian.menard@tu-dresden.de
9812047Schristian.menard@tu-dresden.de
9912047Schristian.menard@tu-dresden.de    sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
10012047Schristian.menard@tu-dresden.de
10112047Schristian.menard@tu-dresden.de
10212047Schristian.menard@tu-dresden.de    /* Prepare the transaction */
10312047Schristian.menard@tu-dresden.de    tlm::tlm_generic_payload * trans = mm.allocate();
10412047Schristian.menard@tu-dresden.de    trans->acquire();
10512047Schristian.menard@tu-dresden.de    packet2payload(packet, *trans);
10612047Schristian.menard@tu-dresden.de
10712047Schristian.menard@tu-dresden.de    /* Attach the packet pointer to the TLM transaction to keep track */
10812047Schristian.menard@tu-dresden.de    Gem5Extension* extension = new Gem5Extension(packet);
10912047Schristian.menard@tu-dresden.de    trans->set_auto_extension(extension);
11012047Schristian.menard@tu-dresden.de
11112047Schristian.menard@tu-dresden.de    /* Execute b_transport: */
11212047Schristian.menard@tu-dresden.de    if (packet->cmd == MemCmd::SwapReq) {
11312047Schristian.menard@tu-dresden.de        SC_REPORT_FATAL("SCSlavePort", "SwapReq not supported");
11412047Schristian.menard@tu-dresden.de    } else if (packet->isRead()) {
11512047Schristian.menard@tu-dresden.de        transactor->socket->b_transport(*trans, delay);
11612047Schristian.menard@tu-dresden.de    } else if (packet->isInvalidate()) {
11712047Schristian.menard@tu-dresden.de        // do nothing
11812047Schristian.menard@tu-dresden.de    } else if (packet->isWrite()) {
11912047Schristian.menard@tu-dresden.de        transactor->socket->b_transport(*trans, delay);
12012047Schristian.menard@tu-dresden.de    } else {
12112047Schristian.menard@tu-dresden.de        SC_REPORT_FATAL("SCSlavePort", "Typo of request not supported");
12212047Schristian.menard@tu-dresden.de    }
12312047Schristian.menard@tu-dresden.de
12412047Schristian.menard@tu-dresden.de    if (packet->needsResponse()) {
12512047Schristian.menard@tu-dresden.de        packet->makeResponse();
12612047Schristian.menard@tu-dresden.de    }
12712047Schristian.menard@tu-dresden.de
12812047Schristian.menard@tu-dresden.de    trans->release();
12912047Schristian.menard@tu-dresden.de
13012047Schristian.menard@tu-dresden.de    return delay.value();
13112047Schristian.menard@tu-dresden.de}
13212047Schristian.menard@tu-dresden.de
13312047Schristian.menard@tu-dresden.de/**
13412047Schristian.menard@tu-dresden.de * Similar to TLM's debug transport
13512047Schristian.menard@tu-dresden.de */
13612047Schristian.menard@tu-dresden.devoid
13712047Schristian.menard@tu-dresden.deSCSlavePort::recvFunctional(PacketPtr packet)
13812047Schristian.menard@tu-dresden.de{
13912047Schristian.menard@tu-dresden.de    /* Prepare the transaction */
14012047Schristian.menard@tu-dresden.de    tlm::tlm_generic_payload * trans = mm.allocate();
14112047Schristian.menard@tu-dresden.de    trans->acquire();
14212047Schristian.menard@tu-dresden.de    packet2payload(packet, *trans);
14312047Schristian.menard@tu-dresden.de
14412047Schristian.menard@tu-dresden.de    /* Attach the packet pointer to the TLM transaction to keep track */
14512047Schristian.menard@tu-dresden.de    Gem5Extension* extension = new Gem5Extension(packet);
14612047Schristian.menard@tu-dresden.de    trans->set_auto_extension(extension);
14712047Schristian.menard@tu-dresden.de
14812047Schristian.menard@tu-dresden.de    /* Execute Debug Transport: */
14912047Schristian.menard@tu-dresden.de    unsigned int bytes = transactor->socket->transport_dbg(*trans);
15012047Schristian.menard@tu-dresden.de    if (bytes != trans->get_data_length()) {
15112047Schristian.menard@tu-dresden.de        SC_REPORT_FATAL("SCSlavePort","debug transport was not completed");
15212047Schristian.menard@tu-dresden.de    }
15312047Schristian.menard@tu-dresden.de
15412047Schristian.menard@tu-dresden.de    trans->release();
15512047Schristian.menard@tu-dresden.de}
15612047Schristian.menard@tu-dresden.de
15712047Schristian.menard@tu-dresden.debool
15812047Schristian.menard@tu-dresden.deSCSlavePort::recvTimingSnoopResp(PacketPtr packet)
15912047Schristian.menard@tu-dresden.de{
16012047Schristian.menard@tu-dresden.de    /* Snooping should be implemented with tlm_dbg_transport */
16112047Schristian.menard@tu-dresden.de    SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvTimingSnoopResp");
16212047Schristian.menard@tu-dresden.de    return false;
16312047Schristian.menard@tu-dresden.de}
16412047Schristian.menard@tu-dresden.de
16512047Schristian.menard@tu-dresden.devoid
16612047Schristian.menard@tu-dresden.deSCSlavePort::recvFunctionalSnoop(PacketPtr packet)
16712047Schristian.menard@tu-dresden.de{
16812047Schristian.menard@tu-dresden.de    /* Snooping should be implemented with tlm_dbg_transport */
16912047Schristian.menard@tu-dresden.de    SC_REPORT_FATAL("SCSlavePort","unimplemented func.: recvFunctionalSnoop");
17012047Schristian.menard@tu-dresden.de}
17112047Schristian.menard@tu-dresden.de
17212047Schristian.menard@tu-dresden.de/**
17312047Schristian.menard@tu-dresden.de *  Similar to TLM's non-blocking transport (AT)
17412047Schristian.menard@tu-dresden.de */
17512047Schristian.menard@tu-dresden.debool
17612047Schristian.menard@tu-dresden.deSCSlavePort::recvTimingReq(PacketPtr packet)
17712047Schristian.menard@tu-dresden.de{
17812047Schristian.menard@tu-dresden.de    CAUGHT_UP;
17912047Schristian.menard@tu-dresden.de
18012047Schristian.menard@tu-dresden.de    panic_if(packet->cacheResponding(), "Should not see packets where cache "
18112047Schristian.menard@tu-dresden.de             "is responding");
18212047Schristian.menard@tu-dresden.de
18312047Schristian.menard@tu-dresden.de    panic_if(!(packet->isRead() || packet->isWrite()),
18412047Schristian.menard@tu-dresden.de             "Should only see read and writes at TLM memory\n");
18512047Schristian.menard@tu-dresden.de
18612047Schristian.menard@tu-dresden.de
18712047Schristian.menard@tu-dresden.de    /* We should never get a second request after noting that a retry is
18812047Schristian.menard@tu-dresden.de     * required */
18912047Schristian.menard@tu-dresden.de    sc_assert(!needToSendRequestRetry);
19012047Schristian.menard@tu-dresden.de
19112047Schristian.menard@tu-dresden.de    /* Remember if a request comes in while we're blocked so that a retry
19212047Schristian.menard@tu-dresden.de     * can be sent to gem5 */
19312047Schristian.menard@tu-dresden.de    if (blockingRequest) {
19412047Schristian.menard@tu-dresden.de        needToSendRequestRetry = true;
19512047Schristian.menard@tu-dresden.de        return false;
19612047Schristian.menard@tu-dresden.de    }
19712047Schristian.menard@tu-dresden.de
19812047Schristian.menard@tu-dresden.de    /*  NOTE: normal tlm is blocking here. But in our case we return false
19912047Schristian.menard@tu-dresden.de     *  and tell gem5 when a retry can be done. This is the main difference
20012047Schristian.menard@tu-dresden.de     *  in the protocol:
20112047Schristian.menard@tu-dresden.de     *  if (requestInProgress)
20212047Schristian.menard@tu-dresden.de     *  {
20312047Schristian.menard@tu-dresden.de     *      wait(endRequestEvent);
20412047Schristian.menard@tu-dresden.de     *  }
20512047Schristian.menard@tu-dresden.de     *  requestInProgress = trans;
20612047Schristian.menard@tu-dresden.de    */
20712047Schristian.menard@tu-dresden.de
20812047Schristian.menard@tu-dresden.de    /* Prepare the transaction */
20912047Schristian.menard@tu-dresden.de    tlm::tlm_generic_payload * trans = mm.allocate();
21012047Schristian.menard@tu-dresden.de    trans->acquire();
21112047Schristian.menard@tu-dresden.de    packet2payload(packet, *trans);
21212047Schristian.menard@tu-dresden.de
21312047Schristian.menard@tu-dresden.de    /* Attach the packet pointer to the TLM transaction to keep track */
21412047Schristian.menard@tu-dresden.de    Gem5Extension* extension = new Gem5Extension(packet);
21512047Schristian.menard@tu-dresden.de    trans->set_auto_extension(extension);
21612047Schristian.menard@tu-dresden.de
21712047Schristian.menard@tu-dresden.de    /*
21812047Schristian.menard@tu-dresden.de     * Pay for annotated transport delays.
21912047Schristian.menard@tu-dresden.de     *
22012047Schristian.menard@tu-dresden.de     * The header delay marks the point in time, when the packet first is seen
22112047Schristian.menard@tu-dresden.de     * by the transactor. This is the point int time, when the transactor needs
22212047Schristian.menard@tu-dresden.de     * to send the BEGIN_REQ to the SystemC world.
22312047Schristian.menard@tu-dresden.de     *
22412047Schristian.menard@tu-dresden.de     * NOTE: We drop the payload delay here. Normally, the receiver would be
22512047Schristian.menard@tu-dresden.de     *       responsible for handling the payload delay. In this case, however,
22612047Schristian.menard@tu-dresden.de     *       the receiver is a SystemC module and has no notion of the gem5
22712047Schristian.menard@tu-dresden.de     *       transport protocol and we cannot simply forward the
22812047Schristian.menard@tu-dresden.de     *       payload delay to the receiving module. Instead, we expect the
22912047Schristian.menard@tu-dresden.de     *       receiving SystemC module to model the payload delay by deferring
23012047Schristian.menard@tu-dresden.de     *       the END_REQ. This could lead to incorrect delays, if the XBar
23112047Schristian.menard@tu-dresden.de     *       payload delay is longer than the time the receiver needs to accept
23212047Schristian.menard@tu-dresden.de     *       the request (time between BEGIN_REQ and END_REQ).
23312047Schristian.menard@tu-dresden.de     *
23412047Schristian.menard@tu-dresden.de     * TODO: We could detect the case described above by remembering the
23512047Schristian.menard@tu-dresden.de     *       payload delay and comparing it to the time between BEGIN_REQ and
23612047Schristian.menard@tu-dresden.de     *       END_REQ. Then, a warning should be printed.
23712047Schristian.menard@tu-dresden.de     */
23812047Schristian.menard@tu-dresden.de    auto delay = sc_core::sc_time::from_value(packet->payloadDelay);
23912047Schristian.menard@tu-dresden.de    // reset the delays
24012047Schristian.menard@tu-dresden.de    packet->payloadDelay = 0;
24112047Schristian.menard@tu-dresden.de    packet->headerDelay = 0;
24212047Schristian.menard@tu-dresden.de
24312047Schristian.menard@tu-dresden.de    /* Starting TLM non-blocking sequence (AT) Refer to IEEE1666-2011 SystemC
24412047Schristian.menard@tu-dresden.de     * Standard Page 507 for a visualisation of the procedure */
24512047Schristian.menard@tu-dresden.de    tlm::tlm_phase phase = tlm::BEGIN_REQ;
24612047Schristian.menard@tu-dresden.de    tlm::tlm_sync_enum status;
24712047Schristian.menard@tu-dresden.de    status = transactor->socket->nb_transport_fw(*trans, phase, delay);
24812047Schristian.menard@tu-dresden.de    /* Check returned value: */
24912047Schristian.menard@tu-dresden.de    if (status == tlm::TLM_ACCEPTED) {
25012047Schristian.menard@tu-dresden.de        sc_assert(phase == tlm::BEGIN_REQ);
25112047Schristian.menard@tu-dresden.de        /* Accepted but is now blocking until END_REQ (exclusion rule)*/
25212047Schristian.menard@tu-dresden.de        blockingRequest = trans;
25312047Schristian.menard@tu-dresden.de    } else if (status == tlm::TLM_UPDATED) {
25412047Schristian.menard@tu-dresden.de        /* The Timing annotation must be honored: */
25512047Schristian.menard@tu-dresden.de        sc_assert(phase == tlm::END_REQ || phase == tlm::BEGIN_RESP);
25612047Schristian.menard@tu-dresden.de
25712047Schristian.menard@tu-dresden.de        PayloadEvent<SCSlavePort> * pe;
25812047Schristian.menard@tu-dresden.de        pe = new PayloadEvent<SCSlavePort>(*this,
25912047Schristian.menard@tu-dresden.de            &SCSlavePort::pec, "PEQ");
26012047Schristian.menard@tu-dresden.de        pe->notify(*trans, phase, delay);
26112047Schristian.menard@tu-dresden.de    } else if (status == tlm::TLM_COMPLETED) {
26212047Schristian.menard@tu-dresden.de        /* Transaction is over nothing has do be done. */
26312047Schristian.menard@tu-dresden.de        sc_assert(phase == tlm::END_RESP);
26412047Schristian.menard@tu-dresden.de        trans->release();
26512047Schristian.menard@tu-dresden.de    }
26612047Schristian.menard@tu-dresden.de
26712047Schristian.menard@tu-dresden.de    return true;
26812047Schristian.menard@tu-dresden.de}
26912047Schristian.menard@tu-dresden.de
27012047Schristian.menard@tu-dresden.devoid
27112047Schristian.menard@tu-dresden.deSCSlavePort::pec(
27212047Schristian.menard@tu-dresden.de    PayloadEvent<SCSlavePort> * pe,
27312047Schristian.menard@tu-dresden.de    tlm::tlm_generic_payload& trans,
27412047Schristian.menard@tu-dresden.de    const tlm::tlm_phase& phase)
27512047Schristian.menard@tu-dresden.de{
27612047Schristian.menard@tu-dresden.de    sc_time delay;
27712047Schristian.menard@tu-dresden.de
27812047Schristian.menard@tu-dresden.de    if (phase == tlm::END_REQ ||
27912047Schristian.menard@tu-dresden.de            &trans == blockingRequest && phase == tlm::BEGIN_RESP) {
28012047Schristian.menard@tu-dresden.de        sc_assert(&trans == blockingRequest);
28112047Schristian.menard@tu-dresden.de        blockingRequest = NULL;
28212047Schristian.menard@tu-dresden.de
28312047Schristian.menard@tu-dresden.de        /* Did another request arrive while blocked, schedule a retry */
28412047Schristian.menard@tu-dresden.de        if (needToSendRequestRetry) {
28512047Schristian.menard@tu-dresden.de            needToSendRequestRetry = false;
28612047Schristian.menard@tu-dresden.de            sendRetryReq();
28712047Schristian.menard@tu-dresden.de        }
28812047Schristian.menard@tu-dresden.de    }
28912047Schristian.menard@tu-dresden.de    if (phase == tlm::BEGIN_RESP)
29012047Schristian.menard@tu-dresden.de    {
29112047Schristian.menard@tu-dresden.de        CAUGHT_UP;
29212047Schristian.menard@tu-dresden.de
29312047Schristian.menard@tu-dresden.de        auto& extension = Gem5Extension::getExtension(trans);
29412047Schristian.menard@tu-dresden.de        auto packet = extension.getPacket();
29512047Schristian.menard@tu-dresden.de
29612047Schristian.menard@tu-dresden.de        sc_assert(!blockingResponse);
29712047Schristian.menard@tu-dresden.de
29812047Schristian.menard@tu-dresden.de        bool need_retry = false;
29912047Schristian.menard@tu-dresden.de
30012047Schristian.menard@tu-dresden.de        /*
30112047Schristian.menard@tu-dresden.de         * If the packet was piped through and needs a response, we don't need
30212047Schristian.menard@tu-dresden.de         * to touch the packet and can forward it directly as a response.
30312047Schristian.menard@tu-dresden.de         * Otherwise, we need to make a response and send the transformed
30412047Schristian.menard@tu-dresden.de         * packet.
30512047Schristian.menard@tu-dresden.de         */
30612047Schristian.menard@tu-dresden.de        if (extension.isPipeThrough()) {
30712047Schristian.menard@tu-dresden.de            if (packet->isResponse()) {
30812047Schristian.menard@tu-dresden.de                need_retry = !sendTimingResp(packet);
30912047Schristian.menard@tu-dresden.de            }
31012047Schristian.menard@tu-dresden.de        } else if (packet->needsResponse()) {
31112047Schristian.menard@tu-dresden.de            packet->makeResponse();
31212047Schristian.menard@tu-dresden.de            need_retry = !sendTimingResp(packet);
31312047Schristian.menard@tu-dresden.de        }
31412047Schristian.menard@tu-dresden.de
31512047Schristian.menard@tu-dresden.de        if (need_retry) {
31612047Schristian.menard@tu-dresden.de            blockingResponse = &trans;
31712047Schristian.menard@tu-dresden.de        } else {
31812047Schristian.menard@tu-dresden.de            if (phase == tlm::BEGIN_RESP) {
31912047Schristian.menard@tu-dresden.de                /* Send END_RESP and we're finished: */
32012047Schristian.menard@tu-dresden.de                tlm::tlm_phase fw_phase = tlm::END_RESP;
32112047Schristian.menard@tu-dresden.de                sc_time delay = SC_ZERO_TIME;
32212047Schristian.menard@tu-dresden.de                transactor->socket->nb_transport_fw(trans, fw_phase, delay);
32312047Schristian.menard@tu-dresden.de                /* Release the transaction with all the extensions */
32412047Schristian.menard@tu-dresden.de                trans.release();
32512047Schristian.menard@tu-dresden.de            }
32612047Schristian.menard@tu-dresden.de        }
32712047Schristian.menard@tu-dresden.de    }
32812047Schristian.menard@tu-dresden.de    delete pe;
32912047Schristian.menard@tu-dresden.de}
33012047Schristian.menard@tu-dresden.de
33112047Schristian.menard@tu-dresden.devoid
33212047Schristian.menard@tu-dresden.deSCSlavePort::recvRespRetry()
33312047Schristian.menard@tu-dresden.de{
33412047Schristian.menard@tu-dresden.de    CAUGHT_UP;
33512047Schristian.menard@tu-dresden.de
33612047Schristian.menard@tu-dresden.de    /* Retry a response */
33712047Schristian.menard@tu-dresden.de    sc_assert(blockingResponse);
33812047Schristian.menard@tu-dresden.de
33912047Schristian.menard@tu-dresden.de    tlm::tlm_generic_payload *trans = blockingResponse;
34012047Schristian.menard@tu-dresden.de    blockingResponse = NULL;
34112047Schristian.menard@tu-dresden.de    PacketPtr packet = Gem5Extension::getExtension(trans).getPacket();
34212047Schristian.menard@tu-dresden.de
34312047Schristian.menard@tu-dresden.de    bool need_retry = !sendTimingResp(packet);
34412047Schristian.menard@tu-dresden.de
34512047Schristian.menard@tu-dresden.de    sc_assert(!need_retry);
34612047Schristian.menard@tu-dresden.de
34712047Schristian.menard@tu-dresden.de    sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
34812047Schristian.menard@tu-dresden.de    tlm::tlm_phase phase = tlm::END_RESP;
34912047Schristian.menard@tu-dresden.de    transactor->socket->nb_transport_fw(*trans, phase, delay);
35012047Schristian.menard@tu-dresden.de    // Release transaction with all the extensions
35112047Schristian.menard@tu-dresden.de    trans->release();
35212047Schristian.menard@tu-dresden.de}
35312047Schristian.menard@tu-dresden.de
35412047Schristian.menard@tu-dresden.detlm::tlm_sync_enum
35512047Schristian.menard@tu-dresden.deSCSlavePort::nb_transport_bw(tlm::tlm_generic_payload& trans,
35612047Schristian.menard@tu-dresden.de    tlm::tlm_phase& phase,
35712047Schristian.menard@tu-dresden.de    sc_core::sc_time& delay)
35812047Schristian.menard@tu-dresden.de{
35912047Schristian.menard@tu-dresden.de    PayloadEvent<SCSlavePort> * pe;
36012047Schristian.menard@tu-dresden.de    pe = new PayloadEvent<SCSlavePort>(*this, &SCSlavePort::pec, "PE");
36112047Schristian.menard@tu-dresden.de    pe->notify(trans, phase, delay);
36212047Schristian.menard@tu-dresden.de    return tlm::TLM_ACCEPTED;
36312047Schristian.menard@tu-dresden.de}
36412047Schristian.menard@tu-dresden.de
36512047Schristian.menard@tu-dresden.deSCSlavePort::SCSlavePort(const std::string &name_,
36612047Schristian.menard@tu-dresden.de    const std::string &systemc_name,
36712047Schristian.menard@tu-dresden.de    ExternalSlave &owner_) :
36812047Schristian.menard@tu-dresden.de    ExternalSlave::Port(name_, owner_),
36912047Schristian.menard@tu-dresden.de    blockingRequest(NULL),
37012047Schristian.menard@tu-dresden.de    needToSendRequestRetry(false),
37112047Schristian.menard@tu-dresden.de    blockingResponse(NULL),
37212047Schristian.menard@tu-dresden.de    transactor(nullptr)
37312047Schristian.menard@tu-dresden.de{
37412047Schristian.menard@tu-dresden.de}
37512047Schristian.menard@tu-dresden.de
37612047Schristian.menard@tu-dresden.devoid
37712047Schristian.menard@tu-dresden.deSCSlavePort::bindToTransactor(Gem5SlaveTransactor* transactor)
37812047Schristian.menard@tu-dresden.de{
37912047Schristian.menard@tu-dresden.de    sc_assert(this->transactor == nullptr);
38012047Schristian.menard@tu-dresden.de
38112047Schristian.menard@tu-dresden.de    this->transactor = transactor;
38212047Schristian.menard@tu-dresden.de
38312047Schristian.menard@tu-dresden.de    transactor->socket.register_nb_transport_bw(this,
38412047Schristian.menard@tu-dresden.de                                                &SCSlavePort::nb_transport_bw);
38512047Schristian.menard@tu-dresden.de}
38612047Schristian.menard@tu-dresden.de
38712047Schristian.menard@tu-dresden.deExternalSlave::Port*
38812047Schristian.menard@tu-dresden.deSCSlavePortHandler::getExternalPort(const std::string &name,
38912047Schristian.menard@tu-dresden.de                                    ExternalSlave &owner,
39012047Schristian.menard@tu-dresden.de                                    const std::string &port_data)
39112047Schristian.menard@tu-dresden.de{
39212047Schristian.menard@tu-dresden.de    // Create and register a new SystemC slave port
39312047Schristian.menard@tu-dresden.de    auto* port = new SCSlavePort(name, port_data, owner);
39412047Schristian.menard@tu-dresden.de
39512047Schristian.menard@tu-dresden.de    control.registerSlavePort(port_data, port);
39612047Schristian.menard@tu-dresden.de
39712047Schristian.menard@tu-dresden.de    return port;
39812047Schristian.menard@tu-dresden.de}
39912047Schristian.menard@tu-dresden.de
40012047Schristian.menard@tu-dresden.de}
401