gem5  v20.1.0.0
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 
49  port(name() + ".port", *this),
50  wrapper(p->deviceConfigFile, p->systemConfigFile, p->filePath,
51  p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug),
52  retryReq(false), retryResp(false), startTick(0),
53  nbrOutstandingReads(0), nbrOutstandingWrites(0),
54  sendResponseEvent([this]{ sendResponse(); }, name()),
55  tickEvent([this]{ tick(); }, name())
56 {
58  "Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
59  wrapper.clockPeriod(), wrapper.queueSize());
60 
61  DRAMSim::TransactionCompleteCB* read_cb =
62  new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
63  this, &DRAMSim2::readComplete);
64  DRAMSim::TransactionCompleteCB* write_cb =
65  new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
67  wrapper.setCallbacks(read_cb, write_cb);
68 
69  // Register a callback to compensate for the destructor not
70  // being called. The callback prints the DRAMSim2 stats.
71  registerExitCallback([this]() { wrapper.printStats(); });
72 }
73 
74 void
76 {
78 
79  if (!port.isConnected()) {
80  fatal("DRAMSim2 %s is unconnected!\n", name());
81  } else {
83  }
84 
85  if (system()->cacheLineSize() != wrapper.burstSize())
86  fatal("DRAMSim2 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
101 {
102  assert(!retryResp);
103  assert(!responseQueue.empty());
104 
105  DPRINTF(DRAMSim2, "Attempting to send response\n");
106 
107  bool success = port.sendTimingResp(responseQueue.front());
108  if (success) {
109  responseQueue.pop_front();
110 
111  DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n",
113  responseQueue.size());
114 
115  if (!responseQueue.empty() && !sendResponseEvent.scheduled())
117 
118  if (nbrOutstanding() == 0)
119  signalDrainDone();
120  } else {
121  retryResp = true;
122 
123  DPRINTF(DRAMSim2, "Waiting for response retry\n");
124 
125  assert(!sendResponseEvent.scheduled());
126  }
127 }
128 
129 unsigned int
131 {
133 }
134 
135 void
137 {
138  wrapper.tick();
139 
140  // is the connected port waiting for a retry, if so check the
141  // state and send a retry if conditions have changed
142  if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
143  retryReq = false;
144  port.sendRetryReq();
145  }
146 
148 }
149 
150 Tick
152 {
153  access(pkt);
154 
155  // 50 ns is just an arbitrary value at this point
156  return pkt->cacheResponding() ? 0 : 50000;
157 }
158 
159 void
161 {
162  pkt->pushLabel(name());
163 
164  functionalAccess(pkt);
165 
166  // potentially update the packets in our response queue as well
167  for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
168  pkt->trySatisfyFunctional(*i);
169 
170  pkt->popLabel();
171 }
172 
173 bool
175 {
176  // if a cache is responding, sink the packet without further action
177  if (pkt->cacheResponding()) {
178  pendingDelete.reset(pkt);
179  return true;
180  }
181 
182  // we should not get a new request after committing to retry the
183  // current one, but unfortunately the CPU violates this rule, so
184  // simply ignore it for now
185  if (retryReq)
186  return false;
187 
188  // if we cannot accept we need to send a retry once progress can
189  // be made
190  bool can_accept = nbrOutstanding() < wrapper.queueSize();
191 
192  // keep track of the transaction
193  if (pkt->isRead()) {
194  if (can_accept) {
195  outstandingReads[pkt->getAddr()].push(pkt);
196 
197  // we count a transaction as outstanding until it has left the
198  // queue in the controller, and the response has been sent
199  // back, note that this will differ for reads and writes
201  }
202  } else if (pkt->isWrite()) {
203  if (can_accept) {
204  outstandingWrites[pkt->getAddr()].push(pkt);
205 
207 
208  // perform the access for writes
209  accessAndRespond(pkt);
210  }
211  } else {
212  // keep it simple and just respond if necessary
213  accessAndRespond(pkt);
214  return true;
215  }
216 
217  if (can_accept) {
218  // we should never have a situation when we think there is space,
219  // and there isn't
220  assert(wrapper.canAccept());
221 
222  DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr());
223 
224  // @todo what about the granularity here, implicit assumption that
225  // a transaction matches the burst size of the memory (which we
226  // cannot determine without parsing the ini file ourselves)
227  wrapper.enqueue(pkt->isWrite(), pkt->getAddr());
228 
229  return true;
230  } else {
231  retryReq = true;
232  return false;
233  }
234 }
235 
236 void
238 {
239  DPRINTF(DRAMSim2, "Retrying\n");
240 
241  assert(retryResp);
242  retryResp = false;
243  sendResponse();
244 }
245 
246 void
248 {
249  DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr());
250 
251  bool needsResponse = pkt->needsResponse();
252 
253  // do the actual memory access which also turns the packet into a
254  // response
255  access(pkt);
256 
257  // turn packet around to go back to requestor if response expected
258  if (needsResponse) {
259  // access already turned the packet into a response
260  assert(pkt->isResponse());
261  // Here we pay for xbar additional delay and to process the payload
262  // of the packet.
263  Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
264  // Reset the timings of the packet
265  pkt->headerDelay = pkt->payloadDelay = 0;
266 
267  DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
268  pkt->getAddr());
269 
270  // queue it to be sent back
271  responseQueue.push_back(pkt);
272 
273  // if we are not already waiting for a retry, or are scheduled
274  // to send a response, schedule an event
277  } else {
278  // queue the packet for deletion
279  pendingDelete.reset(pkt);
280  }
281 }
282 
283 void DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle)
284 {
285  assert(cycle == divCeil(curTick() - startTick,
287 
288  DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr);
289 
290  // get the outstanding reads for the address in question
291  auto p = outstandingReads.find(addr);
292  assert(p != outstandingReads.end());
293 
294  // first in first out, which is not necessarily true, but it is
295  // the best we can do at this point
296  PacketPtr pkt = p->second.front();
297  p->second.pop();
298 
299  if (p->second.empty())
300  outstandingReads.erase(p);
301 
302  // no need to check for drain here as the next call will add a
303  // response to the response queue straight away
304  assert(nbrOutstandingReads != 0);
306 
307  // perform the actual memory access
308  accessAndRespond(pkt);
309 }
310 
311 void DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
312 {
313  assert(cycle == divCeil(curTick() - startTick,
315 
316  DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr);
317 
318  // get the outstanding reads for the address in question
319  auto p = outstandingWrites.find(addr);
320  assert(p != outstandingWrites.end());
321 
322  // we have already responded, and this is only to keep track of
323  // what is outstanding
324  p->second.pop();
325  if (p->second.empty())
326  outstandingWrites.erase(p);
327 
328  assert(nbrOutstandingWrites != 0);
330 
331  if (nbrOutstanding() == 0)
332  signalDrainDone();
333 }
334 
335 Port &
336 DRAMSim2::getPort(const std::string &if_name, PortID idx)
337 {
338  if (if_name != "port") {
339  return AbstractMemory::getPort(if_name, idx);
340  } else {
341  return port;
342  }
343 }
344 
347 {
348  // check our outstanding reads and writes and if any they need to
349  // drain
351 }
352 
353 DRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
354  DRAMSim2& _memory)
355  : ResponsePort(_name, &_memory), memory(_memory)
356 { }
357 
360 {
361  AddrRangeList ranges;
362  ranges.push_back(memory.getAddrRange());
363  return ranges;
364 }
365 
366 Tick
368 {
369  return memory.recvAtomic(pkt);
370 }
371 
372 void
374 {
375  memory.recvFunctional(pkt);
376 }
377 
378 bool
380 {
381  // pass it to the memory controller
382  return memory.recvTimingReq(pkt);
383 }
384 
385 void
387 {
388  memory.recvRespRetry();
389 }
390 
391 DRAMSim2*
392 DRAMSim2Params::create()
393 {
394  return new DRAMSim2(this);
395 }
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
DRAMSim2::responseQueue
std::deque< PacketPtr > responseQueue
Queue to hold response packets until we can send them back.
Definition: dramsim2.hh:131
ResponsePort
A ResponsePort is a specialization of a port.
Definition: port.hh:265
Packet::isResponse
bool isResponse() const
Definition: packet.hh:560
SimClock::Int::ns
Tick ns
nanosecond
Definition: core.cc:65
DRAMSim2::startTick
Tick startTick
Keep track of when the wrapper is started.
Definition: dramsim2.hh:107
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:247
system.hh
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:619
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
memory
Definition: mem.h:38
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:367
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:412
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
DRAMSim2::nbrOutstanding
unsigned int nbrOutstanding() const
Definition: dramsim2.cc:130
DRAMSim2::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: dramsim2.cc:75
DRAMSim2::nbrOutstandingWrites
unsigned int nbrOutstandingWrites
Definition: dramsim2.hh:124
DRAMSim2::sendResponse
void sendResponse()
Definition: dramsim2.cc:100
DRAMSim2::retryResp
bool retryResp
Are we waiting for a retry for sending a response.
Definition: dramsim2.hh:102
DRAMSim2::readComplete
void readComplete(unsigned id, uint64_t addr, uint64_t cycle)
Read completion callback.
Definition: dramsim2.cc:283
Packet::isRead
bool isRead() const
Definition: packet.hh:556
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
DRAMSim2::recvRespRetry
void recvRespRetry()
Definition: dramsim2.cc:237
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
Packet::pushLabel
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1393
DRAMSim2::MemoryPort::MemoryPort
MemoryPort(const std::string &_name, DRAMSim2 &_memory)
Definition: dramsim2.cc:353
DRAMSim2Wrapper::canAccept
bool canAccept() const
Determine if the controller can accept a new packet or not.
Definition: dramsim2_wrapper.cc:164
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:115
Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:394
DRAMSim2::DRAMSim2
DRAMSim2(const Params *p)
Definition: dramsim2.cc:47
AbstractMemory::functionalAccess
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
Definition: abstract_mem.cc:475
DRAMSim2::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: dramsim2.cc:160
DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
DRAMSim2::MemoryPort::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
Definition: dramsim2.cc:367
DRAMSim2::tick
void tick()
Progress the controller one clock cycle.
Definition: dramsim2.cc:136
DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:71
AbstractMemory
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Definition: abstract_mem.hh:104
DRAMSim2::retryReq
bool retryReq
Is the connected port waiting for a retry from us.
Definition: dramsim2.hh:97
divCeil
T divCeil(const T &a, const U &b)
Definition: intmath.hh:114
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
registerExitCallback
void registerExitCallback(const std::function< void()> &callback)
Register an exit callback.
Definition: core.cc:140
AbstractMemory::access
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
Definition: abstract_mem.cc:373
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:123
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
DRAMSim2::port
MemoryPort port
Definition: dramsim2.hh:87
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
DRAMSim2Wrapper::burstSize
unsigned int burstSize() const
Get the burst size in bytes used by DRAMSim2.
Definition: dramsim2_wrapper.cc:189
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:174
Clocked::cycle
Cycles cycle
Definition: clocked_object.hh:69
DRAMSim2
Definition: dramsim2.hh:53
Drainable::signalDrainDone
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:301
DRAMSim2::sendResponseEvent
EventFunctionWrapper sendResponseEvent
Event to schedule sending of responses.
Definition: dramsim2.hh:149
dramsim2.hh
DRAMSim2::MemoryPort::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
Definition: dramsim2.cc:379
DRAMSim2::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: dramsim2.cc:151
DRAMSim2::MemoryPort::recvRespRetry
void recvRespRetry()
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: dramsim2.cc:386
name
const std::string & name()
Definition: trace.cc:50
Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:214
DRAMSim2Wrapper::queueSize
unsigned int queueSize() const
Get the transaction queue size used by DRAMSim2.
Definition: dramsim2_wrapper.cc:183
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
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:336
DRAMSim2::startup
void startup() override
startup() is the final initialization call before simulation.
Definition: dramsim2.cc:91
Stats::startTick
Tick startTick
Definition: stat_control.cc:69
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
DRAMSim2Wrapper::tick
void tick()
Progress the memory controller one cycle.
Definition: dramsim2_wrapper.cc:195
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:346
addr
ip6_addr_t addr
Definition: inet.hh:423
Port::isConnected
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:128
DRAMSim2::MemoryPort::recvFunctional
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Definition: dramsim2.cc:373
SimObject::init
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:73
Packet::isWrite
bool isWrite() const
Definition: packet.hh:557
DRAMSim2::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: dramsim2.cc:174
DRAMSim2Wrapper::enqueue
void enqueue(bool is_write, uint64_t addr)
Enqueue a packet.
Definition: dramsim2_wrapper.cc:170
DRAMSim2Wrapper::clockPeriod
double clockPeriod() const
Get the internal clock period used by DRAMSim2, specified in ns.
Definition: dramsim2_wrapper.cc:177
AbstractMemory::Params
AbstractMemoryParams Params
Definition: abstract_mem.hh:207
trace.hh
ResponsePort::sendRetryReq
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition: port.hh:398
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
std::list< AddrRange >
AbstractMemory::system
System * system() const
read the system pointer Implemented for completeness with the setter
Definition: abstract_mem.hh:244
ResponsePort::sendRangeChange
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:293
Packet::trySatisfyFunctional
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Definition: packet.hh:1331
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:165
DRAMSim2::outstandingWrites
std::unordered_map< Addr, std::queue< PacketPtr > > outstandingWrites
Definition: dramsim2.hh:116
DRAMSim2::writeComplete
void writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
Write completion callback.
Definition: dramsim2.cc:311
DRAMSim2::MemoryPort::getAddrRanges
AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: dramsim2.cc:359
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:123
DRAMSim2::tickEvent
EventFunctionWrapper tickEvent
Event to schedule clock ticks.
Definition: dramsim2.hh:159
callback.hh
Packet::popLabel
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1403
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
DRAMSim2::wrapper
DRAMSim2Wrapper wrapper
The actual DRAMSim2 wrapper.
Definition: dramsim2.hh:92
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17