simple_memobj.cc revision 12338
112338Sjason@lowepower.com/*
212338Sjason@lowepower.com * Copyright (c) 2017 Jason Lowe-Power
312338Sjason@lowepower.com * All rights reserved.
412338Sjason@lowepower.com *
512338Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without
612338Sjason@lowepower.com * modification, are permitted provided that the following conditions are
712338Sjason@lowepower.com * met: redistributions of source code must retain the above copyright
812338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer;
912338Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright
1012338Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the
1112338Sjason@lowepower.com * documentation and/or other materials provided with the distribution;
1212338Sjason@lowepower.com * neither the name of the copyright holders nor the names of its
1312338Sjason@lowepower.com * contributors may be used to endorse or promote products derived from
1412338Sjason@lowepower.com * this software without specific prior written permission.
1512338Sjason@lowepower.com *
1612338Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712338Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812338Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912338Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012338Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112338Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212338Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312338Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412338Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512338Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612338Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712338Sjason@lowepower.com *
2812338Sjason@lowepower.com * Authors: Jason Lowe-Power
2912338Sjason@lowepower.com */
3012338Sjason@lowepower.com
3112338Sjason@lowepower.com#include "learning_gem5/part2/simple_memobj.hh"
3212338Sjason@lowepower.com
3312338Sjason@lowepower.com#include "debug/SimpleMemobj.hh"
3412338Sjason@lowepower.com
3512338Sjason@lowepower.comSimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
3612338Sjason@lowepower.com    MemObject(params),
3712338Sjason@lowepower.com    instPort(params->name + ".inst_port", this),
3812338Sjason@lowepower.com    dataPort(params->name + ".data_port", this),
3912338Sjason@lowepower.com    memPort(params->name + ".mem_side", this),
4012338Sjason@lowepower.com    blocked(false)
4112338Sjason@lowepower.com{
4212338Sjason@lowepower.com}
4312338Sjason@lowepower.com
4412338Sjason@lowepower.comBaseMasterPort&
4512338Sjason@lowepower.comSimpleMemobj::getMasterPort(const std::string& if_name, PortID idx)
4612338Sjason@lowepower.com{
4712338Sjason@lowepower.com    panic_if(idx != InvalidPortID, "This object doesn't support vector ports");
4812338Sjason@lowepower.com
4912338Sjason@lowepower.com    // This is the name from the Python SimObject declaration (SimpleMemobj.py)
5012338Sjason@lowepower.com    if (if_name == "mem_side") {
5112338Sjason@lowepower.com        return memPort;
5212338Sjason@lowepower.com    } else {
5312338Sjason@lowepower.com        // pass it along to our super class
5412338Sjason@lowepower.com        return MemObject::getMasterPort(if_name, idx);
5512338Sjason@lowepower.com    }
5612338Sjason@lowepower.com}
5712338Sjason@lowepower.com
5812338Sjason@lowepower.comBaseSlavePort&
5912338Sjason@lowepower.comSimpleMemobj::getSlavePort(const std::string& if_name, PortID idx)
6012338Sjason@lowepower.com{
6112338Sjason@lowepower.com    panic_if(idx != InvalidPortID, "This object doesn't support vector ports");
6212338Sjason@lowepower.com
6312338Sjason@lowepower.com    // This is the name from the Python SimObject declaration in SimpleCache.py
6412338Sjason@lowepower.com    if (if_name == "inst_port") {
6512338Sjason@lowepower.com        return instPort;
6612338Sjason@lowepower.com    } else if (if_name == "data_port") {
6712338Sjason@lowepower.com        return dataPort;
6812338Sjason@lowepower.com    } else {
6912338Sjason@lowepower.com        // pass it along to our super class
7012338Sjason@lowepower.com        return MemObject::getSlavePort(if_name, idx);
7112338Sjason@lowepower.com    }
7212338Sjason@lowepower.com}
7312338Sjason@lowepower.com
7412338Sjason@lowepower.comvoid
7512338Sjason@lowepower.comSimpleMemobj::CPUSidePort::sendPacket(PacketPtr pkt)
7612338Sjason@lowepower.com{
7712338Sjason@lowepower.com    // Note: This flow control is very simple since the memobj is blocking.
7812338Sjason@lowepower.com
7912338Sjason@lowepower.com    panic_if(blockedPacket != nullptr, "Should never try to send if blocked!");
8012338Sjason@lowepower.com
8112338Sjason@lowepower.com    // If we can't send the packet across the port, store it for later.
8212338Sjason@lowepower.com    if (!sendTimingResp(pkt)) {
8312338Sjason@lowepower.com        blockedPacket = pkt;
8412338Sjason@lowepower.com    }
8512338Sjason@lowepower.com}
8612338Sjason@lowepower.com
8712338Sjason@lowepower.comAddrRangeList
8812338Sjason@lowepower.comSimpleMemobj::CPUSidePort::getAddrRanges() const
8912338Sjason@lowepower.com{
9012338Sjason@lowepower.com    return owner->getAddrRanges();
9112338Sjason@lowepower.com}
9212338Sjason@lowepower.com
9312338Sjason@lowepower.comvoid
9412338Sjason@lowepower.comSimpleMemobj::CPUSidePort::trySendRetry()
9512338Sjason@lowepower.com{
9612338Sjason@lowepower.com    if (needRetry && blockedPacket == nullptr) {
9712338Sjason@lowepower.com        // Only send a retry if the port is now completely free
9812338Sjason@lowepower.com        needRetry = false;
9912338Sjason@lowepower.com        DPRINTF(SimpleMemobj, "Sending retry req for %d\n", id);
10012338Sjason@lowepower.com        sendRetryReq();
10112338Sjason@lowepower.com    }
10212338Sjason@lowepower.com}
10312338Sjason@lowepower.com
10412338Sjason@lowepower.comvoid
10512338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvFunctional(PacketPtr pkt)
10612338Sjason@lowepower.com{
10712338Sjason@lowepower.com    // Just forward to the memobj.
10812338Sjason@lowepower.com    return owner->handleFunctional(pkt);
10912338Sjason@lowepower.com}
11012338Sjason@lowepower.com
11112338Sjason@lowepower.combool
11212338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvTimingReq(PacketPtr pkt)
11312338Sjason@lowepower.com{
11412338Sjason@lowepower.com    // Just forward to the memobj.
11512338Sjason@lowepower.com    if (!owner->handleRequest(pkt)) {
11612338Sjason@lowepower.com        needRetry = true;
11712338Sjason@lowepower.com        return false;
11812338Sjason@lowepower.com    } else {
11912338Sjason@lowepower.com        return true;
12012338Sjason@lowepower.com    }
12112338Sjason@lowepower.com}
12212338Sjason@lowepower.com
12312338Sjason@lowepower.comvoid
12412338Sjason@lowepower.comSimpleMemobj::CPUSidePort::recvRespRetry()
12512338Sjason@lowepower.com{
12612338Sjason@lowepower.com    // We should have a blocked packet if this function is called.
12712338Sjason@lowepower.com    assert(blockedPacket != nullptr);
12812338Sjason@lowepower.com
12912338Sjason@lowepower.com    // Grab the blocked packet.
13012338Sjason@lowepower.com    PacketPtr pkt = blockedPacket;
13112338Sjason@lowepower.com    blockedPacket = nullptr;
13212338Sjason@lowepower.com
13312338Sjason@lowepower.com    // Try to resend it. It's possible that it fails again.
13412338Sjason@lowepower.com    sendPacket(pkt);
13512338Sjason@lowepower.com}
13612338Sjason@lowepower.com
13712338Sjason@lowepower.comvoid
13812338Sjason@lowepower.comSimpleMemobj::MemSidePort::sendPacket(PacketPtr pkt)
13912338Sjason@lowepower.com{
14012338Sjason@lowepower.com    // Note: This flow control is very simple since the memobj is blocking.
14112338Sjason@lowepower.com
14212338Sjason@lowepower.com    panic_if(blockedPacket != nullptr, "Should never try to send if blocked!");
14312338Sjason@lowepower.com
14412338Sjason@lowepower.com    // If we can't send the packet across the port, store it for later.
14512338Sjason@lowepower.com    if (!sendTimingReq(pkt)) {
14612338Sjason@lowepower.com        blockedPacket = pkt;
14712338Sjason@lowepower.com    }
14812338Sjason@lowepower.com}
14912338Sjason@lowepower.com
15012338Sjason@lowepower.combool
15112338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvTimingResp(PacketPtr pkt)
15212338Sjason@lowepower.com{
15312338Sjason@lowepower.com    // Just forward to the memobj.
15412338Sjason@lowepower.com    return owner->handleResponse(pkt);
15512338Sjason@lowepower.com}
15612338Sjason@lowepower.com
15712338Sjason@lowepower.comvoid
15812338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvReqRetry()
15912338Sjason@lowepower.com{
16012338Sjason@lowepower.com    // We should have a blocked packet if this function is called.
16112338Sjason@lowepower.com    assert(blockedPacket != nullptr);
16212338Sjason@lowepower.com
16312338Sjason@lowepower.com    // Grab the blocked packet.
16412338Sjason@lowepower.com    PacketPtr pkt = blockedPacket;
16512338Sjason@lowepower.com    blockedPacket = nullptr;
16612338Sjason@lowepower.com
16712338Sjason@lowepower.com    // Try to resend it. It's possible that it fails again.
16812338Sjason@lowepower.com    sendPacket(pkt);
16912338Sjason@lowepower.com}
17012338Sjason@lowepower.com
17112338Sjason@lowepower.comvoid
17212338Sjason@lowepower.comSimpleMemobj::MemSidePort::recvRangeChange()
17312338Sjason@lowepower.com{
17412338Sjason@lowepower.com    owner->sendRangeChange();
17512338Sjason@lowepower.com}
17612338Sjason@lowepower.com
17712338Sjason@lowepower.combool
17812338Sjason@lowepower.comSimpleMemobj::handleRequest(PacketPtr pkt)
17912338Sjason@lowepower.com{
18012338Sjason@lowepower.com    if (blocked) {
18112338Sjason@lowepower.com        // There is currently an outstanding request. Stall.
18212338Sjason@lowepower.com        return false;
18312338Sjason@lowepower.com    }
18412338Sjason@lowepower.com
18512338Sjason@lowepower.com    DPRINTF(SimpleMemobj, "Got request for addr %#x\n", pkt->getAddr());
18612338Sjason@lowepower.com
18712338Sjason@lowepower.com    // This memobj is now blocked waiting for the response to this packet.
18812338Sjason@lowepower.com    blocked = true;
18912338Sjason@lowepower.com
19012338Sjason@lowepower.com    // Simply forward to the memory port
19112338Sjason@lowepower.com    memPort.sendPacket(pkt);
19212338Sjason@lowepower.com
19312338Sjason@lowepower.com    return true;
19412338Sjason@lowepower.com}
19512338Sjason@lowepower.com
19612338Sjason@lowepower.combool
19712338Sjason@lowepower.comSimpleMemobj::handleResponse(PacketPtr pkt)
19812338Sjason@lowepower.com{
19912338Sjason@lowepower.com    assert(blocked);
20012338Sjason@lowepower.com    DPRINTF(SimpleMemobj, "Got response for addr %#x\n", pkt->getAddr());
20112338Sjason@lowepower.com
20212338Sjason@lowepower.com    // The packet is now done. We're about to put it in the port, no need for
20312338Sjason@lowepower.com    // this object to continue to stall.
20412338Sjason@lowepower.com    // We need to free the resource before sending the packet in case the CPU
20512338Sjason@lowepower.com    // tries to send another request immediately (e.g., in the same callchain).
20612338Sjason@lowepower.com    blocked = false;
20712338Sjason@lowepower.com
20812338Sjason@lowepower.com    // Simply forward to the memory port
20912338Sjason@lowepower.com    if (pkt->req->isInstFetch()) {
21012338Sjason@lowepower.com        instPort.sendPacket(pkt);
21112338Sjason@lowepower.com    } else {
21212338Sjason@lowepower.com        dataPort.sendPacket(pkt);
21312338Sjason@lowepower.com    }
21412338Sjason@lowepower.com
21512338Sjason@lowepower.com    // For each of the cpu ports, if it needs to send a retry, it should do it
21612338Sjason@lowepower.com    // now since this memory object may be unblocked now.
21712338Sjason@lowepower.com    instPort.trySendRetry();
21812338Sjason@lowepower.com    dataPort.trySendRetry();
21912338Sjason@lowepower.com
22012338Sjason@lowepower.com    return true;
22112338Sjason@lowepower.com}
22212338Sjason@lowepower.com
22312338Sjason@lowepower.comvoid
22412338Sjason@lowepower.comSimpleMemobj::handleFunctional(PacketPtr pkt)
22512338Sjason@lowepower.com{
22612338Sjason@lowepower.com    // Just pass this on to the memory side to handle for now.
22712338Sjason@lowepower.com    memPort.sendFunctional(pkt);
22812338Sjason@lowepower.com}
22912338Sjason@lowepower.com
23012338Sjason@lowepower.comAddrRangeList
23112338Sjason@lowepower.comSimpleMemobj::getAddrRanges() const
23212338Sjason@lowepower.com{
23312338Sjason@lowepower.com    DPRINTF(SimpleMemobj, "Sending new ranges\n");
23412338Sjason@lowepower.com    // Just use the same ranges as whatever is on the memory side.
23512338Sjason@lowepower.com    return memPort.getAddrRanges();
23612338Sjason@lowepower.com}
23712338Sjason@lowepower.com
23812338Sjason@lowepower.comvoid
23912338Sjason@lowepower.comSimpleMemobj::sendRangeChange()
24012338Sjason@lowepower.com{
24112338Sjason@lowepower.com    instPort.sendRangeChange();
24212338Sjason@lowepower.com    dataPort.sendRangeChange();
24312338Sjason@lowepower.com}
24412338Sjason@lowepower.com
24512338Sjason@lowepower.com
24612338Sjason@lowepower.com
24712338Sjason@lowepower.comSimpleMemobj*
24812338Sjason@lowepower.comSimpleMemobjParams::create()
24912338Sjason@lowepower.com{
25012338Sjason@lowepower.com    return new SimpleMemobj(this);
25112338Sjason@lowepower.com}
252