gem5  v21.1.0.2
simple_mem.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2013, 2015 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 
41 #include "mem/simple_mem.hh"
42 
43 #include "base/random.hh"
44 #include "base/trace.hh"
45 #include "debug/Drain.hh"
46 
47 namespace gem5
48 {
49 
50 namespace memory
51 {
52 
53 SimpleMemory::SimpleMemory(const SimpleMemoryParams &p) :
55  port(name() + ".port", *this), latency(p.latency),
56  latency_var(p.latency_var), bandwidth(p.bandwidth), isBusy(false),
57  retryReq(false), retryResp(false),
58  releaseEvent([this]{ release(); }, name()),
59  dequeueEvent([this]{ dequeue(); }, name())
60 {
61 }
62 
63 void
65 {
67 
68  // allow unconnected memories as this is used in several ruby
69  // systems at the moment
70  if (port.isConnected()) {
72  }
73 }
74 
75 Tick
77 {
78  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
79  "is responding");
80 
81  access(pkt);
82  return getLatency();
83 }
84 
85 Tick
87 {
88  Tick latency = recvAtomic(pkt);
89  getBackdoor(_backdoor);
90  return latency;
91 }
92 
93 void
95 {
96  pkt->pushLabel(name());
97 
98  functionalAccess(pkt);
99 
100  bool done = false;
101  auto p = packetQueue.begin();
102  // potentially update the packets in our packet queue as well
103  while (!done && p != packetQueue.end()) {
104  done = pkt->trySatisfyFunctional(p->pkt);
105  ++p;
106  }
107 
108  pkt->popLabel();
109 }
110 
111 bool
113 {
114  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
115  "is responding");
116 
117  panic_if(!(pkt->isRead() || pkt->isWrite()),
118  "Should only see read and writes at memory controller, "
119  "saw %s to %#llx\n", pkt->cmdString(), pkt->getAddr());
120 
121  // we should not get a new request after committing to retry the
122  // current one, but unfortunately the CPU violates this rule, so
123  // simply ignore it for now
124  if (retryReq)
125  return false;
126 
127  // if we are busy with a read or write, remember that we have to
128  // retry
129  if (isBusy) {
130  retryReq = true;
131  return false;
132  }
133 
134  // technically the packet only reaches us after the header delay,
135  // and since this is a memory controller we also need to
136  // deserialise the payload before performing any write operation
137  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
138  pkt->headerDelay = pkt->payloadDelay = 0;
139 
140  // update the release time according to the bandwidth limit, and
141  // do so with respect to the time it takes to finish this request
142  // rather than long term as it is the short term data rate that is
143  // limited for any real memory
144 
145  // calculate an appropriate tick to release to not exceed
146  // the bandwidth limit
147  Tick duration = pkt->getSize() * bandwidth;
148 
149  // only consider ourselves busy if there is any need to wait
150  // to avoid extra events being scheduled for (infinitely) fast
151  // memories
152  if (duration != 0) {
153  schedule(releaseEvent, curTick() + duration);
154  isBusy = true;
155  }
156 
157  // go ahead and deal with the packet and put the response in the
158  // queue if there is one
159  bool needsResponse = pkt->needsResponse();
160  recvAtomic(pkt);
161  // turn packet around to go back to requestor if response expected
162  if (needsResponse) {
163  // recvAtomic() should already have turned packet into
164  // atomic response
165  assert(pkt->isResponse());
166 
167  Tick when_to_send = curTick() + receive_delay + getLatency();
168 
169  // typically this should be added at the end, so start the
170  // insertion sort with the last element, also make sure not to
171  // re-order in front of some existing packet with the same
172  // address, the latter is important as this memory effectively
173  // hands out exclusive copies (shared is not asserted)
174  auto i = packetQueue.end();
175  --i;
176  while (i != packetQueue.begin() && when_to_send < i->tick &&
177  !i->pkt->matchAddr(pkt))
178  --i;
179 
180  // emplace inserts the element before the position pointed to by
181  // the iterator, so advance it one step
182  packetQueue.emplace(++i, pkt, when_to_send);
183 
184  if (!retryResp && !dequeueEvent.scheduled())
185  schedule(dequeueEvent, packetQueue.back().tick);
186  } else {
187  pendingDelete.reset(pkt);
188  }
189 
190  return true;
191 }
192 
193 void
195 {
196  assert(isBusy);
197  isBusy = false;
198  if (retryReq) {
199  retryReq = false;
200  port.sendRetryReq();
201  }
202 }
203 
204 void
206 {
207  assert(!packetQueue.empty());
208  DeferredPacket deferred_pkt = packetQueue.front();
209 
210  retryResp = !port.sendTimingResp(deferred_pkt.pkt);
211 
212  if (!retryResp) {
213  packetQueue.pop_front();
214 
215  // if the queue is not empty, schedule the next dequeue event,
216  // otherwise signal that we are drained if we were asked to do so
217  if (!packetQueue.empty()) {
218  // if there were packets that got in-between then we
219  // already have an event scheduled, so use re-schedule
221  std::max(packetQueue.front().tick, curTick()), true);
222  } else if (drainState() == DrainState::Draining) {
223  DPRINTF(Drain, "Draining of SimpleMemory complete\n");
224  signalDrainDone();
225  }
226  }
227 }
228 
229 Tick
231 {
232  return latency +
234 }
235 
236 void
238 {
239  assert(retryResp);
240 
241  dequeue();
242 }
243 
244 Port &
245 SimpleMemory::getPort(const std::string &if_name, PortID idx)
246 {
247  if (if_name != "port") {
248  return AbstractMemory::getPort(if_name, idx);
249  } else {
250  return port;
251  }
252 }
253 
256 {
257  if (!packetQueue.empty()) {
258  DPRINTF(Drain, "SimpleMemory Queue has requests, waiting to drain\n");
259  return DrainState::Draining;
260  } else {
261  return DrainState::Drained;
262  }
263 }
264 
265 SimpleMemory::MemoryPort::MemoryPort(const std::string& _name,
266  SimpleMemory& _memory)
267  : ResponsePort(_name, &_memory), mem(_memory)
268 { }
269 
272 {
273  AddrRangeList ranges;
274  ranges.push_back(mem.getAddrRange());
275  return ranges;
276 }
277 
278 Tick
280 {
281  return mem.recvAtomic(pkt);
282 }
283 
284 Tick
286  PacketPtr pkt, MemBackdoorPtr &_backdoor)
287 {
288  return mem.recvAtomicBackdoor(pkt, _backdoor);
289 }
290 
291 void
293 {
294  mem.recvFunctional(pkt);
295 }
296 
297 bool
299 {
300  return mem.recvTimingReq(pkt);
301 }
302 
303 void
305 {
306  mem.recvRespRetry();
307 }
308 
309 } // namespace memory
310 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:252
gem5::Packet::cmdString
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:577
gem5::SimObject::getPort
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
gem5::memory::SimpleMemory::DeferredPacket::pkt
const PacketPtr pkt
Definition: simple_mem.hh:82
gem5::memory::SimpleMemory::isBusy
bool isBusy
Track the state of the memory as either idle or busy, no need for an enum with only two states.
Definition: simple_mem.hh:137
gem5::memory::SimpleMemory::port
MemoryPort port
Definition: simple_mem.hh:106
gem5::memory::SimpleMemory::latency_var
const Tick latency_var
Fudge factor added to the latency.
Definition: simple_mem.hh:117
gem5::ResponsePort::sendRetryReq
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition: port.hh:401
gem5::memory::SimpleMemory::pendingDelete
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
Definition: simple_mem.hh:178
gem5::Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:324
memory
Definition: mem.h:38
gem5::memory::SimpleMemory::DeferredPacket
A deferred packet stores a packet along with its scheduled transmission time.
Definition: simple_mem.hh:76
gem5::memory::SimpleMemory::latency
const Tick latency
Latency from that a request is accepted until the response is ready to be sent.
Definition: simple_mem.hh:112
gem5::memory::SimpleMemory::MemoryPort::MemoryPort
MemoryPort(const std::string &_name, SimpleMemory &_memory)
Definition: simple_mem.cc:265
gem5::SimObject::init
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:76
random.hh
gem5::memory::SimpleMemory::releaseEvent
EventFunctionWrapper releaseEvent
Definition: simple_mem.hh:157
gem5::Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:646
gem5::memory::SimpleMemory::MemoryPort::recvAtomicBackdoor
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor) override
Default implementations.
Definition: simple_mem.cc:285
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:583
gem5::memory::SimpleMemory::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: simple_mem.cc:64
gem5::memory::SimpleMemory::retryReq
bool retryReq
Remember if we have to retry an outstanding request that arrived while we were busy.
Definition: simple_mem.hh:143
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::memory::SimpleMemory
The simple memory is a basic single-ported memory controller with a configurable throughput and laten...
Definition: simple_mem.hh:67
gem5::memory::SimpleMemory::retryResp
bool retryResp
Remember if we failed to send a response and are awaiting a retry.
Definition: simple_mem.hh:149
gem5::memory::SimpleMemory::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: simple_mem.cc:76
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:420
gem5::Packet::payloadDelay
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:438
gem5::memory::SimpleMemory::recvAtomicBackdoor
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor)
Definition: simple_mem.cc:86
gem5::memory::SimpleMemory::MemoryPort::getAddrRanges
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: simple_mem.cc:271
gem5::DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:74
gem5::Packet::isRead
bool isRead() const
Definition: packet.hh:582
gem5::memory::SimpleMemory::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: simple_mem.cc:245
gem5::Random::random
std::enable_if_t< std::is_integral< T >::value, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:90
gem5::memory::AbstractMemory::functionalAccess
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
Definition: abstract_mem.cc:482
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::memory::SimpleMemory::bandwidth
const double bandwidth
Bandwidth in ticks per byte.
Definition: simple_mem.hh:131
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::memory::SimpleMemory::MemoryPort::recvTimingReq
bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
Definition: simple_mem.cc:298
gem5::memory::AbstractMemory
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Definition: abstract_mem.hh:110
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::ResponsePort::sendTimingResp
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition: port.hh:370
gem5::memory::SimpleMemory::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: simple_mem.cc:112
gem5::EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
gem5::Port::isConnected
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:133
gem5::DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
gem5::Packet::pushLabel
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1420
gem5::Packet::popLabel
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1430
gem5::memory::SimpleMemory::MemoryPort::recvRespRetry
void recvRespRetry() override
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: simple_mem.cc:304
gem5::Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:597
gem5::memory::SimpleMemory::dequeueEvent
EventFunctionWrapper dequeueEvent
Definition: simple_mem.hh:165
name
const std::string & name()
Definition: trace.cc:49
gem5::MemBackdoor
Definition: backdoor.hh:41
gem5::ResponsePort::sendRangeChange
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:296
gem5::memory::AbstractMemory::getBackdoor
void getBackdoor(MemBackdoorPtr &bd_ptr)
Definition: abstract_mem.hh:238
gem5::memory::SimpleMemory::MemoryPort::recvAtomic
Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
Definition: simple_mem.cc:279
gem5::memory::SimpleMemory::drain
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: simple_mem.cc:255
gem5::memory::SimpleMemory::recvRespRetry
void recvRespRetry()
Definition: simple_mem.cc:237
gem5::Drainable::signalDrainDone
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:305
gem5::ResponsePort
A ResponsePort is a specialization of a port.
Definition: port.hh:268
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:203
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
gem5::Clocked::tick
Tick tick
Definition: clocked_object.hh:68
gem5::memory::SimpleMemory::packetQueue
std::list< DeferredPacket > packetQueue
Internal (unbounded) storage to mimic the delay caused by the actual memory access.
Definition: simple_mem.hh:124
gem5::memory::SimpleMemory::SimpleMemory
SimpleMemory(const SimpleMemoryParams &p)
Definition: simple_mem.cc:53
gem5::memory::SimpleMemory::release
void release()
Release the memory after being busy and send a retry if a request was rejected in the meanwhile.
Definition: simple_mem.cc:194
gem5::memory::SimpleMemory::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: simple_mem.cc:94
gem5::Packet::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1358
gem5::memory::SimpleMemory::dequeue
void dequeue()
Dequeue a packet from our internal packet queue and move it to the port where it will be sent as soon...
Definition: simple_mem.cc:205
mem
bool_vector8 mem[]
Definition: reset_stim.h:43
trace.hh
std::list< AddrRange >
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
gem5::memory::AbstractMemory::access
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
Definition: abstract_mem.cc:380
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::memory::SimpleMemory::getLatency
Tick getLatency() const
Detemine the latency.
Definition: simple_mem.cc:230
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::Packet::isResponse
bool isResponse() const
Definition: packet.hh:587
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:791
gem5::DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
gem5::memory::SimpleMemory::MemoryPort::recvFunctional
void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
Definition: simple_mem.cc:292
simple_mem.hh

Generated on Tue Sep 21 2021 12:25:45 for gem5 by doxygen 1.8.17