simple_mem.cc revision 9453:0694ba392248
1/* 2 * Copyright (c) 2010-2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2001-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Ron Dreslinski 41 * Ali Saidi 42 * Andreas Hansson 43 */ 44 45#include "base/random.hh" 46#include "mem/simple_mem.hh" 47 48using namespace std; 49 50SimpleMemory::SimpleMemory(const SimpleMemoryParams* p) : 51 AbstractMemory(p), 52 port(name() + ".port", *this), lat(p->latency), 53 lat_var(p->latency_var), bandwidth(p->bandwidth), 54 isBusy(false), retryReq(false), releaseEvent(this) 55{ 56} 57 58void 59SimpleMemory::init() 60{ 61 // allow unconnected memories as this is used in several ruby 62 // systems at the moment 63 if (port.isConnected()) { 64 port.sendRangeChange(); 65 } 66} 67 68Tick 69SimpleMemory::calculateLatency(PacketPtr pkt) 70{ 71 if (pkt->memInhibitAsserted()) { 72 return 0; 73 } else { 74 Tick latency = lat; 75 if (lat_var != 0) 76 latency += random_mt.random<Tick>(0, lat_var); 77 return latency; 78 } 79} 80 81Tick 82SimpleMemory::doAtomicAccess(PacketPtr pkt) 83{ 84 access(pkt); 85 return calculateLatency(pkt); 86} 87 88void 89SimpleMemory::doFunctionalAccess(PacketPtr pkt) 90{ 91 functionalAccess(pkt); 92} 93 94bool 95SimpleMemory::recvTimingReq(PacketPtr pkt) 96{ 97 /// @todo temporary hack to deal with memory corruption issues until 98 /// 4-phase transactions are complete 99 for (int x = 0; x < pendingDelete.size(); x++) 100 delete pendingDelete[x]; 101 pendingDelete.clear(); 102 103 if (pkt->memInhibitAsserted()) { 104 // snooper will supply based on copy of packet 105 // still target's responsibility to delete packet 106 pendingDelete.push_back(pkt); 107 return true; 108 } 109 110 // we should never get a new request after committing to retry the 111 // current one, the bus violates the rule as it simply sends a 112 // retry to the next one waiting on the retry list, so simply 113 // ignore it 114 if (retryReq) 115 return false; 116 117 // if we are busy with a read or write, remember that we have to 118 // retry 119 if (isBusy) { 120 retryReq = true; 121 return false; 122 } 123 124 // update the release time according to the bandwidth limit, and 125 // do so with respect to the time it takes to finish this request 126 // rather than long term as it is the short term data rate that is 127 // limited for any real memory 128 129 // only look at reads and writes when determining if we are busy, 130 // and for how long, as it is not clear what to regulate for the 131 // other types of commands 132 if (pkt->isRead() || pkt->isWrite()) { 133 // calculate an appropriate tick to release to not exceed 134 // the bandwidth limit 135 Tick duration = pkt->getSize() * bandwidth; 136 137 // only consider ourselves busy if there is any need to wait 138 // to avoid extra events being scheduled for (infinitely) fast 139 // memories 140 if (duration != 0) { 141 schedule(releaseEvent, curTick() + duration); 142 isBusy = true; 143 } 144 } 145 146 // go ahead and deal with the packet and put the response in the 147 // queue if there is one 148 bool needsResponse = pkt->needsResponse(); 149 Tick latency = doAtomicAccess(pkt); 150 // turn packet around to go back to requester if response expected 151 if (needsResponse) { 152 // doAtomicAccess() should already have turned packet into 153 // atomic response 154 assert(pkt->isResponse()); 155 port.schedTimingResp(pkt, curTick() + latency); 156 } else { 157 pendingDelete.push_back(pkt); 158 } 159 160 return true; 161} 162 163void 164SimpleMemory::release() 165{ 166 assert(isBusy); 167 isBusy = false; 168 if (retryReq) { 169 retryReq = false; 170 port.sendRetry(); 171 } 172} 173 174BaseSlavePort & 175SimpleMemory::getSlavePort(const std::string &if_name, PortID idx) 176{ 177 if (if_name != "port") { 178 return MemObject::getSlavePort(if_name, idx); 179 } else { 180 return port; 181 } 182} 183 184unsigned int 185SimpleMemory::drain(DrainManager *dm) 186{ 187 int count = port.drain(dm); 188 189 if (count) 190 setDrainState(Drainable::Draining); 191 else 192 setDrainState(Drainable::Drained); 193 return count; 194} 195 196SimpleMemory::MemoryPort::MemoryPort(const std::string& _name, 197 SimpleMemory& _memory) 198 : QueuedSlavePort(_name, &_memory, queueImpl), 199 queueImpl(_memory, *this), memory(_memory) 200{ } 201 202AddrRangeList 203SimpleMemory::MemoryPort::getAddrRanges() const 204{ 205 AddrRangeList ranges; 206 ranges.push_back(memory.getAddrRange()); 207 return ranges; 208} 209 210Tick 211SimpleMemory::MemoryPort::recvAtomic(PacketPtr pkt) 212{ 213 return memory.doAtomicAccess(pkt); 214} 215 216void 217SimpleMemory::MemoryPort::recvFunctional(PacketPtr pkt) 218{ 219 pkt->pushLabel(memory.name()); 220 221 if (!queue.checkFunctional(pkt)) { 222 // Default implementation of SimpleTimingPort::recvFunctional() 223 // calls recvAtomic() and throws away the latency; we can save a 224 // little here by just not calculating the latency. 225 memory.doFunctionalAccess(pkt); 226 } 227 228 pkt->popLabel(); 229} 230 231bool 232SimpleMemory::MemoryPort::recvTimingReq(PacketPtr pkt) 233{ 234 return memory.recvTimingReq(pkt); 235} 236 237SimpleMemory* 238SimpleMemoryParams::create() 239{ 240 return new SimpleMemory(this); 241} 242