gem5  v21.1.0.2
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 
46 namespace gem5
47 {
48 
49 namespace 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 
74 void
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 
90 void
92 {
93  startTick = curTick();
94 
95  // kick off the clock ticks
97 }
98 
99 void
102 }
103 
104 void
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",
118  responseQueue.size());
119 
120  if (!responseQueue.empty() && !sendResponseEvent.scheduled())
122 
123  if (nbrOutstanding() == 0)
124  signalDrainDone();
125  } else {
126  retryResp = true;
127 
128  DPRINTF(DRAMsim3, "Waiting for response retry\n");
129 
130  assert(!sendResponseEvent.scheduled());
131  }
132 }
133 
134 unsigned int
136 {
138 }
139 
140 void
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
149  if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
150  retryReq = false;
151  port.sendRetryReq();
152  }
153  }
154 
157 }
158 
159 Tick
161 {
162  access(pkt);
163 
164  // 50 ns is just an arbitrary value at this point
165  return pkt->cacheResponding() ? 0 : 50000;
166 }
167 
168 void
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 
182 bool
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 
245 void
247 {
248  DPRINTF(DRAMsim3, "Retrying\n");
249 
250  assert(retryResp);
251  retryResp = false;
252  sendResponse();
253 }
254 
255 void
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 
292 void 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 
318 void 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)
337  signalDrainDone();
338 }
339 
340 Port&
341 DRAMsim3::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 
358 DRAMsim3::MemoryPort::MemoryPort(const std::string& _name,
359  DRAMsim3& _memory)
360  : ResponsePort(_name, &_memory), mem(_memory)
361 { }
362 
365 {
366  AddrRangeList ranges;
367  ranges.push_back(mem.getAddrRange());
368  return ranges;
369 }
370 
371 Tick
373 {
374  return mem.recvAtomic(pkt);
375 }
376 
377 void
379 {
380  mem.recvFunctional(pkt);
381 }
382 
383 bool
385 {
386  // pass it to the memory controller
387  return mem.recvTimingReq(pkt);
388 }
389 
390 void
392 {
393  mem.recvRespRetry();
394 }
395 
396 } // namespace memory
397 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:189
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:252
gem5::memory::DRAMsim3Wrapper::canAccept
bool canAccept(uint64_t addr, bool is_write) const
Determine if the controller can accept a new packet or not.
Definition: dramsim3_wrapper.cc:124
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::DRAMsim3Wrapper::clockPeriod
double clockPeriod() const
Get the internal clock period used by DRAMsim3, specified in ns.
Definition: dramsim3_wrapper.cc:137
gem5::memory::DRAMsim3::MemoryPort::getAddrRanges
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: dramsim3.cc:364
gem5::memory::DRAMsim3::nbrOutstandingWrites
unsigned int nbrOutstandingWrites
Definition: dramsim3.hh:138
gem5::memory::DRAMsim3::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: dramsim3.hh:180
gem5::memory::DRAMsim3::outstandingWrites
std::unordered_map< Addr, std::queue< PacketPtr > > outstandingWrites
Definition: dramsim3.hh:130
system.hh
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::DRAMsim3Wrapper::burstSize
unsigned int burstSize() const
Get the burst size in bytes used by DRAMsim3.
Definition: dramsim3_wrapper.cc:149
gem5::memory::DRAMsim3::resetStats
void resetStats() override
Callback to reset stats.
Definition: dramsim3.cc:100
gem5::memory::DRAMsim3::outstandingReads
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
memory
Definition: mem.h:38
gem5::memory::DRAMsim3::MemoryPort::recvRespRetry
void recvRespRetry()
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: dramsim3.cc:391
gem5::memory::DRAMsim3Wrapper::queueSize
unsigned int queueSize() const
Get the transaction queue size used by DRAMsim3.
Definition: dramsim3_wrapper.cc:143
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
gem5::memory::DRAMsim3::tick
void tick()
Progress the controller one clock cycle.
Definition: dramsim3.cc:141
gem5::memory::DRAMsim3::retryResp
bool retryResp
Are we waiting for a retry for sending a response.
Definition: dramsim3.hh:116
gem5::memory::DRAMsim3::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: dramsim3.cc:160
gem5::memory::DRAMsim3::nbrOutstandingReads
unsigned int nbrOutstandingReads
Count the number of outstanding transactions so that we can block any further requests until there is...
Definition: dramsim3.hh:137
gem5::memory::DRAMsim3::MemoryPort::MemoryPort
MemoryPort(const std::string &_name, DRAMsim3 &_memory)
Definition: dramsim3.cc:358
gem5::Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:646
gem5::memory::DRAMsim3::getPort
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
gem5::memory::DRAMsim3::sendResponse
void sendResponse()
Definition: dramsim3.cc:105
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:583
gem5::memory::DRAMsim3::MemoryPort::recvFunctional
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Definition: dramsim3.cc:378
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::memory::DRAMsim3::writeComplete
void writeComplete(unsigned id, uint64_t addr)
Write completion callback.
Definition: dramsim3.cc:318
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::memory::DRAMsim3::nbrOutstanding
unsigned int nbrOutstanding() const
Definition: dramsim3.cc:135
gem5::memory::DRAMsim3::startup
void startup() override
startup() is the final initialization call before simulation.
Definition: dramsim3.cc:91
gem5::memory::DRAMsim3::retryReq
bool retryReq
Is the connected port waiting for a retry from us.
Definition: dramsim3.hh:111
gem5::memory::DRAMsim3
Definition: dramsim3.hh:61
gem5::memory::DRAMsim3::startTick
Tick startTick
Keep track of when the wrapper is started.
Definition: dramsim3.hh:121
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::DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:74
gem5::memory::DRAMsim3::recvRespRetry
void recvRespRetry()
Definition: dramsim3.cc:246
gem5::Packet::isRead
bool isRead() const
Definition: packet.hh:582
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::memory::DRAMsim3::wrapper
DRAMsim3Wrapper wrapper
The actual DRAMsim3 wrapper.
Definition: dramsim3.hh:106
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::memory::DRAMsim3::DRAMsim3
DRAMsim3(const Params &p)
Definition: dramsim3.cc:52
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::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
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::memory::DRAMsim3::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: dramsim3.cc:75
gem5::memory::DRAMsim3::responseQueue
std::deque< PacketPtr > responseQueue
Queue to hold response packets until we can send them back.
Definition: dramsim3.hh:145
gem5::memory::DRAMsim3::tickEvent
EventFunctionWrapper tickEvent
Event to schedule clock ticks.
Definition: dramsim3.hh:174
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::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::memory::DRAMsim3::readComplete
void readComplete(unsigned id, uint64_t addr)
Read completion callback.
Definition: dramsim3.cc:292
gem5::Packet::popLabel
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1430
gem5::Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:597
name
const std::string & name()
Definition: trace.cc:49
gem5::memory::DRAMsim3::accessAndRespond
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
gem5::Clocked::clockEdge
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...
Definition: clocked_object.hh:177
gem5::ResponsePort::sendRangeChange
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:296
gem5::memory::DRAMsim3::Params
DRAMsim3Params Params
Definition: dramsim3.hh:184
gem5::memory::DRAMsim3Wrapper::enqueue
void enqueue(uint64_t addr, bool is_write)
Enqueue a packet.
Definition: dramsim3_wrapper.cc:130
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
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
std
Overload hash function for BasicBlockRange type.
Definition: types.hh:111
gem5::memory::AbstractMemory::system
System * system() const
read the system pointer Implemented for completeness with the setter
Definition: abstract_mem.hh:266
gem5::memory::DRAMsim3::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: dramsim3.cc:169
gem5::memory::DRAMsim3::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: dramsim3.cc:183
gem5::memory::DRAMsim3Wrapper::tick
void tick()
Progress the memory controller one cycle.
Definition: dramsim3_wrapper.cc:155
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
mem
bool_vector8 mem[]
Definition: reset_stim.h:43
gem5::memory::DRAMsim3::drain
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
trace.hh
std::list< AddrRange >
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
gem5::registerExitCallback
void registerExitCallback(const std::function< void()> &callback)
Register an exit callback.
Definition: core.cc:146
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::DRAMsim3Wrapper::resetStats
void resetStats()
Reset stats (useful for fastforwarding switch)
Definition: dramsim3_wrapper.cc:111
gem5::memory::DRAMsim3::MemoryPort::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
Definition: dramsim3.cc:372
dramsim3.hh
gem5::Packet::isResponse
bool isResponse() const
Definition: packet.hh:587
gem5::memory::DRAMsim3::sendResponseEvent
EventFunctionWrapper sendResponseEvent
Event to schedule sending of responses.
Definition: dramsim3.hh:164
gem5::memory::DRAMsim3::port
MemoryPort port
Definition: dramsim3.hh:95
callback.hh
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::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::memory::DRAMsim3::MemoryPort::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
Definition: dramsim3.cc:384
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

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