110066Sandreas.hansson@arm.com/*
210066Sandreas.hansson@arm.com * Copyright (c) 2013 ARM Limited
310066Sandreas.hansson@arm.com * All rights reserved
410066Sandreas.hansson@arm.com *
510066Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
610066Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
710066Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
810066Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
910066Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1010066Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1110066Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1210066Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1310066Sandreas.hansson@arm.com *
1410066Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
1510066Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
1610066Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
1710066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
1810066Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1910066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
2010066Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
2110066Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
2210066Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
2310066Sandreas.hansson@arm.com * this software without specific prior written permission.
2410066Sandreas.hansson@arm.com *
2510066Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610066Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710066Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810066Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910066Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010066Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110066Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210066Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310066Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410066Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510066Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610066Sandreas.hansson@arm.com *
3710066Sandreas.hansson@arm.com * Authors: Andreas Hansson
3810066Sandreas.hansson@arm.com */
3910066Sandreas.hansson@arm.com
4011793Sbrandon.potter@amd.com#include "mem/dramsim2.hh"
4111793Sbrandon.potter@amd.com
4210066Sandreas.hansson@arm.com#include "DRAMSim2/Callback.h"
4310066Sandreas.hansson@arm.com#include "base/callback.hh"
4410066Sandreas.hansson@arm.com#include "base/trace.hh"
4510066Sandreas.hansson@arm.com#include "debug/DRAMSim2.hh"
4610066Sandreas.hansson@arm.com#include "debug/Drain.hh"
4710066Sandreas.hansson@arm.com#include "sim/system.hh"
4810066Sandreas.hansson@arm.com
4910066Sandreas.hansson@arm.comDRAMSim2::DRAMSim2(const Params* p) :
5010066Sandreas.hansson@arm.com    AbstractMemory(p),
5110066Sandreas.hansson@arm.com    port(name() + ".port", *this),
5210066Sandreas.hansson@arm.com    wrapper(p->deviceConfigFile, p->systemConfigFile, p->filePath,
5310066Sandreas.hansson@arm.com            p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug),
5410296Sandreas.hansson@arm.com    retryReq(false), retryResp(false), startTick(0),
5510066Sandreas.hansson@arm.com    nbrOutstandingReads(0), nbrOutstandingWrites(0),
5612084Sspwilson2@wisc.edu    sendResponseEvent([this]{ sendResponse(); }, name()),
5712084Sspwilson2@wisc.edu    tickEvent([this]{ tick(); }, name())
5810066Sandreas.hansson@arm.com{
5910066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2,
6010066Sandreas.hansson@arm.com            "Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
6110066Sandreas.hansson@arm.com            wrapper.clockPeriod(), wrapper.queueSize());
6210066Sandreas.hansson@arm.com
6310066Sandreas.hansson@arm.com    DRAMSim::TransactionCompleteCB* read_cb =
6410066Sandreas.hansson@arm.com        new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
6510066Sandreas.hansson@arm.com            this, &DRAMSim2::readComplete);
6610066Sandreas.hansson@arm.com    DRAMSim::TransactionCompleteCB* write_cb =
6710066Sandreas.hansson@arm.com        new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
6810066Sandreas.hansson@arm.com            this, &DRAMSim2::writeComplete);
6910066Sandreas.hansson@arm.com    wrapper.setCallbacks(read_cb, write_cb);
7010066Sandreas.hansson@arm.com
7110066Sandreas.hansson@arm.com    // Register a callback to compensate for the destructor not
7210066Sandreas.hansson@arm.com    // being called. The callback prints the DRAMSim2 stats.
7310066Sandreas.hansson@arm.com    Callback* cb = new MakeCallback<DRAMSim2Wrapper,
7410066Sandreas.hansson@arm.com        &DRAMSim2Wrapper::printStats>(wrapper);
7510066Sandreas.hansson@arm.com    registerExitCallback(cb);
7610066Sandreas.hansson@arm.com}
7710066Sandreas.hansson@arm.com
7810066Sandreas.hansson@arm.comvoid
7910066Sandreas.hansson@arm.comDRAMSim2::init()
8010066Sandreas.hansson@arm.com{
8110466Sandreas.hansson@arm.com    AbstractMemory::init();
8210466Sandreas.hansson@arm.com
8310066Sandreas.hansson@arm.com    if (!port.isConnected()) {
8410066Sandreas.hansson@arm.com        fatal("DRAMSim2 %s is unconnected!\n", name());
8510066Sandreas.hansson@arm.com    } else {
8610066Sandreas.hansson@arm.com        port.sendRangeChange();
8710066Sandreas.hansson@arm.com    }
8810066Sandreas.hansson@arm.com
8910066Sandreas.hansson@arm.com    if (system()->cacheLineSize() != wrapper.burstSize())
9010066Sandreas.hansson@arm.com        fatal("DRAMSim2 burst size %d does not match cache line size %d\n",
9110066Sandreas.hansson@arm.com              wrapper.burstSize(), system()->cacheLineSize());
9210066Sandreas.hansson@arm.com}
9310066Sandreas.hansson@arm.com
9410066Sandreas.hansson@arm.comvoid
9510066Sandreas.hansson@arm.comDRAMSim2::startup()
9610066Sandreas.hansson@arm.com{
9710296Sandreas.hansson@arm.com    startTick = curTick();
9810296Sandreas.hansson@arm.com
9910066Sandreas.hansson@arm.com    // kick off the clock ticks
10010066Sandreas.hansson@arm.com    schedule(tickEvent, clockEdge());
10110066Sandreas.hansson@arm.com}
10210066Sandreas.hansson@arm.com
10310066Sandreas.hansson@arm.comvoid
10410066Sandreas.hansson@arm.comDRAMSim2::sendResponse()
10510066Sandreas.hansson@arm.com{
10610066Sandreas.hansson@arm.com    assert(!retryResp);
10710066Sandreas.hansson@arm.com    assert(!responseQueue.empty());
10810066Sandreas.hansson@arm.com
10910066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2, "Attempting to send response\n");
11010066Sandreas.hansson@arm.com
11110066Sandreas.hansson@arm.com    bool success = port.sendTimingResp(responseQueue.front());
11210066Sandreas.hansson@arm.com    if (success) {
11310066Sandreas.hansson@arm.com        responseQueue.pop_front();
11410066Sandreas.hansson@arm.com
11510066Sandreas.hansson@arm.com        DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n",
11610066Sandreas.hansson@arm.com                nbrOutstandingReads, nbrOutstandingWrites,
11710066Sandreas.hansson@arm.com                responseQueue.size());
11810066Sandreas.hansson@arm.com
11910066Sandreas.hansson@arm.com        if (!responseQueue.empty() && !sendResponseEvent.scheduled())
12010066Sandreas.hansson@arm.com            schedule(sendResponseEvent, curTick());
12110066Sandreas.hansson@arm.com
12210913Sandreas.sandberg@arm.com        if (nbrOutstanding() == 0)
12310913Sandreas.sandberg@arm.com            signalDrainDone();
12410066Sandreas.hansson@arm.com    } else {
12510066Sandreas.hansson@arm.com        retryResp = true;
12610066Sandreas.hansson@arm.com
12710066Sandreas.hansson@arm.com        DPRINTF(DRAMSim2, "Waiting for response retry\n");
12810066Sandreas.hansson@arm.com
12910066Sandreas.hansson@arm.com        assert(!sendResponseEvent.scheduled());
13010066Sandreas.hansson@arm.com    }
13110066Sandreas.hansson@arm.com}
13210066Sandreas.hansson@arm.com
13310066Sandreas.hansson@arm.comunsigned int
13410066Sandreas.hansson@arm.comDRAMSim2::nbrOutstanding() const
13510066Sandreas.hansson@arm.com{
13610066Sandreas.hansson@arm.com    return nbrOutstandingReads + nbrOutstandingWrites + responseQueue.size();
13710066Sandreas.hansson@arm.com}
13810066Sandreas.hansson@arm.com
13910066Sandreas.hansson@arm.comvoid
14010066Sandreas.hansson@arm.comDRAMSim2::tick()
14110066Sandreas.hansson@arm.com{
14210066Sandreas.hansson@arm.com    wrapper.tick();
14310066Sandreas.hansson@arm.com
14410066Sandreas.hansson@arm.com    // is the connected port waiting for a retry, if so check the
14510066Sandreas.hansson@arm.com    // state and send a retry if conditions have changed
14610066Sandreas.hansson@arm.com    if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
14710066Sandreas.hansson@arm.com        retryReq = false;
14810713Sandreas.hansson@arm.com        port.sendRetryReq();
14910066Sandreas.hansson@arm.com    }
15010066Sandreas.hansson@arm.com
15110066Sandreas.hansson@arm.com    schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns);
15210066Sandreas.hansson@arm.com}
15310066Sandreas.hansson@arm.com
15410066Sandreas.hansson@arm.comTick
15510066Sandreas.hansson@arm.comDRAMSim2::recvAtomic(PacketPtr pkt)
15610066Sandreas.hansson@arm.com{
15710066Sandreas.hansson@arm.com    access(pkt);
15810066Sandreas.hansson@arm.com
15910066Sandreas.hansson@arm.com    // 50 ns is just an arbitrary value at this point
16011284Sandreas.hansson@arm.com    return pkt->cacheResponding() ? 0 : 50000;
16110066Sandreas.hansson@arm.com}
16210066Sandreas.hansson@arm.com
16310066Sandreas.hansson@arm.comvoid
16410066Sandreas.hansson@arm.comDRAMSim2::recvFunctional(PacketPtr pkt)
16510066Sandreas.hansson@arm.com{
16610066Sandreas.hansson@arm.com    pkt->pushLabel(name());
16710066Sandreas.hansson@arm.com
16810066Sandreas.hansson@arm.com    functionalAccess(pkt);
16910066Sandreas.hansson@arm.com
17010066Sandreas.hansson@arm.com    // potentially update the packets in our response queue as well
17110066Sandreas.hansson@arm.com    for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
17212823Srmk35@cl.cam.ac.uk        pkt->trySatisfyFunctional(*i);
17310066Sandreas.hansson@arm.com
17410066Sandreas.hansson@arm.com    pkt->popLabel();
17510066Sandreas.hansson@arm.com}
17610066Sandreas.hansson@arm.com
17710066Sandreas.hansson@arm.combool
17810066Sandreas.hansson@arm.comDRAMSim2::recvTimingReq(PacketPtr pkt)
17910066Sandreas.hansson@arm.com{
18011284Sandreas.hansson@arm.com    // if a cache is responding, sink the packet without further action
18111284Sandreas.hansson@arm.com    if (pkt->cacheResponding()) {
18211190Sandreas.hansson@arm.com        pendingDelete.reset(pkt);
18310066Sandreas.hansson@arm.com        return true;
18410066Sandreas.hansson@arm.com    }
18510066Sandreas.hansson@arm.com
18611192Sandreas.hansson@arm.com    // we should not get a new request after committing to retry the
18711192Sandreas.hansson@arm.com    // current one, but unfortunately the CPU violates this rule, so
18811192Sandreas.hansson@arm.com    // simply ignore it for now
18911192Sandreas.hansson@arm.com    if (retryReq)
19011192Sandreas.hansson@arm.com        return false;
19111192Sandreas.hansson@arm.com
19210066Sandreas.hansson@arm.com    // if we cannot accept we need to send a retry once progress can
19310066Sandreas.hansson@arm.com    // be made
19410066Sandreas.hansson@arm.com    bool can_accept = nbrOutstanding() < wrapper.queueSize();
19510066Sandreas.hansson@arm.com
19610066Sandreas.hansson@arm.com    // keep track of the transaction
19710066Sandreas.hansson@arm.com    if (pkt->isRead()) {
19810066Sandreas.hansson@arm.com        if (can_accept) {
19910066Sandreas.hansson@arm.com            outstandingReads[pkt->getAddr()].push(pkt);
20010066Sandreas.hansson@arm.com
20110066Sandreas.hansson@arm.com            // we count a transaction as outstanding until it has left the
20210066Sandreas.hansson@arm.com            // queue in the controller, and the response has been sent
20310066Sandreas.hansson@arm.com            // back, note that this will differ for reads and writes
20410066Sandreas.hansson@arm.com            ++nbrOutstandingReads;
20510066Sandreas.hansson@arm.com        }
20610066Sandreas.hansson@arm.com    } else if (pkt->isWrite()) {
20710066Sandreas.hansson@arm.com        if (can_accept) {
20810066Sandreas.hansson@arm.com            outstandingWrites[pkt->getAddr()].push(pkt);
20910066Sandreas.hansson@arm.com
21010066Sandreas.hansson@arm.com            ++nbrOutstandingWrites;
21110066Sandreas.hansson@arm.com
21210066Sandreas.hansson@arm.com            // perform the access for writes
21310066Sandreas.hansson@arm.com            accessAndRespond(pkt);
21410066Sandreas.hansson@arm.com        }
21510066Sandreas.hansson@arm.com    } else {
21610066Sandreas.hansson@arm.com        // keep it simple and just respond if necessary
21710066Sandreas.hansson@arm.com        accessAndRespond(pkt);
21810066Sandreas.hansson@arm.com        return true;
21910066Sandreas.hansson@arm.com    }
22010066Sandreas.hansson@arm.com
22110066Sandreas.hansson@arm.com    if (can_accept) {
22210066Sandreas.hansson@arm.com        // we should never have a situation when we think there is space,
22310066Sandreas.hansson@arm.com        // and there isn't
22410066Sandreas.hansson@arm.com        assert(wrapper.canAccept());
22510066Sandreas.hansson@arm.com
22610066Sandreas.hansson@arm.com        DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr());
22710066Sandreas.hansson@arm.com
22810066Sandreas.hansson@arm.com        // @todo what about the granularity here, implicit assumption that
22910066Sandreas.hansson@arm.com        // a transaction matches the burst size of the memory (which we
23010066Sandreas.hansson@arm.com        // cannot determine without parsing the ini file ourselves)
23110066Sandreas.hansson@arm.com        wrapper.enqueue(pkt->isWrite(), pkt->getAddr());
23210066Sandreas.hansson@arm.com
23310066Sandreas.hansson@arm.com        return true;
23410066Sandreas.hansson@arm.com    } else {
23510066Sandreas.hansson@arm.com        retryReq = true;
23610066Sandreas.hansson@arm.com        return false;
23710066Sandreas.hansson@arm.com    }
23810066Sandreas.hansson@arm.com}
23910066Sandreas.hansson@arm.com
24010066Sandreas.hansson@arm.comvoid
24110713Sandreas.hansson@arm.comDRAMSim2::recvRespRetry()
24210066Sandreas.hansson@arm.com{
24310066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2, "Retrying\n");
24410066Sandreas.hansson@arm.com
24510066Sandreas.hansson@arm.com    assert(retryResp);
24610066Sandreas.hansson@arm.com    retryResp = false;
24710066Sandreas.hansson@arm.com    sendResponse();
24810066Sandreas.hansson@arm.com}
24910066Sandreas.hansson@arm.com
25010066Sandreas.hansson@arm.comvoid
25110066Sandreas.hansson@arm.comDRAMSim2::accessAndRespond(PacketPtr pkt)
25210066Sandreas.hansson@arm.com{
25310066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr());
25410066Sandreas.hansson@arm.com
25510066Sandreas.hansson@arm.com    bool needsResponse = pkt->needsResponse();
25610066Sandreas.hansson@arm.com
25710066Sandreas.hansson@arm.com    // do the actual memory access which also turns the packet into a
25810066Sandreas.hansson@arm.com    // response
25910066Sandreas.hansson@arm.com    access(pkt);
26010066Sandreas.hansson@arm.com
26110066Sandreas.hansson@arm.com    // turn packet around to go back to requester if response expected
26210066Sandreas.hansson@arm.com    if (needsResponse) {
26310066Sandreas.hansson@arm.com        // access already turned the packet into a response
26410066Sandreas.hansson@arm.com        assert(pkt->isResponse());
26510721SMarco.Balboni@ARM.com        // Here we pay for xbar additional delay and to process the payload
26610721SMarco.Balboni@ARM.com        // of the packet.
26710721SMarco.Balboni@ARM.com        Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
26810721SMarco.Balboni@ARM.com        // Reset the timings of the packet
26910694SMarco.Balboni@ARM.com        pkt->headerDelay = pkt->payloadDelay = 0;
27010066Sandreas.hansson@arm.com
27110066Sandreas.hansson@arm.com        DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
27210066Sandreas.hansson@arm.com                pkt->getAddr());
27310066Sandreas.hansson@arm.com
27410066Sandreas.hansson@arm.com        // queue it to be sent back
27510066Sandreas.hansson@arm.com        responseQueue.push_back(pkt);
27610066Sandreas.hansson@arm.com
27710066Sandreas.hansson@arm.com        // if we are not already waiting for a retry, or are scheduled
27810066Sandreas.hansson@arm.com        // to send a response, schedule an event
27910066Sandreas.hansson@arm.com        if (!retryResp && !sendResponseEvent.scheduled())
28010721SMarco.Balboni@ARM.com            schedule(sendResponseEvent, time);
28110066Sandreas.hansson@arm.com    } else {
28211190Sandreas.hansson@arm.com        // queue the packet for deletion
28311190Sandreas.hansson@arm.com        pendingDelete.reset(pkt);
28410066Sandreas.hansson@arm.com    }
28510066Sandreas.hansson@arm.com}
28610066Sandreas.hansson@arm.com
28710066Sandreas.hansson@arm.comvoid DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle)
28810066Sandreas.hansson@arm.com{
28910296Sandreas.hansson@arm.com    assert(cycle == divCeil(curTick() - startTick,
29010066Sandreas.hansson@arm.com                            wrapper.clockPeriod() * SimClock::Int::ns));
29110066Sandreas.hansson@arm.com
29210066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr);
29310066Sandreas.hansson@arm.com
29410066Sandreas.hansson@arm.com    // get the outstanding reads for the address in question
29510066Sandreas.hansson@arm.com    auto p = outstandingReads.find(addr);
29610066Sandreas.hansson@arm.com    assert(p != outstandingReads.end());
29710066Sandreas.hansson@arm.com
29810066Sandreas.hansson@arm.com    // first in first out, which is not necessarily true, but it is
29910066Sandreas.hansson@arm.com    // the best we can do at this point
30010066Sandreas.hansson@arm.com    PacketPtr pkt = p->second.front();
30110066Sandreas.hansson@arm.com    p->second.pop();
30210066Sandreas.hansson@arm.com
30310066Sandreas.hansson@arm.com    if (p->second.empty())
30410066Sandreas.hansson@arm.com        outstandingReads.erase(p);
30510066Sandreas.hansson@arm.com
30610066Sandreas.hansson@arm.com    // no need to check for drain here as the next call will add a
30710066Sandreas.hansson@arm.com    // response to the response queue straight away
30810066Sandreas.hansson@arm.com    assert(nbrOutstandingReads != 0);
30910066Sandreas.hansson@arm.com    --nbrOutstandingReads;
31010066Sandreas.hansson@arm.com
31110066Sandreas.hansson@arm.com    // perform the actual memory access
31210066Sandreas.hansson@arm.com    accessAndRespond(pkt);
31310066Sandreas.hansson@arm.com}
31410066Sandreas.hansson@arm.com
31510066Sandreas.hansson@arm.comvoid DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
31610066Sandreas.hansson@arm.com{
31710296Sandreas.hansson@arm.com    assert(cycle == divCeil(curTick() - startTick,
31810066Sandreas.hansson@arm.com                            wrapper.clockPeriod() * SimClock::Int::ns));
31910066Sandreas.hansson@arm.com
32010066Sandreas.hansson@arm.com    DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr);
32110066Sandreas.hansson@arm.com
32210066Sandreas.hansson@arm.com    // get the outstanding reads for the address in question
32310066Sandreas.hansson@arm.com    auto p = outstandingWrites.find(addr);
32410066Sandreas.hansson@arm.com    assert(p != outstandingWrites.end());
32510066Sandreas.hansson@arm.com
32610066Sandreas.hansson@arm.com    // we have already responded, and this is only to keep track of
32710066Sandreas.hansson@arm.com    // what is outstanding
32810066Sandreas.hansson@arm.com    p->second.pop();
32910066Sandreas.hansson@arm.com    if (p->second.empty())
33010066Sandreas.hansson@arm.com        outstandingWrites.erase(p);
33110066Sandreas.hansson@arm.com
33210066Sandreas.hansson@arm.com    assert(nbrOutstandingWrites != 0);
33310066Sandreas.hansson@arm.com    --nbrOutstandingWrites;
33410066Sandreas.hansson@arm.com
33510913Sandreas.sandberg@arm.com    if (nbrOutstanding() == 0)
33610913Sandreas.sandberg@arm.com        signalDrainDone();
33710066Sandreas.hansson@arm.com}
33810066Sandreas.hansson@arm.com
33913784Sgabeblack@google.comPort &
34013784Sgabeblack@google.comDRAMSim2::getPort(const std::string &if_name, PortID idx)
34110066Sandreas.hansson@arm.com{
34210066Sandreas.hansson@arm.com    if (if_name != "port") {
34313892Sgabeblack@google.com        return AbstractMemory::getPort(if_name, idx);
34410066Sandreas.hansson@arm.com    } else {
34510066Sandreas.hansson@arm.com        return port;
34610066Sandreas.hansson@arm.com    }
34710066Sandreas.hansson@arm.com}
34810066Sandreas.hansson@arm.com
34910921Sandreas.hansson@arm.comDrainState
35010913Sandreas.sandberg@arm.comDRAMSim2::drain()
35110066Sandreas.hansson@arm.com{
35210066Sandreas.hansson@arm.com    // check our outstanding reads and writes and if any they need to
35310066Sandreas.hansson@arm.com    // drain
35410913Sandreas.sandberg@arm.com    return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained;
35510066Sandreas.hansson@arm.com}
35610066Sandreas.hansson@arm.com
35710066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
35810066Sandreas.hansson@arm.com                                 DRAMSim2& _memory)
35910066Sandreas.hansson@arm.com    : SlavePort(_name, &_memory), memory(_memory)
36010066Sandreas.hansson@arm.com{ }
36110066Sandreas.hansson@arm.com
36210066Sandreas.hansson@arm.comAddrRangeList
36310066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::getAddrRanges() const
36410066Sandreas.hansson@arm.com{
36510066Sandreas.hansson@arm.com    AddrRangeList ranges;
36610066Sandreas.hansson@arm.com    ranges.push_back(memory.getAddrRange());
36710066Sandreas.hansson@arm.com    return ranges;
36810066Sandreas.hansson@arm.com}
36910066Sandreas.hansson@arm.com
37010066Sandreas.hansson@arm.comTick
37110066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvAtomic(PacketPtr pkt)
37210066Sandreas.hansson@arm.com{
37310066Sandreas.hansson@arm.com    return memory.recvAtomic(pkt);
37410066Sandreas.hansson@arm.com}
37510066Sandreas.hansson@arm.com
37610066Sandreas.hansson@arm.comvoid
37710066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvFunctional(PacketPtr pkt)
37810066Sandreas.hansson@arm.com{
37910066Sandreas.hansson@arm.com    memory.recvFunctional(pkt);
38010066Sandreas.hansson@arm.com}
38110066Sandreas.hansson@arm.com
38210066Sandreas.hansson@arm.combool
38310066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvTimingReq(PacketPtr pkt)
38410066Sandreas.hansson@arm.com{
38510066Sandreas.hansson@arm.com    // pass it to the memory controller
38610066Sandreas.hansson@arm.com    return memory.recvTimingReq(pkt);
38710066Sandreas.hansson@arm.com}
38810066Sandreas.hansson@arm.com
38910066Sandreas.hansson@arm.comvoid
39010713Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvRespRetry()
39110066Sandreas.hansson@arm.com{
39210713Sandreas.hansson@arm.com    memory.recvRespRetry();
39310066Sandreas.hansson@arm.com}
39410066Sandreas.hansson@arm.com
39510066Sandreas.hansson@arm.comDRAMSim2*
39610066Sandreas.hansson@arm.comDRAMSim2Params::create()
39710066Sandreas.hansson@arm.com{
39810066Sandreas.hansson@arm.com    return new DRAMSim2(this);
39910066Sandreas.hansson@arm.com}
400