gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
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
47namespace gem5
48{
49
50namespace memory
51{
52
53SimpleMemory::SimpleMemory(const SimpleMemoryParams &p) :
55 port(name() + ".port", *this), latency(p.latency),
57 retryReq(false), retryResp(false),
58 releaseEvent([this]{ release(); }, name()),
59 dequeueEvent([this]{ dequeue(); }, name())
60{
61}
62
63void
65{
67
68 // allow unconnected memories as this is used in several ruby
69 // systems at the moment
70 if (port.isConnected()) {
71 port.sendRangeChange();
72 }
73}
74
75Tick
77{
78 panic_if(pkt->cacheResponding(), "Should not see packets where cache "
79 "is responding");
80
81 access(pkt);
82 return getLatency();
83}
84
85Tick
87{
88 Tick latency = recvAtomic(pkt);
89 getBackdoor(_backdoor);
90 return latency;
91}
92
93void
95{
96 pkt->pushLabel(name());
97
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
111void
113 MemBackdoorPtr &_backdoor)
114{
115 getBackdoor(_backdoor);
116}
117
118bool
120{
121 panic_if(pkt->cacheResponding(), "Should not see packets where cache "
122 "is responding");
123
124 panic_if(!(pkt->isRead() || pkt->isWrite()),
125 "Should only see read and writes at memory controller, "
126 "saw %s to %#llx\n", pkt->cmdString(), pkt->getAddr());
127
128 // we should not get a new request after committing to retry the
129 // current one, but unfortunately the CPU violates this rule, so
130 // simply ignore it for now
131 if (retryReq)
132 return false;
133
134 // if we are busy with a read or write, remember that we have to
135 // retry
136 if (isBusy) {
137 retryReq = true;
138 return false;
139 }
140
141 // technically the packet only reaches us after the header delay,
142 // and since this is a memory controller we also need to
143 // deserialise the payload before performing any write operation
144 Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
145 pkt->headerDelay = pkt->payloadDelay = 0;
146
147 // update the release time according to the bandwidth limit, and
148 // do so with respect to the time it takes to finish this request
149 // rather than long term as it is the short term data rate that is
150 // limited for any real memory
151
152 // calculate an appropriate tick to release to not exceed
153 // the bandwidth limit
154 Tick duration = pkt->getSize() * bandwidth;
155
156 // only consider ourselves busy if there is any need to wait
157 // to avoid extra events being scheduled for (infinitely) fast
158 // memories
159 if (duration != 0) {
160 schedule(releaseEvent, curTick() + duration);
161 isBusy = true;
162 }
163
164 // go ahead and deal with the packet and put the response in the
165 // queue if there is one
166 bool needsResponse = pkt->needsResponse();
167 recvAtomic(pkt);
168 // turn packet around to go back to requestor if response expected
169 if (needsResponse) {
170 // recvAtomic() should already have turned packet into
171 // atomic response
172 assert(pkt->isResponse());
173
174 Tick when_to_send = curTick() + receive_delay + getLatency();
175
176 // typically this should be added at the end, so start the
177 // insertion sort with the last element, also make sure not to
178 // re-order in front of some existing packet with the same
179 // address, the latter is important as this memory effectively
180 // hands out exclusive copies (shared is not asserted)
181 auto i = packetQueue.end();
182 --i;
183 while (i != packetQueue.begin() && when_to_send < i->tick &&
184 !i->pkt->matchAddr(pkt))
185 --i;
186
187 // emplace inserts the element before the position pointed to by
188 // the iterator, so advance it one step
189 packetQueue.emplace(++i, pkt, when_to_send);
190
191 if (!retryResp && !dequeueEvent.scheduled())
192 schedule(dequeueEvent, packetQueue.back().tick);
193 } else {
194 pendingDelete.reset(pkt);
195 }
196
197 return true;
198}
199
200void
202{
203 assert(isBusy);
204 isBusy = false;
205 if (retryReq) {
206 retryReq = false;
207 port.sendRetryReq();
208 }
209}
210
211void
213{
214 assert(!packetQueue.empty());
215 DeferredPacket deferred_pkt = packetQueue.front();
216
217 retryResp = !port.sendTimingResp(deferred_pkt.pkt);
218
219 if (!retryResp) {
220 packetQueue.pop_front();
221
222 // if the queue is not empty, schedule the next dequeue event,
223 // otherwise signal that we are drained if we were asked to do so
224 if (!packetQueue.empty()) {
225 // if there were packets that got in-between then we
226 // already have an event scheduled, so use re-schedule
228 std::max(packetQueue.front().tick, curTick()), true);
229 } else if (drainState() == DrainState::Draining) {
230 DPRINTF(Drain, "Draining of SimpleMemory complete\n");
232 }
233 }
234}
235
236Tick
238{
239 return latency +
240 (latency_var ? rng->random<Tick>(0, latency_var) : 0);
241}
242
243void
245{
246 assert(retryResp);
247
248 dequeue();
249}
250
251Port &
252SimpleMemory::getPort(const std::string &if_name, PortID idx)
253{
254 if (if_name != "port") {
255 return AbstractMemory::getPort(if_name, idx);
256 } else {
257 return port;
258 }
259}
260
263{
264 if (!packetQueue.empty()) {
265 DPRINTF(Drain, "SimpleMemory Queue has requests, waiting to drain\n");
267 } else {
268 return DrainState::Drained;
269 }
270}
271
273 SimpleMemory& _memory)
274 : ResponsePort(_name), mem(_memory)
275{ }
276
279{
280 AddrRangeList ranges;
281 ranges.push_back(mem.getAddrRange());
282 return ranges;
283}
284
285Tick
287{
288 return mem.recvAtomic(pkt);
289}
290
291Tick
293 PacketPtr pkt, MemBackdoorPtr &_backdoor)
294{
295 return mem.recvAtomicBackdoor(pkt, _backdoor);
296}
297
298void
300{
301 mem.recvFunctional(pkt);
302}
303
304void
307{
308 mem.recvMemBackdoorReq(req, backdoor);
309}
310
311bool
313{
314 return mem.recvTimingReq(pkt);
315}
316
317void
319{
320 mem.recvRespRetry();
321}
322
323} // namespace memory
324} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const std::string _name
Definition named.hh:54
virtual std::string name() const
Definition named.hh:60
bool isRead() const
Definition packet.hh:593
Addr getAddr() const
Definition packet.hh:807
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition packet.hh:1470
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition packet.hh:588
bool isResponse() const
Definition packet.hh:598
bool needsResponse() const
Definition packet.hh:608
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition packet.hh:449
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition packet.hh:431
bool isWrite() const
Definition packet.hh:594
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition packet.hh:1399
unsigned getSize() const
Definition packet.hh:817
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition packet.hh:1480
bool cacheResponding() const
Definition packet.hh:659
Ports are used to interface objects to each other.
Definition port.hh:62
ResponsePort(const std::string &name, SimObject *_owner, PortID id=InvalidPortID)
Response port.
Definition port.cc:218
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
AbstractMemory(const AbstractMemory &)
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:78
Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
void recvMemBackdoorReq(const MemBackdoorReq &req, MemBackdoorPtr &backdoor) override
Receive a request for a back door to a range of memory.
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
void recvRespRetry() override
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
MemoryPort(const std::string &_name, SimpleMemory &_memory)
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor) override
Receive an atomic request packet from the peer, and optionally provide a backdoor to the data being a...
void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
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...
void release()
Release the memory after being busy and send a retry if a request was rejected in the meanwhile.
const Tick latency
Latency from that a request is accepted until the response is ready to be sent.
std::list< DeferredPacket > packetQueue
Internal (unbounded) storage to mimic the delay caused by the actual memory access.
bool retryResp
Remember if we failed to send a response and are awaiting a retry.
Tick getLatency() const
Detemine the latency.
EventFunctionWrapper dequeueEvent
bool retryReq
Remember if we have to retry an outstanding request that arrived while we were busy.
SimpleMemory(const SimpleMemoryParams &p)
Definition simple_mem.cc:53
Random::RandomPtr rng
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor)
Definition simple_mem.cc:86
const double bandwidth
Bandwidth in ticks per byte.
bool recvTimingReq(PacketPtr pkt)
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
Tick recvAtomic(PacketPtr pkt)
Definition simple_mem.cc:76
DrainState drain() override
Provide a default implementation of the drain interface for objects that don't need draining.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition simple_mem.cc:64
void recvMemBackdoorReq(const MemBackdoorReq &req, MemBackdoorPtr &backdoor)
EventFunctionWrapper releaseEvent
bool isBusy
Track the state of the memory as either idle or busy, no need for an enum with only two states.
const Tick latency_var
Fudge factor added to the latency.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
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.
Definition drain.hh:77
@ Drained
Buffers drained, ready for serialization/handover.
Definition drain.hh:78
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
void reschedule(Event &event, Tick when, bool always=false)
Definition eventq.hh:1030
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition sim_object.cc:73
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 0 > p
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
MemBackdoor * MemBackdoorPtr
Definition backdoor.hh:127
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
Packet * PacketPtr
SimpleMemory declaration.
const std::string & name()
Definition trace.cc:48

Generated on Mon May 26 2025 09:19:13 for gem5 by doxygen 1.13.2