gem5  v21.1.0.2
dramsim2.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/dramsim2.hh"
39 
40 #include "DRAMSim2/Callback.h"
41 #include "base/callback.hh"
42 #include "base/trace.hh"
43 #include "debug/DRAMSim2.hh"
44 #include "debug/Drain.hh"
45 #include "sim/system.hh"
46 
47 namespace gem5
48 {
49 
50 namespace memory
51 {
52 
55  port(name() + ".port", *this),
56  wrapper(p.deviceConfigFile, p.systemConfigFile, p.filePath,
57  p.traceFile, p.range.size() / 1024 / 1024, p.enableDebug),
58  retryReq(false), retryResp(false), startTick(0),
59  nbrOutstandingReads(0), nbrOutstandingWrites(0),
60  sendResponseEvent([this]{ sendResponse(); }, name()),
61  tickEvent([this]{ tick(); }, name())
62 {
63  DPRINTF(DRAMSim2,
64  "Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
65  wrapper.clockPeriod(), wrapper.queueSize());
66 
67  DRAMSim::TransactionCompleteCB* read_cb =
68  new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
69  this, &DRAMSim2::readComplete);
70  DRAMSim::TransactionCompleteCB* write_cb =
71  new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
73  wrapper.setCallbacks(read_cb, write_cb);
74 
75  // Register a callback to compensate for the destructor not
76  // being called. The callback prints the DRAMSim2 stats.
77  registerExitCallback([this]() { wrapper.printStats(); });
78 }
79 
80 void
82 {
84 
85  if (!port.isConnected()) {
86  fatal("DRAMSim2 %s is unconnected!\n", name());
87  } else {
89  }
90 
91  if (system()->cacheLineSize() != wrapper.burstSize())
92  fatal("DRAMSim2 burst size %d does not match cache line size %d\n",
93  wrapper.burstSize(), system()->cacheLineSize());
94 }
95 
96 void
98 {
99  startTick = curTick();
100 
101  // kick off the clock ticks
103 }
104 
105 void
107 {
108  assert(!retryResp);
109  assert(!responseQueue.empty());
110 
111  DPRINTF(DRAMSim2, "Attempting to send response\n");
112 
113  bool success = port.sendTimingResp(responseQueue.front());
114  if (success) {
115  responseQueue.pop_front();
116 
117  DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n",
119  responseQueue.size());
120 
121  if (!responseQueue.empty() && !sendResponseEvent.scheduled())
123 
124  if (nbrOutstanding() == 0)
125  signalDrainDone();
126  } else {
127  retryResp = true;
128 
129  DPRINTF(DRAMSim2, "Waiting for response retry\n");
130 
131  assert(!sendResponseEvent.scheduled());
132  }
133 }
134 
135 unsigned int
137 {
139 }
140 
141 void
143 {
144  wrapper.tick();
145 
146  // is the connected port waiting for a retry, if so check the
147  // state and send a retry if conditions have changed
148  if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
149  retryReq = false;
150  port.sendRetryReq();
151  }
152 
155 }
156 
157 Tick
159 {
160  access(pkt);
161 
162  // 50 ns is just an arbitrary value at this point
163  return pkt->cacheResponding() ? 0 : 50000;
164 }
165 
166 void
168 {
169  pkt->pushLabel(name());
170 
171  functionalAccess(pkt);
172 
173  // potentially update the packets in our response queue as well
174  for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
175  pkt->trySatisfyFunctional(*i);
176 
177  pkt->popLabel();
178 }
179 
180 bool
182 {
183  // if a cache is responding, sink the packet without further action
184  if (pkt->cacheResponding()) {
185  pendingDelete.reset(pkt);
186  return true;
187  }
188 
189  // we should not get a new request after committing to retry the
190  // current one, but unfortunately the CPU violates this rule, so
191  // simply ignore it for now
192  if (retryReq)
193  return false;
194 
195  // if we cannot accept we need to send a retry once progress can
196  // be made
197  bool can_accept = nbrOutstanding() < wrapper.queueSize();
198 
199  // keep track of the transaction
200  if (pkt->isRead()) {
201  if (can_accept) {
202  outstandingReads[pkt->getAddr()].push(pkt);
203 
204  // we count a transaction as outstanding until it has left the
205  // queue in the controller, and the response has been sent
206  // back, note that this will differ for reads and writes
208  }
209  } else if (pkt->isWrite()) {
210  if (can_accept) {
211  outstandingWrites[pkt->getAddr()].push(pkt);
212 
214 
215  // perform the access for writes
216  accessAndRespond(pkt);
217  }
218  } else {
219  // keep it simple and just respond if necessary
220  accessAndRespond(pkt);
221  return true;
222  }
223 
224  if (can_accept) {
225  // we should never have a situation when we think there is space,
226  // and there isn't
227  assert(wrapper.canAccept());
228 
229  DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr());
230 
231  // @todo what about the granularity here, implicit assumption that
232  // a transaction matches the burst size of the memory (which we
233  // cannot determine without parsing the ini file ourselves)
234  wrapper.enqueue(pkt->isWrite(), pkt->getAddr());
235 
236  return true;
237  } else {
238  retryReq = true;
239  return false;
240  }
241 }
242 
243 void
245 {
246  DPRINTF(DRAMSim2, "Retrying\n");
247 
248  assert(retryResp);
249  retryResp = false;
250  sendResponse();
251 }
252 
253 void
255 {
256  DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr());
257 
258  bool needsResponse = pkt->needsResponse();
259 
260  // do the actual memory access which also turns the packet into a
261  // response
262  access(pkt);
263 
264  // turn packet around to go back to requestor if response expected
265  if (needsResponse) {
266  // access already turned the packet into a response
267  assert(pkt->isResponse());
268  // Here we pay for xbar additional delay and to process the payload
269  // of the packet.
270  Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
271  // Reset the timings of the packet
272  pkt->headerDelay = pkt->payloadDelay = 0;
273 
274  DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
275  pkt->getAddr());
276 
277  // queue it to be sent back
278  responseQueue.push_back(pkt);
279 
280  // if we are not already waiting for a retry, or are scheduled
281  // to send a response, schedule an event
284  } else {
285  // queue the packet for deletion
286  pendingDelete.reset(pkt);
287  }
288 }
289 
290 void DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle)
291 {
292  assert(cycle == divCeil(curTick() - startTick,
294 
295  DPRINTF(DRAMSim2, "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 DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
319 {
320  assert(cycle == divCeil(curTick() - startTick,
322 
323  DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr);
324 
325  // get the outstanding reads for the address in question
326  auto p = outstandingWrites.find(addr);
327  assert(p != outstandingWrites.end());
328 
329  // we have already responded, and this is only to keep track of
330  // what is outstanding
331  p->second.pop();
332  if (p->second.empty())
333  outstandingWrites.erase(p);
334 
335  assert(nbrOutstandingWrites != 0);
337 
338  if (nbrOutstanding() == 0)
339  signalDrainDone();
340 }
341 
342 Port &
343 DRAMSim2::getPort(const std::string &if_name, PortID idx)
344 {
345  if (if_name != "port") {
346  return AbstractMemory::getPort(if_name, idx);
347  } else {
348  return port;
349  }
350 }
351 
354 {
355  // check our outstanding reads and writes and if any they need to
356  // drain
358 }
359 
360 DRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
361  DRAMSim2& _memory)
362  : ResponsePort(_name, &_memory), mem(_memory)
363 { }
364 
367 {
368  AddrRangeList ranges;
369  ranges.push_back(mem.getAddrRange());
370  return ranges;
371 }
372 
373 Tick
375 {
376  return mem.recvAtomic(pkt);
377 }
378 
379 void
381 {
382  mem.recvFunctional(pkt);
383 }
384 
385 bool
387 {
388  // pass it to the memory controller
389  return mem.recvTimingReq(pkt);
390 }
391 
392 void
394 {
395  mem.recvRespRetry();
396 }
397 
398 } // namespace memory
399 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::Clocked::cycle
Cycles cycle
Definition: clocked_object.hh:72
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::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::DRAMSim2::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: dramsim2.cc:167
gem5::memory::DRAMSim2::MemoryPort::recvFunctional
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Definition: dramsim2.cc:380
gem5::memory::DRAMSim2::startup
void startup() override
startup() is the final initialization call before simulation.
Definition: dramsim2.cc:97
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::DRAMSim2::recvRespRetry
void recvRespRetry()
Definition: dramsim2.cc:244
gem5::memory::DRAMSim2::nbrOutstandingReads
unsigned int nbrOutstandingReads
Count the number of outstanding transactions so that we can block any further requests until there is...
Definition: dramsim2.hh:129
memory
Definition: mem.h:38
gem5::memory::DRAMSim2::retryResp
bool retryResp
Are we waiting for a retry for sending a response.
Definition: dramsim2.hh:108
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::DRAMSim2::responseQueue
std::deque< PacketPtr > responseQueue
Queue to hold response packets until we can send them back.
Definition: dramsim2.hh:137
gem5::Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:646
gem5::memory::DRAMSim2::Params
DRAMSim2Params Params
Definition: dramsim2.hh:175
gem5::memory::DRAMSim2Wrapper::canAccept
bool canAccept() const
Determine if the controller can accept a new packet or not.
Definition: dramsim2_wrapper.cc:170
gem5::memory::DRAMSim2Wrapper::enqueue
void enqueue(bool is_write, uint64_t addr)
Enqueue a packet.
Definition: dramsim2_wrapper.cc:176
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:583
gem5::memory::DRAMSim2::DRAMSim2
DRAMSim2(const Params &p)
Definition: dramsim2.cc:53
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::memory::DRAMSim2::nbrOutstanding
unsigned int nbrOutstanding() const
Definition: dramsim2.cc:136
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::DRAMSim2::nbrOutstandingWrites
unsigned int nbrOutstandingWrites
Definition: dramsim2.hh:130
gem5::memory::DRAMSim2::readComplete
void readComplete(unsigned id, uint64_t addr, uint64_t cycle)
Read completion callback.
Definition: dramsim2.cc:290
gem5::memory::DRAMSim2::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: dramsim2.cc:343
gem5::memory::DRAMSim2::tick
void tick()
Progress the controller one clock cycle.
Definition: dramsim2.cc:142
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::DRAMSim2::retryReq
bool retryReq
Is the connected port waiting for a retry from us.
Definition: dramsim2.hh:103
gem5::DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:74
gem5::memory::DRAMSim2::tickEvent
EventFunctionWrapper tickEvent
Event to schedule clock ticks.
Definition: dramsim2.hh:165
gem5::Packet::isRead
bool isRead() const
Definition: packet.hh:582
gem5::memory::DRAMSim2::sendResponseEvent
EventFunctionWrapper sendResponseEvent
Event to schedule sending of responses.
Definition: dramsim2.hh:155
gem5::memory::DRAMSim2::writeComplete
void writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
Write completion callback.
Definition: dramsim2.cc:318
gem5::memory::DRAMSim2::sendResponse
void sendResponse()
Definition: dramsim2.cc:106
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
gem5::memory::DRAMSim2Wrapper::queueSize
unsigned int queueSize() const
Get the transaction queue size used by DRAMSim2.
Definition: dramsim2_wrapper.cc:189
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::memory::DRAMSim2::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: dramsim2.hh:121
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::memory::DRAMSim2Wrapper::clockPeriod
double clockPeriod() const
Get the internal clock period used by DRAMSim2, specified in ns.
Definition: dramsim2_wrapper.cc:183
gem5::memory::DRAMSim2::MemoryPort::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
Definition: dramsim2.cc:374
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::DRAMSim2::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: dramsim2.cc:158
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
dramsim2.hh
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
gem5::memory::DRAMSim2::port
MemoryPort port
Definition: dramsim2.hh:93
name
const std::string & name()
Definition: trace.cc:49
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::DRAMSim2::drain
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: dramsim2.cc:353
gem5::divCeil
static constexpr T divCeil(const T &a, const U &b)
Definition: intmath.hh:110
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::memory::DRAMSim2::wrapper
DRAMSim2Wrapper wrapper
The actual DRAMSim2 wrapper.
Definition: dramsim2.hh:98
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
gem5::memory::DRAMSim2Wrapper::tick
void tick()
Progress the memory controller one cycle.
Definition: dramsim2_wrapper.cc:201
gem5::memory::AbstractMemory::system
System * system() const
read the system pointer Implemented for completeness with the setter
Definition: abstract_mem.hh:266
gem5::memory::DRAMSim2::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: dramsim2.hh:171
gem5::memory::DRAMSim2::MemoryPort::getAddrRanges
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: dramsim2.cc:366
gem5::memory::DRAMSim2::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: dramsim2.cc:81
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::DRAMSim2::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: dramsim2.cc:181
trace.hh
std::list< AddrRange >
gem5::memory::DRAMSim2::outstandingWrites
std::unordered_map< Addr, std::queue< PacketPtr > > outstandingWrites
Definition: dramsim2.hh:122
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::DRAMSim2::MemoryPort::recvRespRetry
void recvRespRetry()
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: dramsim2.cc:393
gem5::memory::DRAMSim2::MemoryPort::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
Definition: dramsim2.cc:386
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::DRAMSim2::MemoryPort::MemoryPort
MemoryPort(const std::string &_name, DRAMSim2 &_memory)
Definition: dramsim2.cc:360
gem5::memory::DRAMSim2Wrapper::burstSize
unsigned int burstSize() const
Get the burst size in bytes used by DRAMSim2.
Definition: dramsim2_wrapper.cc:195
gem5::Packet::isResponse
bool isResponse() const
Definition: packet.hh:587
gem5::memory::DRAMSim2::startTick
Tick startTick
Keep track of when the wrapper is started.
Definition: dramsim2.hh:113
callback.hh
gem5::DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
gem5::memory::DRAMSim2::accessAndRespond
void accessAndRespond(PacketPtr pkt)
When a packet is ready, use the "access()" method in AbstractMemory to actually create the response p...
Definition: dramsim2.cc:254
gem5::memory::DRAMSim2
Definition: dramsim2.hh:59
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::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