dramsim2.cc revision 10296
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 4010066Sandreas.hansson@arm.com#include "DRAMSim2/Callback.h" 4110066Sandreas.hansson@arm.com#include "base/callback.hh" 4210066Sandreas.hansson@arm.com#include "base/trace.hh" 4310066Sandreas.hansson@arm.com#include "debug/DRAMSim2.hh" 4410066Sandreas.hansson@arm.com#include "debug/Drain.hh" 4510066Sandreas.hansson@arm.com#include "mem/dramsim2.hh" 4610066Sandreas.hansson@arm.com#include "sim/system.hh" 4710066Sandreas.hansson@arm.com 4810066Sandreas.hansson@arm.comDRAMSim2::DRAMSim2(const Params* p) : 4910066Sandreas.hansson@arm.com AbstractMemory(p), 5010066Sandreas.hansson@arm.com port(name() + ".port", *this), 5110066Sandreas.hansson@arm.com wrapper(p->deviceConfigFile, p->systemConfigFile, p->filePath, 5210066Sandreas.hansson@arm.com p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug), 5310296Sandreas.hansson@arm.com retryReq(false), retryResp(false), startTick(0), 5410066Sandreas.hansson@arm.com nbrOutstandingReads(0), nbrOutstandingWrites(0), 5510066Sandreas.hansson@arm.com drainManager(NULL), 5610066Sandreas.hansson@arm.com sendResponseEvent(this), tickEvent(this) 5710066Sandreas.hansson@arm.com{ 5810066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, 5910066Sandreas.hansson@arm.com "Instantiated DRAMSim2 with clock %d ns and queue size %d\n", 6010066Sandreas.hansson@arm.com wrapper.clockPeriod(), wrapper.queueSize()); 6110066Sandreas.hansson@arm.com 6210066Sandreas.hansson@arm.com DRAMSim::TransactionCompleteCB* read_cb = 6310066Sandreas.hansson@arm.com new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>( 6410066Sandreas.hansson@arm.com this, &DRAMSim2::readComplete); 6510066Sandreas.hansson@arm.com DRAMSim::TransactionCompleteCB* write_cb = 6610066Sandreas.hansson@arm.com new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>( 6710066Sandreas.hansson@arm.com this, &DRAMSim2::writeComplete); 6810066Sandreas.hansson@arm.com wrapper.setCallbacks(read_cb, write_cb); 6910066Sandreas.hansson@arm.com 7010066Sandreas.hansson@arm.com // Register a callback to compensate for the destructor not 7110066Sandreas.hansson@arm.com // being called. The callback prints the DRAMSim2 stats. 7210066Sandreas.hansson@arm.com Callback* cb = new MakeCallback<DRAMSim2Wrapper, 7310066Sandreas.hansson@arm.com &DRAMSim2Wrapper::printStats>(wrapper); 7410066Sandreas.hansson@arm.com registerExitCallback(cb); 7510066Sandreas.hansson@arm.com} 7610066Sandreas.hansson@arm.com 7710066Sandreas.hansson@arm.comvoid 7810066Sandreas.hansson@arm.comDRAMSim2::init() 7910066Sandreas.hansson@arm.com{ 8010066Sandreas.hansson@arm.com if (!port.isConnected()) { 8110066Sandreas.hansson@arm.com fatal("DRAMSim2 %s is unconnected!\n", name()); 8210066Sandreas.hansson@arm.com } else { 8310066Sandreas.hansson@arm.com port.sendRangeChange(); 8410066Sandreas.hansson@arm.com } 8510066Sandreas.hansson@arm.com 8610066Sandreas.hansson@arm.com if (system()->cacheLineSize() != wrapper.burstSize()) 8710066Sandreas.hansson@arm.com fatal("DRAMSim2 burst size %d does not match cache line size %d\n", 8810066Sandreas.hansson@arm.com wrapper.burstSize(), system()->cacheLineSize()); 8910066Sandreas.hansson@arm.com} 9010066Sandreas.hansson@arm.com 9110066Sandreas.hansson@arm.comvoid 9210066Sandreas.hansson@arm.comDRAMSim2::startup() 9310066Sandreas.hansson@arm.com{ 9410296Sandreas.hansson@arm.com startTick = curTick(); 9510296Sandreas.hansson@arm.com 9610066Sandreas.hansson@arm.com // kick off the clock ticks 9710066Sandreas.hansson@arm.com schedule(tickEvent, clockEdge()); 9810066Sandreas.hansson@arm.com} 9910066Sandreas.hansson@arm.com 10010066Sandreas.hansson@arm.comvoid 10110066Sandreas.hansson@arm.comDRAMSim2::sendResponse() 10210066Sandreas.hansson@arm.com{ 10310066Sandreas.hansson@arm.com assert(!retryResp); 10410066Sandreas.hansson@arm.com assert(!responseQueue.empty()); 10510066Sandreas.hansson@arm.com 10610066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Attempting to send response\n"); 10710066Sandreas.hansson@arm.com 10810066Sandreas.hansson@arm.com bool success = port.sendTimingResp(responseQueue.front()); 10910066Sandreas.hansson@arm.com if (success) { 11010066Sandreas.hansson@arm.com responseQueue.pop_front(); 11110066Sandreas.hansson@arm.com 11210066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n", 11310066Sandreas.hansson@arm.com nbrOutstandingReads, nbrOutstandingWrites, 11410066Sandreas.hansson@arm.com responseQueue.size()); 11510066Sandreas.hansson@arm.com 11610066Sandreas.hansson@arm.com if (!responseQueue.empty() && !sendResponseEvent.scheduled()) 11710066Sandreas.hansson@arm.com schedule(sendResponseEvent, curTick()); 11810066Sandreas.hansson@arm.com 11910066Sandreas.hansson@arm.com // check if we were asked to drain and if we are now done 12010066Sandreas.hansson@arm.com if (drainManager && nbrOutstanding() == 0) { 12110066Sandreas.hansson@arm.com drainManager->signalDrainDone(); 12210066Sandreas.hansson@arm.com drainManager = NULL; 12310066Sandreas.hansson@arm.com } 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; 14810066Sandreas.hansson@arm.com port.sendRetry(); 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 16010066Sandreas.hansson@arm.com return pkt->memInhibitAsserted() ? 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) 17210066Sandreas.hansson@arm.com pkt->checkFunctional(*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{ 18010066Sandreas.hansson@arm.com // we should never see a new request while in retry 18110066Sandreas.hansson@arm.com assert(!retryReq); 18210066Sandreas.hansson@arm.com 18310066Sandreas.hansson@arm.com // @todo temporary hack to deal with memory corruption issues until 18410066Sandreas.hansson@arm.com // 4-phase transactions are complete 18510066Sandreas.hansson@arm.com for (int x = 0; x < pendingDelete.size(); x++) 18610066Sandreas.hansson@arm.com delete pendingDelete[x]; 18710066Sandreas.hansson@arm.com pendingDelete.clear(); 18810066Sandreas.hansson@arm.com 18910066Sandreas.hansson@arm.com if (pkt->memInhibitAsserted()) { 19010066Sandreas.hansson@arm.com // snooper will supply based on copy of packet 19110066Sandreas.hansson@arm.com // still target's responsibility to delete packet 19210066Sandreas.hansson@arm.com pendingDelete.push_back(pkt); 19310066Sandreas.hansson@arm.com return true; 19410066Sandreas.hansson@arm.com } 19510066Sandreas.hansson@arm.com 19610066Sandreas.hansson@arm.com // if we cannot accept we need to send a retry once progress can 19710066Sandreas.hansson@arm.com // be made 19810066Sandreas.hansson@arm.com bool can_accept = nbrOutstanding() < wrapper.queueSize(); 19910066Sandreas.hansson@arm.com 20010066Sandreas.hansson@arm.com // keep track of the transaction 20110066Sandreas.hansson@arm.com if (pkt->isRead()) { 20210066Sandreas.hansson@arm.com if (can_accept) { 20310066Sandreas.hansson@arm.com outstandingReads[pkt->getAddr()].push(pkt); 20410066Sandreas.hansson@arm.com 20510066Sandreas.hansson@arm.com // we count a transaction as outstanding until it has left the 20610066Sandreas.hansson@arm.com // queue in the controller, and the response has been sent 20710066Sandreas.hansson@arm.com // back, note that this will differ for reads and writes 20810066Sandreas.hansson@arm.com ++nbrOutstandingReads; 20910066Sandreas.hansson@arm.com } 21010066Sandreas.hansson@arm.com } else if (pkt->isWrite()) { 21110066Sandreas.hansson@arm.com if (can_accept) { 21210066Sandreas.hansson@arm.com outstandingWrites[pkt->getAddr()].push(pkt); 21310066Sandreas.hansson@arm.com 21410066Sandreas.hansson@arm.com ++nbrOutstandingWrites; 21510066Sandreas.hansson@arm.com 21610066Sandreas.hansson@arm.com // perform the access for writes 21710066Sandreas.hansson@arm.com accessAndRespond(pkt); 21810066Sandreas.hansson@arm.com } 21910066Sandreas.hansson@arm.com } else { 22010066Sandreas.hansson@arm.com // keep it simple and just respond if necessary 22110066Sandreas.hansson@arm.com accessAndRespond(pkt); 22210066Sandreas.hansson@arm.com return true; 22310066Sandreas.hansson@arm.com } 22410066Sandreas.hansson@arm.com 22510066Sandreas.hansson@arm.com if (can_accept) { 22610066Sandreas.hansson@arm.com // we should never have a situation when we think there is space, 22710066Sandreas.hansson@arm.com // and there isn't 22810066Sandreas.hansson@arm.com assert(wrapper.canAccept()); 22910066Sandreas.hansson@arm.com 23010066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr()); 23110066Sandreas.hansson@arm.com 23210066Sandreas.hansson@arm.com // @todo what about the granularity here, implicit assumption that 23310066Sandreas.hansson@arm.com // a transaction matches the burst size of the memory (which we 23410066Sandreas.hansson@arm.com // cannot determine without parsing the ini file ourselves) 23510066Sandreas.hansson@arm.com wrapper.enqueue(pkt->isWrite(), pkt->getAddr()); 23610066Sandreas.hansson@arm.com 23710066Sandreas.hansson@arm.com return true; 23810066Sandreas.hansson@arm.com } else { 23910066Sandreas.hansson@arm.com retryReq = true; 24010066Sandreas.hansson@arm.com return false; 24110066Sandreas.hansson@arm.com } 24210066Sandreas.hansson@arm.com} 24310066Sandreas.hansson@arm.com 24410066Sandreas.hansson@arm.comvoid 24510066Sandreas.hansson@arm.comDRAMSim2::recvRetry() 24610066Sandreas.hansson@arm.com{ 24710066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Retrying\n"); 24810066Sandreas.hansson@arm.com 24910066Sandreas.hansson@arm.com assert(retryResp); 25010066Sandreas.hansson@arm.com retryResp = false; 25110066Sandreas.hansson@arm.com sendResponse(); 25210066Sandreas.hansson@arm.com} 25310066Sandreas.hansson@arm.com 25410066Sandreas.hansson@arm.comvoid 25510066Sandreas.hansson@arm.comDRAMSim2::accessAndRespond(PacketPtr pkt) 25610066Sandreas.hansson@arm.com{ 25710066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr()); 25810066Sandreas.hansson@arm.com 25910066Sandreas.hansson@arm.com bool needsResponse = pkt->needsResponse(); 26010066Sandreas.hansson@arm.com 26110066Sandreas.hansson@arm.com // do the actual memory access which also turns the packet into a 26210066Sandreas.hansson@arm.com // response 26310066Sandreas.hansson@arm.com access(pkt); 26410066Sandreas.hansson@arm.com 26510066Sandreas.hansson@arm.com // turn packet around to go back to requester if response expected 26610066Sandreas.hansson@arm.com if (needsResponse) { 26710066Sandreas.hansson@arm.com // access already turned the packet into a response 26810066Sandreas.hansson@arm.com assert(pkt->isResponse()); 26910066Sandreas.hansson@arm.com 27010066Sandreas.hansson@arm.com // @todo someone should pay for this 27110066Sandreas.hansson@arm.com pkt->busFirstWordDelay = pkt->busLastWordDelay = 0; 27210066Sandreas.hansson@arm.com 27310066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Queuing response for address %lld\n", 27410066Sandreas.hansson@arm.com pkt->getAddr()); 27510066Sandreas.hansson@arm.com 27610066Sandreas.hansson@arm.com // queue it to be sent back 27710066Sandreas.hansson@arm.com responseQueue.push_back(pkt); 27810066Sandreas.hansson@arm.com 27910066Sandreas.hansson@arm.com // if we are not already waiting for a retry, or are scheduled 28010066Sandreas.hansson@arm.com // to send a response, schedule an event 28110066Sandreas.hansson@arm.com if (!retryResp && !sendResponseEvent.scheduled()) 28210066Sandreas.hansson@arm.com schedule(sendResponseEvent, curTick()); 28310066Sandreas.hansson@arm.com } else { 28410066Sandreas.hansson@arm.com // @todo the packet is going to be deleted, and the DRAMPacket 28510066Sandreas.hansson@arm.com // is still having a pointer to it 28610066Sandreas.hansson@arm.com pendingDelete.push_back(pkt); 28710066Sandreas.hansson@arm.com } 28810066Sandreas.hansson@arm.com} 28910066Sandreas.hansson@arm.com 29010066Sandreas.hansson@arm.comvoid DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle) 29110066Sandreas.hansson@arm.com{ 29210296Sandreas.hansson@arm.com assert(cycle == divCeil(curTick() - startTick, 29310066Sandreas.hansson@arm.com wrapper.clockPeriod() * SimClock::Int::ns)); 29410066Sandreas.hansson@arm.com 29510066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr); 29610066Sandreas.hansson@arm.com 29710066Sandreas.hansson@arm.com // get the outstanding reads for the address in question 29810066Sandreas.hansson@arm.com auto p = outstandingReads.find(addr); 29910066Sandreas.hansson@arm.com assert(p != outstandingReads.end()); 30010066Sandreas.hansson@arm.com 30110066Sandreas.hansson@arm.com // first in first out, which is not necessarily true, but it is 30210066Sandreas.hansson@arm.com // the best we can do at this point 30310066Sandreas.hansson@arm.com PacketPtr pkt = p->second.front(); 30410066Sandreas.hansson@arm.com p->second.pop(); 30510066Sandreas.hansson@arm.com 30610066Sandreas.hansson@arm.com if (p->second.empty()) 30710066Sandreas.hansson@arm.com outstandingReads.erase(p); 30810066Sandreas.hansson@arm.com 30910066Sandreas.hansson@arm.com // no need to check for drain here as the next call will add a 31010066Sandreas.hansson@arm.com // response to the response queue straight away 31110066Sandreas.hansson@arm.com assert(nbrOutstandingReads != 0); 31210066Sandreas.hansson@arm.com --nbrOutstandingReads; 31310066Sandreas.hansson@arm.com 31410066Sandreas.hansson@arm.com // perform the actual memory access 31510066Sandreas.hansson@arm.com accessAndRespond(pkt); 31610066Sandreas.hansson@arm.com} 31710066Sandreas.hansson@arm.com 31810066Sandreas.hansson@arm.comvoid DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle) 31910066Sandreas.hansson@arm.com{ 32010296Sandreas.hansson@arm.com assert(cycle == divCeil(curTick() - startTick, 32110066Sandreas.hansson@arm.com wrapper.clockPeriod() * SimClock::Int::ns)); 32210066Sandreas.hansson@arm.com 32310066Sandreas.hansson@arm.com DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr); 32410066Sandreas.hansson@arm.com 32510066Sandreas.hansson@arm.com // get the outstanding reads for the address in question 32610066Sandreas.hansson@arm.com auto p = outstandingWrites.find(addr); 32710066Sandreas.hansson@arm.com assert(p != outstandingWrites.end()); 32810066Sandreas.hansson@arm.com 32910066Sandreas.hansson@arm.com // we have already responded, and this is only to keep track of 33010066Sandreas.hansson@arm.com // what is outstanding 33110066Sandreas.hansson@arm.com p->second.pop(); 33210066Sandreas.hansson@arm.com if (p->second.empty()) 33310066Sandreas.hansson@arm.com outstandingWrites.erase(p); 33410066Sandreas.hansson@arm.com 33510066Sandreas.hansson@arm.com assert(nbrOutstandingWrites != 0); 33610066Sandreas.hansson@arm.com --nbrOutstandingWrites; 33710066Sandreas.hansson@arm.com 33810066Sandreas.hansson@arm.com // check if we were asked to drain and if we are now done 33910066Sandreas.hansson@arm.com if (drainManager && nbrOutstanding() == 0) { 34010066Sandreas.hansson@arm.com drainManager->signalDrainDone(); 34110066Sandreas.hansson@arm.com drainManager = NULL; 34210066Sandreas.hansson@arm.com } 34310066Sandreas.hansson@arm.com} 34410066Sandreas.hansson@arm.com 34510066Sandreas.hansson@arm.comBaseSlavePort& 34610066Sandreas.hansson@arm.comDRAMSim2::getSlavePort(const std::string &if_name, PortID idx) 34710066Sandreas.hansson@arm.com{ 34810066Sandreas.hansson@arm.com if (if_name != "port") { 34910066Sandreas.hansson@arm.com return MemObject::getSlavePort(if_name, idx); 35010066Sandreas.hansson@arm.com } else { 35110066Sandreas.hansson@arm.com return port; 35210066Sandreas.hansson@arm.com } 35310066Sandreas.hansson@arm.com} 35410066Sandreas.hansson@arm.com 35510066Sandreas.hansson@arm.comunsigned int 35610066Sandreas.hansson@arm.comDRAMSim2::drain(DrainManager* dm) 35710066Sandreas.hansson@arm.com{ 35810066Sandreas.hansson@arm.com // check our outstanding reads and writes and if any they need to 35910066Sandreas.hansson@arm.com // drain 36010066Sandreas.hansson@arm.com if (nbrOutstanding() != 0) { 36110066Sandreas.hansson@arm.com setDrainState(Drainable::Draining); 36210066Sandreas.hansson@arm.com drainManager = dm; 36310066Sandreas.hansson@arm.com return 1; 36410066Sandreas.hansson@arm.com } else { 36510066Sandreas.hansson@arm.com setDrainState(Drainable::Drained); 36610066Sandreas.hansson@arm.com return 0; 36710066Sandreas.hansson@arm.com } 36810066Sandreas.hansson@arm.com} 36910066Sandreas.hansson@arm.com 37010066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::MemoryPort(const std::string& _name, 37110066Sandreas.hansson@arm.com DRAMSim2& _memory) 37210066Sandreas.hansson@arm.com : SlavePort(_name, &_memory), memory(_memory) 37310066Sandreas.hansson@arm.com{ } 37410066Sandreas.hansson@arm.com 37510066Sandreas.hansson@arm.comAddrRangeList 37610066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::getAddrRanges() const 37710066Sandreas.hansson@arm.com{ 37810066Sandreas.hansson@arm.com AddrRangeList ranges; 37910066Sandreas.hansson@arm.com ranges.push_back(memory.getAddrRange()); 38010066Sandreas.hansson@arm.com return ranges; 38110066Sandreas.hansson@arm.com} 38210066Sandreas.hansson@arm.com 38310066Sandreas.hansson@arm.comTick 38410066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvAtomic(PacketPtr pkt) 38510066Sandreas.hansson@arm.com{ 38610066Sandreas.hansson@arm.com return memory.recvAtomic(pkt); 38710066Sandreas.hansson@arm.com} 38810066Sandreas.hansson@arm.com 38910066Sandreas.hansson@arm.comvoid 39010066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvFunctional(PacketPtr pkt) 39110066Sandreas.hansson@arm.com{ 39210066Sandreas.hansson@arm.com memory.recvFunctional(pkt); 39310066Sandreas.hansson@arm.com} 39410066Sandreas.hansson@arm.com 39510066Sandreas.hansson@arm.combool 39610066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvTimingReq(PacketPtr pkt) 39710066Sandreas.hansson@arm.com{ 39810066Sandreas.hansson@arm.com // pass it to the memory controller 39910066Sandreas.hansson@arm.com return memory.recvTimingReq(pkt); 40010066Sandreas.hansson@arm.com} 40110066Sandreas.hansson@arm.com 40210066Sandreas.hansson@arm.comvoid 40310066Sandreas.hansson@arm.comDRAMSim2::MemoryPort::recvRetry() 40410066Sandreas.hansson@arm.com{ 40510066Sandreas.hansson@arm.com memory.recvRetry(); 40610066Sandreas.hansson@arm.com} 40710066Sandreas.hansson@arm.com 40810066Sandreas.hansson@arm.comDRAMSim2* 40910066Sandreas.hansson@arm.comDRAMSim2Params::create() 41010066Sandreas.hansson@arm.com{ 41110066Sandreas.hansson@arm.com return new DRAMSim2(this); 41210066Sandreas.hansson@arm.com} 413