dramsim2.cc (13784:1941dc118243) dramsim2.cc (13892:0182a0601f66)
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 * Authors: Andreas Hansson
38 */
39
40#include "mem/dramsim2.hh"
41
42#include "DRAMSim2/Callback.h"
43#include "base/callback.hh"
44#include "base/trace.hh"
45#include "debug/DRAMSim2.hh"
46#include "debug/Drain.hh"
47#include "sim/system.hh"
48
49DRAMSim2::DRAMSim2(const Params* p) :
50 AbstractMemory(p),
51 port(name() + ".port", *this),
52 wrapper(p->deviceConfigFile, p->systemConfigFile, p->filePath,
53 p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug),
54 retryReq(false), retryResp(false), startTick(0),
55 nbrOutstandingReads(0), nbrOutstandingWrites(0),
56 sendResponseEvent([this]{ sendResponse(); }, name()),
57 tickEvent([this]{ tick(); }, name())
58{
59 DPRINTF(DRAMSim2,
60 "Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
61 wrapper.clockPeriod(), wrapper.queueSize());
62
63 DRAMSim::TransactionCompleteCB* read_cb =
64 new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
65 this, &DRAMSim2::readComplete);
66 DRAMSim::TransactionCompleteCB* write_cb =
67 new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
68 this, &DRAMSim2::writeComplete);
69 wrapper.setCallbacks(read_cb, write_cb);
70
71 // Register a callback to compensate for the destructor not
72 // being called. The callback prints the DRAMSim2 stats.
73 Callback* cb = new MakeCallback<DRAMSim2Wrapper,
74 &DRAMSim2Wrapper::printStats>(wrapper);
75 registerExitCallback(cb);
76}
77
78void
79DRAMSim2::init()
80{
81 AbstractMemory::init();
82
83 if (!port.isConnected()) {
84 fatal("DRAMSim2 %s is unconnected!\n", name());
85 } else {
86 port.sendRangeChange();
87 }
88
89 if (system()->cacheLineSize() != wrapper.burstSize())
90 fatal("DRAMSim2 burst size %d does not match cache line size %d\n",
91 wrapper.burstSize(), system()->cacheLineSize());
92}
93
94void
95DRAMSim2::startup()
96{
97 startTick = curTick();
98
99 // kick off the clock ticks
100 schedule(tickEvent, clockEdge());
101}
102
103void
104DRAMSim2::sendResponse()
105{
106 assert(!retryResp);
107 assert(!responseQueue.empty());
108
109 DPRINTF(DRAMSim2, "Attempting to send response\n");
110
111 bool success = port.sendTimingResp(responseQueue.front());
112 if (success) {
113 responseQueue.pop_front();
114
115 DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n",
116 nbrOutstandingReads, nbrOutstandingWrites,
117 responseQueue.size());
118
119 if (!responseQueue.empty() && !sendResponseEvent.scheduled())
120 schedule(sendResponseEvent, curTick());
121
122 if (nbrOutstanding() == 0)
123 signalDrainDone();
124 } else {
125 retryResp = true;
126
127 DPRINTF(DRAMSim2, "Waiting for response retry\n");
128
129 assert(!sendResponseEvent.scheduled());
130 }
131}
132
133unsigned int
134DRAMSim2::nbrOutstanding() const
135{
136 return nbrOutstandingReads + nbrOutstandingWrites + responseQueue.size();
137}
138
139void
140DRAMSim2::tick()
141{
142 wrapper.tick();
143
144 // is the connected port waiting for a retry, if so check the
145 // state and send a retry if conditions have changed
146 if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
147 retryReq = false;
148 port.sendRetryReq();
149 }
150
151 schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns);
152}
153
154Tick
155DRAMSim2::recvAtomic(PacketPtr pkt)
156{
157 access(pkt);
158
159 // 50 ns is just an arbitrary value at this point
160 return pkt->cacheResponding() ? 0 : 50000;
161}
162
163void
164DRAMSim2::recvFunctional(PacketPtr pkt)
165{
166 pkt->pushLabel(name());
167
168 functionalAccess(pkt);
169
170 // potentially update the packets in our response queue as well
171 for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
172 pkt->trySatisfyFunctional(*i);
173
174 pkt->popLabel();
175}
176
177bool
178DRAMSim2::recvTimingReq(PacketPtr pkt)
179{
180 // if a cache is responding, sink the packet without further action
181 if (pkt->cacheResponding()) {
182 pendingDelete.reset(pkt);
183 return true;
184 }
185
186 // we should not get a new request after committing to retry the
187 // current one, but unfortunately the CPU violates this rule, so
188 // simply ignore it for now
189 if (retryReq)
190 return false;
191
192 // if we cannot accept we need to send a retry once progress can
193 // be made
194 bool can_accept = nbrOutstanding() < wrapper.queueSize();
195
196 // keep track of the transaction
197 if (pkt->isRead()) {
198 if (can_accept) {
199 outstandingReads[pkt->getAddr()].push(pkt);
200
201 // we count a transaction as outstanding until it has left the
202 // queue in the controller, and the response has been sent
203 // back, note that this will differ for reads and writes
204 ++nbrOutstandingReads;
205 }
206 } else if (pkt->isWrite()) {
207 if (can_accept) {
208 outstandingWrites[pkt->getAddr()].push(pkt);
209
210 ++nbrOutstandingWrites;
211
212 // perform the access for writes
213 accessAndRespond(pkt);
214 }
215 } else {
216 // keep it simple and just respond if necessary
217 accessAndRespond(pkt);
218 return true;
219 }
220
221 if (can_accept) {
222 // we should never have a situation when we think there is space,
223 // and there isn't
224 assert(wrapper.canAccept());
225
226 DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr());
227
228 // @todo what about the granularity here, implicit assumption that
229 // a transaction matches the burst size of the memory (which we
230 // cannot determine without parsing the ini file ourselves)
231 wrapper.enqueue(pkt->isWrite(), pkt->getAddr());
232
233 return true;
234 } else {
235 retryReq = true;
236 return false;
237 }
238}
239
240void
241DRAMSim2::recvRespRetry()
242{
243 DPRINTF(DRAMSim2, "Retrying\n");
244
245 assert(retryResp);
246 retryResp = false;
247 sendResponse();
248}
249
250void
251DRAMSim2::accessAndRespond(PacketPtr pkt)
252{
253 DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr());
254
255 bool needsResponse = pkt->needsResponse();
256
257 // do the actual memory access which also turns the packet into a
258 // response
259 access(pkt);
260
261 // turn packet around to go back to requester if response expected
262 if (needsResponse) {
263 // access already turned the packet into a response
264 assert(pkt->isResponse());
265 // Here we pay for xbar additional delay and to process the payload
266 // of the packet.
267 Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
268 // Reset the timings of the packet
269 pkt->headerDelay = pkt->payloadDelay = 0;
270
271 DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
272 pkt->getAddr());
273
274 // queue it to be sent back
275 responseQueue.push_back(pkt);
276
277 // if we are not already waiting for a retry, or are scheduled
278 // to send a response, schedule an event
279 if (!retryResp && !sendResponseEvent.scheduled())
280 schedule(sendResponseEvent, time);
281 } else {
282 // queue the packet for deletion
283 pendingDelete.reset(pkt);
284 }
285}
286
287void DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle)
288{
289 assert(cycle == divCeil(curTick() - startTick,
290 wrapper.clockPeriod() * SimClock::Int::ns));
291
292 DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr);
293
294 // get the outstanding reads for the address in question
295 auto p = outstandingReads.find(addr);
296 assert(p != outstandingReads.end());
297
298 // first in first out, which is not necessarily true, but it is
299 // the best we can do at this point
300 PacketPtr pkt = p->second.front();
301 p->second.pop();
302
303 if (p->second.empty())
304 outstandingReads.erase(p);
305
306 // no need to check for drain here as the next call will add a
307 // response to the response queue straight away
308 assert(nbrOutstandingReads != 0);
309 --nbrOutstandingReads;
310
311 // perform the actual memory access
312 accessAndRespond(pkt);
313}
314
315void DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
316{
317 assert(cycle == divCeil(curTick() - startTick,
318 wrapper.clockPeriod() * SimClock::Int::ns));
319
320 DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr);
321
322 // get the outstanding reads for the address in question
323 auto p = outstandingWrites.find(addr);
324 assert(p != outstandingWrites.end());
325
326 // we have already responded, and this is only to keep track of
327 // what is outstanding
328 p->second.pop();
329 if (p->second.empty())
330 outstandingWrites.erase(p);
331
332 assert(nbrOutstandingWrites != 0);
333 --nbrOutstandingWrites;
334
335 if (nbrOutstanding() == 0)
336 signalDrainDone();
337}
338
339Port &
340DRAMSim2::getPort(const std::string &if_name, PortID idx)
341{
342 if (if_name != "port") {
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 * Authors: Andreas Hansson
38 */
39
40#include "mem/dramsim2.hh"
41
42#include "DRAMSim2/Callback.h"
43#include "base/callback.hh"
44#include "base/trace.hh"
45#include "debug/DRAMSim2.hh"
46#include "debug/Drain.hh"
47#include "sim/system.hh"
48
49DRAMSim2::DRAMSim2(const Params* p) :
50 AbstractMemory(p),
51 port(name() + ".port", *this),
52 wrapper(p->deviceConfigFile, p->systemConfigFile, p->filePath,
53 p->traceFile, p->range.size() / 1024 / 1024, p->enableDebug),
54 retryReq(false), retryResp(false), startTick(0),
55 nbrOutstandingReads(0), nbrOutstandingWrites(0),
56 sendResponseEvent([this]{ sendResponse(); }, name()),
57 tickEvent([this]{ tick(); }, name())
58{
59 DPRINTF(DRAMSim2,
60 "Instantiated DRAMSim2 with clock %d ns and queue size %d\n",
61 wrapper.clockPeriod(), wrapper.queueSize());
62
63 DRAMSim::TransactionCompleteCB* read_cb =
64 new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
65 this, &DRAMSim2::readComplete);
66 DRAMSim::TransactionCompleteCB* write_cb =
67 new DRAMSim::Callback<DRAMSim2, void, unsigned, uint64_t, uint64_t>(
68 this, &DRAMSim2::writeComplete);
69 wrapper.setCallbacks(read_cb, write_cb);
70
71 // Register a callback to compensate for the destructor not
72 // being called. The callback prints the DRAMSim2 stats.
73 Callback* cb = new MakeCallback<DRAMSim2Wrapper,
74 &DRAMSim2Wrapper::printStats>(wrapper);
75 registerExitCallback(cb);
76}
77
78void
79DRAMSim2::init()
80{
81 AbstractMemory::init();
82
83 if (!port.isConnected()) {
84 fatal("DRAMSim2 %s is unconnected!\n", name());
85 } else {
86 port.sendRangeChange();
87 }
88
89 if (system()->cacheLineSize() != wrapper.burstSize())
90 fatal("DRAMSim2 burst size %d does not match cache line size %d\n",
91 wrapper.burstSize(), system()->cacheLineSize());
92}
93
94void
95DRAMSim2::startup()
96{
97 startTick = curTick();
98
99 // kick off the clock ticks
100 schedule(tickEvent, clockEdge());
101}
102
103void
104DRAMSim2::sendResponse()
105{
106 assert(!retryResp);
107 assert(!responseQueue.empty());
108
109 DPRINTF(DRAMSim2, "Attempting to send response\n");
110
111 bool success = port.sendTimingResp(responseQueue.front());
112 if (success) {
113 responseQueue.pop_front();
114
115 DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n",
116 nbrOutstandingReads, nbrOutstandingWrites,
117 responseQueue.size());
118
119 if (!responseQueue.empty() && !sendResponseEvent.scheduled())
120 schedule(sendResponseEvent, curTick());
121
122 if (nbrOutstanding() == 0)
123 signalDrainDone();
124 } else {
125 retryResp = true;
126
127 DPRINTF(DRAMSim2, "Waiting for response retry\n");
128
129 assert(!sendResponseEvent.scheduled());
130 }
131}
132
133unsigned int
134DRAMSim2::nbrOutstanding() const
135{
136 return nbrOutstandingReads + nbrOutstandingWrites + responseQueue.size();
137}
138
139void
140DRAMSim2::tick()
141{
142 wrapper.tick();
143
144 // is the connected port waiting for a retry, if so check the
145 // state and send a retry if conditions have changed
146 if (retryReq && nbrOutstanding() < wrapper.queueSize()) {
147 retryReq = false;
148 port.sendRetryReq();
149 }
150
151 schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns);
152}
153
154Tick
155DRAMSim2::recvAtomic(PacketPtr pkt)
156{
157 access(pkt);
158
159 // 50 ns is just an arbitrary value at this point
160 return pkt->cacheResponding() ? 0 : 50000;
161}
162
163void
164DRAMSim2::recvFunctional(PacketPtr pkt)
165{
166 pkt->pushLabel(name());
167
168 functionalAccess(pkt);
169
170 // potentially update the packets in our response queue as well
171 for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i)
172 pkt->trySatisfyFunctional(*i);
173
174 pkt->popLabel();
175}
176
177bool
178DRAMSim2::recvTimingReq(PacketPtr pkt)
179{
180 // if a cache is responding, sink the packet without further action
181 if (pkt->cacheResponding()) {
182 pendingDelete.reset(pkt);
183 return true;
184 }
185
186 // we should not get a new request after committing to retry the
187 // current one, but unfortunately the CPU violates this rule, so
188 // simply ignore it for now
189 if (retryReq)
190 return false;
191
192 // if we cannot accept we need to send a retry once progress can
193 // be made
194 bool can_accept = nbrOutstanding() < wrapper.queueSize();
195
196 // keep track of the transaction
197 if (pkt->isRead()) {
198 if (can_accept) {
199 outstandingReads[pkt->getAddr()].push(pkt);
200
201 // we count a transaction as outstanding until it has left the
202 // queue in the controller, and the response has been sent
203 // back, note that this will differ for reads and writes
204 ++nbrOutstandingReads;
205 }
206 } else if (pkt->isWrite()) {
207 if (can_accept) {
208 outstandingWrites[pkt->getAddr()].push(pkt);
209
210 ++nbrOutstandingWrites;
211
212 // perform the access for writes
213 accessAndRespond(pkt);
214 }
215 } else {
216 // keep it simple and just respond if necessary
217 accessAndRespond(pkt);
218 return true;
219 }
220
221 if (can_accept) {
222 // we should never have a situation when we think there is space,
223 // and there isn't
224 assert(wrapper.canAccept());
225
226 DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr());
227
228 // @todo what about the granularity here, implicit assumption that
229 // a transaction matches the burst size of the memory (which we
230 // cannot determine without parsing the ini file ourselves)
231 wrapper.enqueue(pkt->isWrite(), pkt->getAddr());
232
233 return true;
234 } else {
235 retryReq = true;
236 return false;
237 }
238}
239
240void
241DRAMSim2::recvRespRetry()
242{
243 DPRINTF(DRAMSim2, "Retrying\n");
244
245 assert(retryResp);
246 retryResp = false;
247 sendResponse();
248}
249
250void
251DRAMSim2::accessAndRespond(PacketPtr pkt)
252{
253 DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr());
254
255 bool needsResponse = pkt->needsResponse();
256
257 // do the actual memory access which also turns the packet into a
258 // response
259 access(pkt);
260
261 // turn packet around to go back to requester if response expected
262 if (needsResponse) {
263 // access already turned the packet into a response
264 assert(pkt->isResponse());
265 // Here we pay for xbar additional delay and to process the payload
266 // of the packet.
267 Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay;
268 // Reset the timings of the packet
269 pkt->headerDelay = pkt->payloadDelay = 0;
270
271 DPRINTF(DRAMSim2, "Queuing response for address %lld\n",
272 pkt->getAddr());
273
274 // queue it to be sent back
275 responseQueue.push_back(pkt);
276
277 // if we are not already waiting for a retry, or are scheduled
278 // to send a response, schedule an event
279 if (!retryResp && !sendResponseEvent.scheduled())
280 schedule(sendResponseEvent, time);
281 } else {
282 // queue the packet for deletion
283 pendingDelete.reset(pkt);
284 }
285}
286
287void DRAMSim2::readComplete(unsigned id, uint64_t addr, uint64_t cycle)
288{
289 assert(cycle == divCeil(curTick() - startTick,
290 wrapper.clockPeriod() * SimClock::Int::ns));
291
292 DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr);
293
294 // get the outstanding reads for the address in question
295 auto p = outstandingReads.find(addr);
296 assert(p != outstandingReads.end());
297
298 // first in first out, which is not necessarily true, but it is
299 // the best we can do at this point
300 PacketPtr pkt = p->second.front();
301 p->second.pop();
302
303 if (p->second.empty())
304 outstandingReads.erase(p);
305
306 // no need to check for drain here as the next call will add a
307 // response to the response queue straight away
308 assert(nbrOutstandingReads != 0);
309 --nbrOutstandingReads;
310
311 // perform the actual memory access
312 accessAndRespond(pkt);
313}
314
315void DRAMSim2::writeComplete(unsigned id, uint64_t addr, uint64_t cycle)
316{
317 assert(cycle == divCeil(curTick() - startTick,
318 wrapper.clockPeriod() * SimClock::Int::ns));
319
320 DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr);
321
322 // get the outstanding reads for the address in question
323 auto p = outstandingWrites.find(addr);
324 assert(p != outstandingWrites.end());
325
326 // we have already responded, and this is only to keep track of
327 // what is outstanding
328 p->second.pop();
329 if (p->second.empty())
330 outstandingWrites.erase(p);
331
332 assert(nbrOutstandingWrites != 0);
333 --nbrOutstandingWrites;
334
335 if (nbrOutstanding() == 0)
336 signalDrainDone();
337}
338
339Port &
340DRAMSim2::getPort(const std::string &if_name, PortID idx)
341{
342 if (if_name != "port") {
343 return MemObject::getPort(if_name, idx);
343 return AbstractMemory::getPort(if_name, idx);
344 } else {
345 return port;
346 }
347}
348
349DrainState
350DRAMSim2::drain()
351{
352 // check our outstanding reads and writes and if any they need to
353 // drain
354 return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained;
355}
356
357DRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
358 DRAMSim2& _memory)
359 : SlavePort(_name, &_memory), memory(_memory)
360{ }
361
362AddrRangeList
363DRAMSim2::MemoryPort::getAddrRanges() const
364{
365 AddrRangeList ranges;
366 ranges.push_back(memory.getAddrRange());
367 return ranges;
368}
369
370Tick
371DRAMSim2::MemoryPort::recvAtomic(PacketPtr pkt)
372{
373 return memory.recvAtomic(pkt);
374}
375
376void
377DRAMSim2::MemoryPort::recvFunctional(PacketPtr pkt)
378{
379 memory.recvFunctional(pkt);
380}
381
382bool
383DRAMSim2::MemoryPort::recvTimingReq(PacketPtr pkt)
384{
385 // pass it to the memory controller
386 return memory.recvTimingReq(pkt);
387}
388
389void
390DRAMSim2::MemoryPort::recvRespRetry()
391{
392 memory.recvRespRetry();
393}
394
395DRAMSim2*
396DRAMSim2Params::create()
397{
398 return new DRAMSim2(this);
399}
344 } else {
345 return port;
346 }
347}
348
349DrainState
350DRAMSim2::drain()
351{
352 // check our outstanding reads and writes and if any they need to
353 // drain
354 return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained;
355}
356
357DRAMSim2::MemoryPort::MemoryPort(const std::string& _name,
358 DRAMSim2& _memory)
359 : SlavePort(_name, &_memory), memory(_memory)
360{ }
361
362AddrRangeList
363DRAMSim2::MemoryPort::getAddrRanges() const
364{
365 AddrRangeList ranges;
366 ranges.push_back(memory.getAddrRange());
367 return ranges;
368}
369
370Tick
371DRAMSim2::MemoryPort::recvAtomic(PacketPtr pkt)
372{
373 return memory.recvAtomic(pkt);
374}
375
376void
377DRAMSim2::MemoryPort::recvFunctional(PacketPtr pkt)
378{
379 memory.recvFunctional(pkt);
380}
381
382bool
383DRAMSim2::MemoryPort::recvTimingReq(PacketPtr pkt)
384{
385 // pass it to the memory controller
386 return memory.recvTimingReq(pkt);
387}
388
389void
390DRAMSim2::MemoryPort::recvRespRetry()
391{
392 memory.recvRespRetry();
393}
394
395DRAMSim2*
396DRAMSim2Params::create()
397{
398 return new DRAMSim2(this);
399}