gem5 v24.0.0.0
Loading...
Searching...
No Matches
dramsim3.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "mem/dramsim3.hh"
39
40#include "base/callback.hh"
41#include "base/trace.hh"
42#include "debug/DRAMsim3.hh"
43#include "debug/Drain.hh"
44#include "sim/system.hh"
45
46namespace gem5
47{
48
49namespace memory
50{
51
54 port(name() + ".port", *this),
55 read_cb(std::bind(&DRAMsim3::readComplete,
56 this, 0, std::placeholders::_1)),
57 write_cb(std::bind(&DRAMsim3::writeComplete,
58 this, 0, std::placeholders::_1)),
59 wrapper(p.configFile, p.filePath, read_cb, write_cb),
60 retryReq(false), retryResp(false), startTick(0),
61 nbrOutstandingReads(0), nbrOutstandingWrites(0),
62 sendResponseEvent([this]{ sendResponse(); }, name()),
63 tickEvent([this]{ tick(); }, name())
64{
65 DPRINTF(DRAMsim3,
66 "Instantiated DRAMsim3 with clock %d ns and queue size %d\n",
67 wrapper.clockPeriod(), wrapper.queueSize());
68
69 // Register a callback to compensate for the destructor not
70 // being called. The callback prints the DRAMsim3 stats.
71 registerExitCallback([this]() { wrapper.printStats(); });
72}
73
74void
76{
78
79 if (!port.isConnected()) {
80 fatal("DRAMsim3 %s is unconnected!\n", name());
81 } else {
83 }
84
85 if (system()->cacheLineSize() != wrapper.burstSize())
86 fatal("DRAMsim3 burst size %d does not match cache line size %d\n",
87 wrapper.burstSize(), system()->cacheLineSize());
88}
89
90void
92{
94
95 // kick off the clock ticks
97}
98
99void
103
104void
106{
107 assert(!retryResp);
108 assert(!responseQueue.empty());
109
110 DPRINTF(DRAMsim3, "Attempting to send response\n");
111
112 bool success = port.sendTimingResp(responseQueue.front());
113 if (success) {
114 responseQueue.pop_front();
115
116 DPRINTF(DRAMsim3, "Have %d read, %d write, %d responses outstanding\n",
119
120 if (!responseQueue.empty() && !sendResponseEvent.scheduled())
122
123 if (nbrOutstanding() == 0)
125 } else {
126 retryResp = true;
127
128 DPRINTF(DRAMsim3, "Waiting for response retry\n");
129
130 assert(!sendResponseEvent.scheduled());
131 }
132}
133
134unsigned int
139
140void
142{
143 // Only tick when it's timing mode
144 if (system()->isTimingMode()) {
145 wrapper.tick();
146
147 // is the connected port waiting for a retry, if so check the
148 // state and send a retry if conditions have changed
150 retryReq = false;
152 }
153 }
154
157}
158
159Tick
161{
162 access(pkt);
163
164 // 50 ns is just an arbitrary value at this point
165 return pkt->cacheResponding() ? 0 : 50000;
166}
167
168void
170{
171 pkt->pushLabel(name());
172
173 functionalAccess(pkt);
174
175 // potentially update the packets in our response queue as well
176 for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
177 pkt->trySatisfyFunctional(*i);
178
179 pkt->popLabel();
180}
181
182bool
184{
185 // if a cache is responding, sink the packet without further action
186 if (pkt->cacheResponding()) {
187 pendingDelete.reset(pkt);
188 return true;
189 }
190
191 // we should not get a new request after committing to retry the
192 // current one, but unfortunately the CPU violates this rule, so
193 // simply ignore it for now
194 if (retryReq)
195 return false;
196
197 // if we cannot accept we need to send a retry once progress can
198 // be made
199 bool can_accept = nbrOutstanding() < wrapper.queueSize();
200
201 // keep track of the transaction
202 if (pkt->isRead()) {
203 if (can_accept) {
204 outstandingReads[pkt->getAddr()].push(pkt);
205
206 // we count a transaction as outstanding until it has left the
207 // queue in the controller, and the response has been sent
208 // back, note that this will differ for reads and writes
210 }
211 } else if (pkt->isWrite()) {
212 if (can_accept) {
213 outstandingWrites[pkt->getAddr()].push(pkt);
214
216
217 // perform the access for writes
218 accessAndRespond(pkt);
219 }
220 } else {
221 // keep it simple and just respond if necessary
222 accessAndRespond(pkt);
223 return true;
224 }
225
226 if (can_accept) {
227 // we should never have a situation when we think there is space,
228 // and there isn't
229 assert(wrapper.canAccept(pkt->getAddr(), pkt->isWrite()));
230
231 DPRINTF(DRAMsim3, "Enqueueing address %lld\n", pkt->getAddr());
232
233 // @todo what about the granularity here, implicit assumption that
234 // a transaction matches the burst size of the memory (which we
235 // cannot determine without parsing the ini file ourselves)
236 wrapper.enqueue(pkt->getAddr(), pkt->isWrite());
237
238 return true;
239 } else {
240 retryReq = true;
241 return false;
242 }
243}
244
245void
247{
248 DPRINTF(DRAMsim3, "Retrying\n");
249
250 assert(retryResp);
251 retryResp = false;
252 sendResponse();
253}
254
255void
257{
258 DPRINTF(DRAMsim3, "Access for address %lld\n", pkt->getAddr());
259
260 bool needsResponse = pkt->needsResponse();
261
262 // do the actual memory access which also turns the packet into a
263 // response
264 access(pkt);
265
266 // turn packet around to go back to requestor if response expected
267 if (needsResponse) {
268 // access already turned the packet into a response
269 assert(pkt->isResponse());
270 // Here we pay for xbar additional delay and to process the payload
271 // of the packet.
272 Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
273 // Reset the timings of the packet
274 pkt->headerDelay = pkt->payloadDelay = 0;
275
276 DPRINTF(DRAMsim3, "Queuing response for address %lld\n",
277 pkt->getAddr());
278
279 // queue it to be sent back
280 responseQueue.push_back(pkt);
281
282 // if we are not already waiting for a retry, or are scheduled
283 // to send a response, schedule an event
286 } else {
287 // queue the packet for deletion
288 pendingDelete.reset(pkt);
289 }
290}
291
292void DRAMsim3::readComplete(unsigned id, uint64_t addr)
293{
294
295 DPRINTF(DRAMsim3, "Read to address %lld complete\n", addr);
296
297 // get the outstanding reads for the address in question
298 auto p = outstandingReads.find(addr);
299 assert(p != outstandingReads.end());
300
301 // first in first out, which is not necessarily true, but it is
302 // the best we can do at this point
303 PacketPtr pkt = p->second.front();
304 p->second.pop();
305
306 if (p->second.empty())
307 outstandingReads.erase(p);
308
309 // no need to check for drain here as the next call will add a
310 // response to the response queue straight away
311 assert(nbrOutstandingReads != 0);
313
314 // perform the actual memory access
315 accessAndRespond(pkt);
316}
317
318void DRAMsim3::writeComplete(unsigned id, uint64_t addr)
319{
320
321 DPRINTF(DRAMsim3, "Write to address %lld complete\n", addr);
322
323 // get the outstanding reads for the address in question
324 auto p = outstandingWrites.find(addr);
325 assert(p != outstandingWrites.end());
326
327 // we have already responded, and this is only to keep track of
328 // what is outstanding
329 p->second.pop();
330 if (p->second.empty())
331 outstandingWrites.erase(p);
332
333 assert(nbrOutstandingWrites != 0);
335
336 if (nbrOutstanding() == 0)
338}
339
340Port&
341DRAMsim3::getPort(const std::string &if_name, PortID idx)
342{
343 if (if_name != "port") {
344 return ClockedObject::getPort(if_name, idx);
345 } else {
346 return port;
347 }
348}
349
352{
353 // check our outstanding reads and writes and if any they need to
354 // drain
356}
357
358DRAMsim3::MemoryPort::MemoryPort(const std::string& _name,
359 DRAMsim3& _memory)
360 : ResponsePort(_name), mem(_memory)
361{ }
362
365{
366 AddrRangeList ranges;
367 ranges.push_back(mem.getAddrRange());
368 return ranges;
369}
370
371Tick
373{
374 return mem.recvAtomic(pkt);
375}
376
377void
379{
380 mem.recvFunctional(pkt);
381}
382
383bool
385{
386 // pass it to the memory controller
387 return mem.recvTimingReq(pkt);
388}
389
390void
392{
393 mem.recvRespRetry();
394}
395
396} // namespace memory
397} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
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:295
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
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
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
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:349
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition port.hh:454
void sendRangeChange() const
Called by the owner to send a range change.
Definition port.hh:380
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition port.hh:489
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.
uint64_t size() const
Get the memory size.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
System * system() const
read the system pointer Implemented for completeness with the setter
unsigned int burstSize() const
Get the burst size in bytes used by DRAMsim3.
void tick()
Progress the memory controller one cycle.
void enqueue(uint64_t addr, bool is_write)
Enqueue a packet.
unsigned int queueSize() const
Get the transaction queue size used by DRAMsim3.
void resetStats()
Reset stats (useful for fastforwarding switch)
double clockPeriod() const
Get the internal clock period used by DRAMsim3, specified in ns.
bool canAccept(uint64_t addr, bool is_write) const
Determine if the controller can accept a new packet or not.
void recvRespRetry()
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition dramsim3.cc:391
MemoryPort(const std::string &_name, DRAMsim3 &_memory)
Definition dramsim3.cc:358
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Definition dramsim3.cc:378
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
Definition dramsim3.cc:372
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition dramsim3.cc:364
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
Definition dramsim3.cc:384
Tick startTick
Keep track of when the wrapper is started.
Definition dramsim3.hh:121
EventFunctionWrapper tickEvent
Event to schedule clock ticks.
Definition dramsim3.hh:174
DRAMsim3Params Params
Definition dramsim3.hh:184
bool recvTimingReq(PacketPtr pkt)
Definition dramsim3.cc:183
void recvFunctional(PacketPtr pkt)
Definition dramsim3.cc:169
void accessAndRespond(PacketPtr pkt)
When a packet is ready, use the "access()" method in AbstractMemory to actually create the response p...
Definition dramsim3.cc:256
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition dramsim3.cc:75
void tick()
Progress the controller one clock cycle.
Definition dramsim3.cc:141
std::deque< PacketPtr > responseQueue
Queue to hold response packets until we can send them back.
Definition dramsim3.hh:145
void startup() override
startup() is the final initialization call before simulation.
Definition dramsim3.cc:91
void resetStats() override
Callback to reset stats.
Definition dramsim3.cc:100
Tick recvAtomic(PacketPtr pkt)
Definition dramsim3.cc:160
std::unordered_map< Addr, std::queue< PacketPtr > > outstandingWrites
Definition dramsim3.hh:130
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition dramsim3.cc:351
bool retryReq
Is the connected port waiting for a retry from us.
Definition dramsim3.hh:111
DRAMsim3Wrapper wrapper
The actual DRAMsim3 wrapper.
Definition dramsim3.hh:106
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition dramsim3.cc:341
void readComplete(unsigned id, uint64_t addr)
Read completion callback.
Definition dramsim3.cc:292
EventFunctionWrapper sendResponseEvent
Event to schedule sending of responses.
Definition dramsim3.hh:164
bool retryResp
Are we waiting for a retry for sending a response.
Definition dramsim3.hh:116
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
Definition dramsim3.hh:180
unsigned int nbrOutstandingWrites
Definition dramsim3.hh:138
unsigned int nbrOutstanding() const
Definition dramsim3.cc:135
DRAMsim3(const Params &p)
Definition dramsim3.cc:52
unsigned int nbrOutstandingReads
Count the number of outstanding transactions so that we can block any further requests until there is...
Definition dramsim3.hh:137
std::unordered_map< Addr, std::queue< PacketPtr > > outstandingReads
Keep track of what packets are outstanding per address, and do so separately for reads and writes.
Definition dramsim3.hh:129
void writeComplete(unsigned id, uint64_t addr)
Write completion callback.
Definition dramsim3.cc:318
DRAMsim3.
void signalDrainDone() const
Signal that an object is drained.
Definition drain.hh:305
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:458
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
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
Bitfield< 3 > addr
Definition types.hh:84
Tick ns
nanosecond
Definition core.cc:68
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
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
void registerExitCallback(const std::function< void()> &callback)
Register an exit callback.
Definition core.cc:143
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
Definition mem.h:38
bool_vector8 mem[]
Definition reset_stim.h:43
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0