gem5  v20.1.0.0
simple_mem.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2013, 2015 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  * Copyright (c) 2001-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #include "mem/simple_mem.hh"
42 
43 #include "base/random.hh"
44 #include "base/trace.hh"
45 #include "debug/Drain.hh"
46 
47 SimpleMemory::SimpleMemory(const SimpleMemoryParams* p) :
49  port(name() + ".port", *this), latency(p->latency),
50  latency_var(p->latency_var), bandwidth(p->bandwidth), isBusy(false),
51  retryReq(false), retryResp(false),
52  releaseEvent([this]{ release(); }, name()),
53  dequeueEvent([this]{ dequeue(); }, name())
54 {
55 }
56 
57 void
59 {
61 
62  // allow unconnected memories as this is used in several ruby
63  // systems at the moment
64  if (port.isConnected()) {
66  }
67 }
68 
69 Tick
71 {
72  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
73  "is responding");
74 
75  access(pkt);
76  return getLatency();
77 }
78 
79 Tick
81 {
82  Tick latency = recvAtomic(pkt);
83 
84  if (backdoor.ptr())
85  _backdoor = &backdoor;
86  return latency;
87 }
88 
89 void
91 {
92  pkt->pushLabel(name());
93 
94  functionalAccess(pkt);
95 
96  bool done = false;
97  auto p = packetQueue.begin();
98  // potentially update the packets in our packet queue as well
99  while (!done && p != packetQueue.end()) {
100  done = pkt->trySatisfyFunctional(p->pkt);
101  ++p;
102  }
103 
104  pkt->popLabel();
105 }
106 
107 bool
109 {
110  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
111  "is responding");
112 
113  panic_if(!(pkt->isRead() || pkt->isWrite()),
114  "Should only see read and writes at memory controller, "
115  "saw %s to %#llx\n", pkt->cmdString(), pkt->getAddr());
116 
117  // we should not get a new request after committing to retry the
118  // current one, but unfortunately the CPU violates this rule, so
119  // simply ignore it for now
120  if (retryReq)
121  return false;
122 
123  // if we are busy with a read or write, remember that we have to
124  // retry
125  if (isBusy) {
126  retryReq = true;
127  return false;
128  }
129 
130  // technically the packet only reaches us after the header delay,
131  // and since this is a memory controller we also need to
132  // deserialise the payload before performing any write operation
133  Tick receive_delay = pkt->headerDelay + pkt->payloadDelay;
134  pkt->headerDelay = pkt->payloadDelay = 0;
135 
136  // update the release time according to the bandwidth limit, and
137  // do so with respect to the time it takes to finish this request
138  // rather than long term as it is the short term data rate that is
139  // limited for any real memory
140 
141  // calculate an appropriate tick to release to not exceed
142  // the bandwidth limit
143  Tick duration = pkt->getSize() * bandwidth;
144 
145  // only consider ourselves busy if there is any need to wait
146  // to avoid extra events being scheduled for (infinitely) fast
147  // memories
148  if (duration != 0) {
149  schedule(releaseEvent, curTick() + duration);
150  isBusy = true;
151  }
152 
153  // go ahead and deal with the packet and put the response in the
154  // queue if there is one
155  bool needsResponse = pkt->needsResponse();
156  recvAtomic(pkt);
157  // turn packet around to go back to requestor if response expected
158  if (needsResponse) {
159  // recvAtomic() should already have turned packet into
160  // atomic response
161  assert(pkt->isResponse());
162 
163  Tick when_to_send = curTick() + receive_delay + getLatency();
164 
165  // typically this should be added at the end, so start the
166  // insertion sort with the last element, also make sure not to
167  // re-order in front of some existing packet with the same
168  // address, the latter is important as this memory effectively
169  // hands out exclusive copies (shared is not asserted)
170  auto i = packetQueue.end();
171  --i;
172  while (i != packetQueue.begin() && when_to_send < i->tick &&
173  !i->pkt->matchAddr(pkt))
174  --i;
175 
176  // emplace inserts the element before the position pointed to by
177  // the iterator, so advance it one step
178  packetQueue.emplace(++i, pkt, when_to_send);
179 
180  if (!retryResp && !dequeueEvent.scheduled())
181  schedule(dequeueEvent, packetQueue.back().tick);
182  } else {
183  pendingDelete.reset(pkt);
184  }
185 
186  return true;
187 }
188 
189 void
191 {
192  assert(isBusy);
193  isBusy = false;
194  if (retryReq) {
195  retryReq = false;
196  port.sendRetryReq();
197  }
198 }
199 
200 void
202 {
203  assert(!packetQueue.empty());
204  DeferredPacket deferred_pkt = packetQueue.front();
205 
206  retryResp = !port.sendTimingResp(deferred_pkt.pkt);
207 
208  if (!retryResp) {
209  packetQueue.pop_front();
210 
211  // if the queue is not empty, schedule the next dequeue event,
212  // otherwise signal that we are drained if we were asked to do so
213  if (!packetQueue.empty()) {
214  // if there were packets that got in-between then we
215  // already have an event scheduled, so use re-schedule
217  std::max(packetQueue.front().tick, curTick()), true);
218  } else if (drainState() == DrainState::Draining) {
219  DPRINTF(Drain, "Draining of SimpleMemory complete\n");
220  signalDrainDone();
221  }
222  }
223 }
224 
225 Tick
227 {
228  return latency +
230 }
231 
232 void
234 {
235  assert(retryResp);
236 
237  dequeue();
238 }
239 
240 Port &
241 SimpleMemory::getPort(const std::string &if_name, PortID idx)
242 {
243  if (if_name != "port") {
244  return AbstractMemory::getPort(if_name, idx);
245  } else {
246  return port;
247  }
248 }
249 
252 {
253  if (!packetQueue.empty()) {
254  DPRINTF(Drain, "SimpleMemory Queue has requests, waiting to drain\n");
255  return DrainState::Draining;
256  } else {
257  return DrainState::Drained;
258  }
259 }
260 
261 SimpleMemory::MemoryPort::MemoryPort(const std::string& _name,
262  SimpleMemory& _memory)
263  : ResponsePort(_name, &_memory), memory(_memory)
264 { }
265 
268 {
269  AddrRangeList ranges;
270  ranges.push_back(memory.getAddrRange());
271  return ranges;
272 }
273 
274 Tick
276 {
277  return memory.recvAtomic(pkt);
278 }
279 
280 Tick
282  PacketPtr pkt, MemBackdoorPtr &_backdoor)
283 {
284  return memory.recvAtomicBackdoor(pkt, _backdoor);
285 }
286 
287 void
289 {
290  memory.recvFunctional(pkt);
291 }
292 
293 bool
295 {
296  return memory.recvTimingReq(pkt);
297 }
298 
299 void
301 {
302  memory.recvRespRetry();
303 }
304 
306 SimpleMemoryParams::create()
307 {
308  return new SimpleMemory(this);
309 }
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
SimpleMemory::packetQueue
std::list< DeferredPacket > packetQueue
Internal (unbounded) storage to mimic the delay caused by the actual memory access.
Definition: simple_mem.hh:118
ResponsePort
A ResponsePort is a specialization of a port.
Definition: port.hh:265
Packet::isResponse
bool isResponse() const
Definition: packet.hh:560
MemBackdoor
Definition: backdoor.hh:38
SimpleMemory::dequeueEvent
EventFunctionWrapper dequeueEvent
Definition: simple_mem.hh:159
SimpleMemory::MemoryPort::recvAtomic
Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
Definition: simple_mem.cc:275
SimpleMemory::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: simple_mem.cc:241
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:619
SimpleMemory::port
MemoryPort port
Definition: simple_mem.hh:100
SimpleMemory::release
void release()
Release the memory after being busy and send a retry if a request was rejected in the meanwhile.
Definition: simple_mem.cc:190
SimpleMemory::getLatency
Tick getLatency() const
Detemine the latency.
Definition: simple_mem.cc:226
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
SimpleMemory::recvRespRetry
void recvRespRetry()
Definition: simple_mem.cc:233
SimpleMemory::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: simple_mem.cc:70
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
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1023
SimpleMemory::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: simple_mem.cc:90
Clocked::tick
Tick tick
Definition: clocked_object.hh:65
SimpleMemory
The simple memory is a basic single-ported memory controller with a configurable throughput and laten...
Definition: simple_mem.hh:61
random.hh
Packet::isRead
bool isRead() const
Definition: packet.hh:556
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
SimpleMemory::MemoryPort::recvTimingReq
bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
Definition: simple_mem.cc:294
Packet::pushLabel
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1393
SimpleMemory::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: simple_mem.cc:108
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
SimpleMemory::drain
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: simple_mem.cc:251
SimpleMemory::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: simple_mem.cc:58
Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:394
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
SimpleMemory::retryResp
bool retryResp
Remember if we failed to send a response and are awaiting a retry.
Definition: simple_mem.hh:143
DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
SimpleMemory::DeferredPacket::pkt
const PacketPtr pkt
Definition: simple_mem.hh:76
DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:71
SimpleMemory::recvAtomicBackdoor
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor)
Definition: simple_mem.cc:80
AbstractMemory
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Definition: abstract_mem.hh:104
random_mt
Random random_mt
Definition: random.cc:96
SimpleMemory::MemoryPort::recvRespRetry
void recvRespRetry() override
Called by the peer if sendTimingResp was called on this protocol (causing recvTimingResp to be called...
Definition: simple_mem.cc:300
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
SimpleMemory::releaseEvent
EventFunctionWrapper releaseEvent
Definition: simple_mem.hh:151
AbstractMemory::access
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
Definition: abstract_mem.cc:373
SimpleMemory::dequeue
void dequeue()
Dequeue a packet from our internal packet queue and move it to the port where it will be sent as soon...
Definition: simple_mem.cc:201
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
SimpleMemory::SimpleMemory
SimpleMemory(const SimpleMemoryParams *p)
Definition: simple_mem.cc:47
SimpleMemory::retryReq
bool retryReq
Remember if we have to retry an outstanding request that arrived while we were busy.
Definition: simple_mem.hh:137
Packet::cmdString
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:551
MemBackdoor::ptr
uint8_t * ptr() const
Definition: backdoor.hh:58
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
SimpleMemory::DeferredPacket
A deferred packet stores a packet along with its scheduled transmission time.
Definition: simple_mem.hh:70
Drainable::signalDrainDone
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:301
SimpleMemory::isBusy
bool isBusy
Track the state of the memory as either idle or busy, no need for an enum with only two states.
Definition: simple_mem.hh:131
SimpleMemory::MemoryPort::getAddrRanges
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition: simple_mem.cc:267
SimpleMemory::bandwidth
const double bandwidth
Bandwidth in ticks per byte.
Definition: simple_mem.hh:125
name
const std::string & name()
Definition: trace.cc:50
SimpleMemory::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: simple_mem.hh:172
Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:320
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
SimpleMemory::MemoryPort::recvAtomicBackdoor
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor) override
Default implementations.
Definition: simple_mem.cc:281
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:197
SimpleMemory::MemoryPort::recvFunctional
void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
Definition: simple_mem.cc:288
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
Port::isConnected
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:128
SimpleMemory::latency_var
const Tick latency_var
Fudge factor added to the latency.
Definition: simple_mem.hh:111
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
Random::random
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:86
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::backdoor
MemBackdoor backdoor
Definition: abstract_mem.hh:115
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
SimpleMemory::latency
const Tick latency
Latency from that a request is accepted until the response is ready to be sent.
Definition: simple_mem.hh:106
Packet::popLabel
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
Definition: packet.hh:1403
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
SimpleMemory::MemoryPort::MemoryPort
MemoryPort(const std::string &_name, SimpleMemory &_memory)
Definition: simple_mem.cc:261
simple_mem.hh
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

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