simple_mem.cc revision 9878:cfb305ba76bd
15703SN/A/*
25703SN/A * Copyright (c) 2010-2013 ARM Limited
311860Sandreas.hansson@arm.com * All rights reserved
411860Sandreas.hansson@arm.com *
511860Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
65703SN/A * not be construed as granting a license to any other intellectual
711860Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
811860Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
911860Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
1011860Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
1111860Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
1211860Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
1311860Sandreas.hansson@arm.com *
1410036SAli.Saidi@ARM.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
1510036SAli.Saidi@ARM.com * All rights reserved.
1611860Sandreas.hansson@arm.com *
1711860Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
1811860Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
1910352Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
2011860Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
2111860Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
2211860Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
2311860Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
2411860Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
2511860Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
2611860Sandreas.hansson@arm.com * this software without specific prior written permission.
2710352Sandreas.hansson@arm.com *
2811860Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2911860Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3011860Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3111860Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3211860Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3311680SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3411860Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3511860Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3611860Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3711860Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3811860Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3911860Sandreas.hansson@arm.com *
4011860Sandreas.hansson@arm.com * Authors: Ron Dreslinski
4111860Sandreas.hansson@arm.com *          Ali Saidi
4211680SCurtis.Dunham@arm.com *          Andreas Hansson
4311860Sandreas.hansson@arm.com */
4411860Sandreas.hansson@arm.com
4511860Sandreas.hansson@arm.com#include "base/random.hh"
4611860Sandreas.hansson@arm.com#include "mem/simple_mem.hh"
4711860Sandreas.hansson@arm.com
4811860Sandreas.hansson@arm.comusing namespace std;
4911860Sandreas.hansson@arm.com
5011860Sandreas.hansson@arm.comSimpleMemory::SimpleMemory(const SimpleMemoryParams* p) :
5111860Sandreas.hansson@arm.com    AbstractMemory(p),
5211860Sandreas.hansson@arm.com    port(name() + ".port", *this), latency(p->latency),
5311860Sandreas.hansson@arm.com    latency_var(p->latency_var), bandwidth(p->bandwidth), isBusy(false),
5410892Sandreas.hansson@arm.com    retryReq(false), retryResp(false),
5511336Sandreas.hansson@arm.com    releaseEvent(this), dequeueEvent(this), drainManager(NULL)
5611860Sandreas.hansson@arm.com{
5711860Sandreas.hansson@arm.com}
5811860Sandreas.hansson@arm.com
5911860Sandreas.hansson@arm.comvoid
6011860Sandreas.hansson@arm.comSimpleMemory::init()
6111860Sandreas.hansson@arm.com{
6211860Sandreas.hansson@arm.com    // allow unconnected memories as this is used in several ruby
6311860Sandreas.hansson@arm.com    // systems at the moment
6411860Sandreas.hansson@arm.com    if (port.isConnected()) {
6511860Sandreas.hansson@arm.com        port.sendRangeChange();
6611860Sandreas.hansson@arm.com    }
6711860Sandreas.hansson@arm.com}
6811860Sandreas.hansson@arm.com
6911860Sandreas.hansson@arm.comTick
7011754Sandreas.hansson@arm.comSimpleMemory::recvAtomic(PacketPtr pkt)
7111860Sandreas.hansson@arm.com{
7211860Sandreas.hansson@arm.com    access(pkt);
7311860Sandreas.hansson@arm.com    return pkt->memInhibitAsserted() ? 0 : getLatency();
7411860Sandreas.hansson@arm.com}
7511860Sandreas.hansson@arm.com
7611860Sandreas.hansson@arm.comvoid
7711860Sandreas.hansson@arm.comSimpleMemory::recvFunctional(PacketPtr pkt)
7811860Sandreas.hansson@arm.com{
7911860Sandreas.hansson@arm.com    pkt->pushLabel(name());
8011860Sandreas.hansson@arm.com
8111860Sandreas.hansson@arm.com    functionalAccess(pkt);
8211754Sandreas.hansson@arm.com
8311754Sandreas.hansson@arm.com    // potentially update the packets in our packet queue as well
8411860Sandreas.hansson@arm.com    for (auto i = packetQueue.begin(); i != packetQueue.end(); ++i)
8511860Sandreas.hansson@arm.com        pkt->checkFunctional(i->pkt);
8611754Sandreas.hansson@arm.com
8711860Sandreas.hansson@arm.com    pkt->popLabel();
889978Sandreas.hansson@arm.com}
8911860Sandreas.hansson@arm.com
9011860Sandreas.hansson@arm.combool
919978Sandreas.hansson@arm.comSimpleMemory::recvTimingReq(PacketPtr pkt)
929978Sandreas.hansson@arm.com{
939978Sandreas.hansson@arm.com    /// @todo temporary hack to deal with memory corruption issues until
949978Sandreas.hansson@arm.com    /// 4-phase transactions are complete
959978Sandreas.hansson@arm.com    for (int x = 0; x < pendingDelete.size(); x++)
969978Sandreas.hansson@arm.com        delete pendingDelete[x];
9711860Sandreas.hansson@arm.com    pendingDelete.clear();
989978Sandreas.hansson@arm.com
999978Sandreas.hansson@arm.com    if (pkt->memInhibitAsserted()) {
1009978Sandreas.hansson@arm.com        // snooper will supply based on copy of packet
1019978Sandreas.hansson@arm.com        // still target's responsibility to delete packet
1029978Sandreas.hansson@arm.com        pendingDelete.push_back(pkt);
1039978Sandreas.hansson@arm.com        return true;
10411860Sandreas.hansson@arm.com    }
10511860Sandreas.hansson@arm.com
10611860Sandreas.hansson@arm.com    // we should never get a new request after committing to retry the
10711860Sandreas.hansson@arm.com    // current one, the bus violates the rule as it simply sends a
10811860Sandreas.hansson@arm.com    // retry to the next one waiting on the retry list, so simply
10911860Sandreas.hansson@arm.com    // ignore it
11011860Sandreas.hansson@arm.com    if (retryReq)
11111860Sandreas.hansson@arm.com        return false;
11210352Sandreas.hansson@arm.com
11310352Sandreas.hansson@arm.com    // if we are busy with a read or write, remember that we have to
11410352Sandreas.hansson@arm.com    // retry
11510352Sandreas.hansson@arm.com    if (isBusy) {
11610352Sandreas.hansson@arm.com        retryReq = true;
11710352Sandreas.hansson@arm.com        return false;
11810352Sandreas.hansson@arm.com    }
11910352Sandreas.hansson@arm.com
12010352Sandreas.hansson@arm.com    // @todo someone should pay for this
12110352Sandreas.hansson@arm.com    pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
12210352Sandreas.hansson@arm.com
12310352Sandreas.hansson@arm.com    // update the release time according to the bandwidth limit, and
12410352Sandreas.hansson@arm.com    // do so with respect to the time it takes to finish this request
12510352Sandreas.hansson@arm.com    // rather than long term as it is the short term data rate that is
12610352Sandreas.hansson@arm.com    // limited for any real memory
1279978Sandreas.hansson@arm.com
1289312Sandreas.hansson@arm.com    // only look at reads and writes when determining if we are busy,
1299312Sandreas.hansson@arm.com    // and for how long, as it is not clear what to regulate for the
1309312Sandreas.hansson@arm.com    // other types of commands
1319312Sandreas.hansson@arm.com    if (pkt->isRead() || pkt->isWrite()) {
1329312Sandreas.hansson@arm.com        // calculate an appropriate tick to release to not exceed
1339312Sandreas.hansson@arm.com        // the bandwidth limit
1349312Sandreas.hansson@arm.com        Tick duration = pkt->getSize() * bandwidth;
1359312Sandreas.hansson@arm.com
1369312Sandreas.hansson@arm.com        // only consider ourselves busy if there is any need to wait
13710148Sandreas.hansson@arm.com        // to avoid extra events being scheduled for (infinitely) fast
13810148Sandreas.hansson@arm.com        // memories
13910148Sandreas.hansson@arm.com        if (duration != 0) {
14010148Sandreas.hansson@arm.com            schedule(releaseEvent, curTick() + duration);
14110148Sandreas.hansson@arm.com            isBusy = true;
14210148Sandreas.hansson@arm.com        }
14310148Sandreas.hansson@arm.com    }
14410148Sandreas.hansson@arm.com
14510148Sandreas.hansson@arm.com    // go ahead and deal with the packet and put the response in the
14610148Sandreas.hansson@arm.com    // queue if there is one
14710148Sandreas.hansson@arm.com    bool needsResponse = pkt->needsResponse();
14810148Sandreas.hansson@arm.com    recvAtomic(pkt);
14910148Sandreas.hansson@arm.com    // turn packet around to go back to requester if response expected
15010148Sandreas.hansson@arm.com    if (needsResponse) {
15110148Sandreas.hansson@arm.com        // recvAtomic() should already have turned packet into
15211860Sandreas.hansson@arm.com        // atomic response
15311860Sandreas.hansson@arm.com        assert(pkt->isResponse());
15411860Sandreas.hansson@arm.com        // to keep things simple (and in order), we put the packet at
15511860Sandreas.hansson@arm.com        // the end even if the latency suggests it should be sent
15611860Sandreas.hansson@arm.com        // before the packet(s) before it
15711860Sandreas.hansson@arm.com        packetQueue.push_back(DeferredPacket(pkt, curTick() + getLatency()));
15811860Sandreas.hansson@arm.com        if (!retryResp && !dequeueEvent.scheduled())
15911860Sandreas.hansson@arm.com            schedule(dequeueEvent, packetQueue.back().tick);
16011860Sandreas.hansson@arm.com    } else {
16111860Sandreas.hansson@arm.com        pendingDelete.push_back(pkt);
16211860Sandreas.hansson@arm.com    }
16311860Sandreas.hansson@arm.com
16411860Sandreas.hansson@arm.com    return true;
16511860Sandreas.hansson@arm.com}
16611860Sandreas.hansson@arm.com
16711860Sandreas.hansson@arm.comvoid
16811860Sandreas.hansson@arm.comSimpleMemory::release()
16911860Sandreas.hansson@arm.com{
17011860Sandreas.hansson@arm.com    assert(isBusy);
17111860Sandreas.hansson@arm.com    isBusy = false;
17211860Sandreas.hansson@arm.com    if (retryReq) {
17311860Sandreas.hansson@arm.com        retryReq = false;
17411860Sandreas.hansson@arm.com        port.sendRetry();
17511860Sandreas.hansson@arm.com    }
17611860Sandreas.hansson@arm.com}
17711860Sandreas.hansson@arm.com
17811860Sandreas.hansson@arm.comvoid
17911860Sandreas.hansson@arm.comSimpleMemory::dequeue()
18011860Sandreas.hansson@arm.com{
18111860Sandreas.hansson@arm.com    assert(!packetQueue.empty());
18211860Sandreas.hansson@arm.com    DeferredPacket deferred_pkt = packetQueue.front();
18311860Sandreas.hansson@arm.com
18411860Sandreas.hansson@arm.com    retryResp = !port.sendTimingResp(deferred_pkt.pkt);
18511860Sandreas.hansson@arm.com
18611860Sandreas.hansson@arm.com    if (!retryResp) {
18711860Sandreas.hansson@arm.com        packetQueue.pop_front();
18811860Sandreas.hansson@arm.com
18911860Sandreas.hansson@arm.com        // if the queue is not empty, schedule the next dequeue event,
19011860Sandreas.hansson@arm.com        // otherwise signal that we are drained if we were asked to do so
19111860Sandreas.hansson@arm.com        if (!packetQueue.empty()) {
19211860Sandreas.hansson@arm.com            // if there were packets that got in-between then we
19311860Sandreas.hansson@arm.com            // already have an event scheduled, so use re-schedule
19411860Sandreas.hansson@arm.com            reschedule(dequeueEvent,
19511860Sandreas.hansson@arm.com                       std::max(packetQueue.front().tick, curTick()), true);
19611860Sandreas.hansson@arm.com        } else if (drainManager) {
19711860Sandreas.hansson@arm.com            drainManager->signalDrainDone();
19811860Sandreas.hansson@arm.com            drainManager = NULL;
19911860Sandreas.hansson@arm.com        }
20011860Sandreas.hansson@arm.com    }
20111860Sandreas.hansson@arm.com}
20211860Sandreas.hansson@arm.com
20311860Sandreas.hansson@arm.comTick
20411860Sandreas.hansson@arm.comSimpleMemory::getLatency() const
20511860Sandreas.hansson@arm.com{
20611860Sandreas.hansson@arm.com    return latency +
20711860Sandreas.hansson@arm.com        (latency_var ? random_mt.random<Tick>(0, latency_var) : 0);
20811860Sandreas.hansson@arm.com}
20911860Sandreas.hansson@arm.com
21011860Sandreas.hansson@arm.comvoid
21111860Sandreas.hansson@arm.comSimpleMemory::recvRetry()
21211860Sandreas.hansson@arm.com{
21311860Sandreas.hansson@arm.com    assert(retryResp);
21411860Sandreas.hansson@arm.com
21511860Sandreas.hansson@arm.com    dequeue();
21611860Sandreas.hansson@arm.com}
21711860Sandreas.hansson@arm.com
21811860Sandreas.hansson@arm.comBaseSlavePort &
21911441Sandreas.hansson@arm.comSimpleMemory::getSlavePort(const std::string &if_name, PortID idx)
22011441Sandreas.hansson@arm.com{
22111441Sandreas.hansson@arm.com    if (if_name != "port") {
22211860Sandreas.hansson@arm.com        return MemObject::getSlavePort(if_name, idx);
22311860Sandreas.hansson@arm.com    } else {
22411860Sandreas.hansson@arm.com        return port;
22511860Sandreas.hansson@arm.com    }
22611860Sandreas.hansson@arm.com}
22711860Sandreas.hansson@arm.com
22811860Sandreas.hansson@arm.comunsigned int
22911860Sandreas.hansson@arm.comSimpleMemory::drain(DrainManager *dm)
23011860Sandreas.hansson@arm.com{
23111860Sandreas.hansson@arm.com    int count = 0;
23211860Sandreas.hansson@arm.com
23311860Sandreas.hansson@arm.com    // also track our internal queue
23411860Sandreas.hansson@arm.com    if (!packetQueue.empty()) {
23511860Sandreas.hansson@arm.com        count += 1;
23611860Sandreas.hansson@arm.com        drainManager = dm;
23711860Sandreas.hansson@arm.com    }
23811860Sandreas.hansson@arm.com
23911860Sandreas.hansson@arm.com    if (count)
24011860Sandreas.hansson@arm.com        setDrainState(Drainable::Draining);
24111860Sandreas.hansson@arm.com    else
24211860Sandreas.hansson@arm.com        setDrainState(Drainable::Drained);
24311860Sandreas.hansson@arm.com    return count;
24411860Sandreas.hansson@arm.com}
24511860Sandreas.hansson@arm.com
24611860Sandreas.hansson@arm.comSimpleMemory::MemoryPort::MemoryPort(const std::string& _name,
24711860Sandreas.hansson@arm.com                                     SimpleMemory& _memory)
24811860Sandreas.hansson@arm.com    : SlavePort(_name, &_memory), memory(_memory)
24911860Sandreas.hansson@arm.com{ }
25011860Sandreas.hansson@arm.com
25111860Sandreas.hansson@arm.comAddrRangeList
25211860Sandreas.hansson@arm.comSimpleMemory::MemoryPort::getAddrRanges() const
25311860Sandreas.hansson@arm.com{
25411860Sandreas.hansson@arm.com    AddrRangeList ranges;
25511860Sandreas.hansson@arm.com    ranges.push_back(memory.getAddrRange());
25611860Sandreas.hansson@arm.com    return ranges;
25711860Sandreas.hansson@arm.com}
25811860Sandreas.hansson@arm.com
25911860Sandreas.hansson@arm.comTick
2609978Sandreas.hansson@arm.comSimpleMemory::MemoryPort::recvAtomic(PacketPtr pkt)
26111860Sandreas.hansson@arm.com{
26211680SCurtis.Dunham@arm.com    return memory.recvAtomic(pkt);
26311680SCurtis.Dunham@arm.com}
26411680SCurtis.Dunham@arm.com
26511680SCurtis.Dunham@arm.comvoid
2669978Sandreas.hansson@arm.comSimpleMemory::MemoryPort::recvFunctional(PacketPtr pkt)
26710726Sandreas.hansson@arm.com{
26810352Sandreas.hansson@arm.com    memory.recvFunctional(pkt);
26910892Sandreas.hansson@arm.com}
27011860Sandreas.hansson@arm.com
27111860Sandreas.hansson@arm.combool
27211860Sandreas.hansson@arm.comSimpleMemory::MemoryPort::recvTimingReq(PacketPtr pkt)
27311860Sandreas.hansson@arm.com{
27411754Sandreas.hansson@arm.com    return memory.recvTimingReq(pkt);
27511860Sandreas.hansson@arm.com}
27611860Sandreas.hansson@arm.com
27711860Sandreas.hansson@arm.comvoid
27811860Sandreas.hansson@arm.comSimpleMemory::MemoryPort::recvRetry()
27911860Sandreas.hansson@arm.com{
28011860Sandreas.hansson@arm.com    memory.recvRetry();
28111860Sandreas.hansson@arm.com}
28211860Sandreas.hansson@arm.com
28311860Sandreas.hansson@arm.comSimpleMemory*
28411860Sandreas.hansson@arm.comSimpleMemoryParams::create()
28511860Sandreas.hansson@arm.com{
28611860Sandreas.hansson@arm.com    return new SimpleMemory(this);
28711860Sandreas.hansson@arm.com}
28811860Sandreas.hansson@arm.com