gem5  v22.1.0.0
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
#define DPRINTF(x,...)
Definition: trace.hh:186
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
bool isRead() const
Definition: packet.hh:592
Addr getAddr() const
Definition: packet.hh:805
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1448
bool isResponse() const
Definition: packet.hh:597
bool needsResponse() const
Definition: packet.hh:607
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:448
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:430
bool isWrite() const
Definition: packet.hh:593
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1386
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:587
unsigned getSize() const
Definition: packet.hh:815
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1458
bool cacheResponding() const
Definition: packet.hh:657
Ports are used to interface objects to each other.
Definition: port.hh:62
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:133
A ResponsePort is a specialization of a port.
Definition: port.hh:270
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition: port.hh:370
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:296
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition: port.hh:401
An abstract memory represents a contiguous block of physical memory, with an associated address range...
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
void getBackdoor(MemBackdoorPtr &bd_ptr)
A deferred packet stores a packet along with its scheduled transmission time.
Definition: simple_mem.hh:77
Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
Definition: simple_mem.cc:279
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: simple_mem.cc:271
bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
Definition: simple_mem.cc:298
void recvRespRetry() override
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: simple_mem.cc:304
MemoryPort(const std::string &_name, SimpleMemory &_memory)
Definition: simple_mem.cc:265
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor) override
Default implementations.
Definition: simple_mem.cc:285
void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
Definition: simple_mem.cc:292
The simple memory is a basic single-ported memory controller with a configurable throughput and laten...
Definition: simple_mem.hh:68
void recvFunctional(PacketPtr pkt)
Definition: simple_mem.cc:94
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
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
const Tick latency
Latency from that a request is accepted until the response is ready to be sent.
Definition: simple_mem.hh:112
std::list< DeferredPacket > packetQueue
Internal (unbounded) storage to mimic the delay caused by the actual memory access.
Definition: simple_mem.hh:124
bool retryResp
Remember if we failed to send a response and are awaiting a retry.
Definition: simple_mem.hh:149
Tick getLatency() const
Detemine the latency.
Definition: simple_mem.cc:230
EventFunctionWrapper dequeueEvent
Definition: simple_mem.hh:165
bool retryReq
Remember if we have to retry an outstanding request that arrived while we were busy.
Definition: simple_mem.hh:143
SimpleMemory(const SimpleMemoryParams &p)
Definition: simple_mem.cc:53
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor)
Definition: simple_mem.cc:86
const double bandwidth
Bandwidth in ticks per byte.
Definition: simple_mem.hh:131
bool recvTimingReq(PacketPtr pkt)
Definition: simple_mem.cc:112
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
Tick recvAtomic(PacketPtr pkt)
Definition: simple_mem.cc:76
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
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: simple_mem.cc:64
EventFunctionWrapper releaseEvent
Definition: simple_mem.hh:157
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
const Tick latency_var
Fudge factor added to the latency.
Definition: simple_mem.hh:117
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
Random random_mt
Definition: random.cc:99
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:90
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:305
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:324
DrainState
Object drain/handover states.
Definition: drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
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
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:76
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 54 > p
Definition: pagetable.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
uint64_t Tick
Tick count type.
Definition: types.hh:58
SimpleMemory declaration.
Definition: mem.h:38
bool_vector8 mem[]
Definition: reset_stim.h:43
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:39 for gem5 by doxygen 1.9.1