gem5  v20.1.0.0
noncoherent_cache.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2018 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) 2002-2005 The Regents of The University of Michigan
15  * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
48 
49 #include <cassert>
50 
51 #include "base/logging.hh"
52 #include "base/trace.hh"
53 #include "base/types.hh"
54 #include "debug/Cache.hh"
55 #include "mem/cache/cache_blk.hh"
56 #include "mem/cache/mshr.hh"
57 #include "params/NoncoherentCache.hh"
58 
59 NoncoherentCache::NoncoherentCache(const NoncoherentCacheParams *p)
60  : BaseCache(p, p->system->cacheLineSize())
61 {
62 }
63 
64 void
66 {
67  // As this a non-coherent cache located below the point of
68  // coherency, we do not expect requests that are typically used to
69  // keep caches coherent (e.g., InvalidateReq or UpdateReq).
70  assert(pkt->isRead() || pkt->isWrite());
71  BaseCache::satisfyRequest(pkt, blk);
72 }
73 
74 bool
76  PacketList &writebacks)
77 {
78  bool success = BaseCache::access(pkt, blk, lat, writebacks);
79 
80  if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) {
81  assert(blk && blk->isValid());
82  // Writeback and WriteClean can allocate and fill even if the
83  // referenced block was not present or it was invalid. If that
84  // is the case, make sure that the new block is marked as
85  // writable
86  blk->status |= BlkWritable;
87  }
88 
89  return success;
90 }
91 
92 void
94 {
95  while (!writebacks.empty()) {
96  PacketPtr wb_pkt = writebacks.front();
97  allocateWriteBuffer(wb_pkt, forward_time);
98  writebacks.pop_front();
99  }
100 }
101 
102 void
104 {
105  while (!writebacks.empty()) {
106  PacketPtr wb_pkt = writebacks.front();
107  memSidePort.sendAtomic(wb_pkt);
108  writebacks.pop_front();
109  delete wb_pkt;
110  }
111 }
112 
113 void
115  Tick forward_time, Tick request_time)
116 {
117  // miss
118  Addr blk_addr = pkt->getBlockAddr(blkSize);
119  MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false);
120 
121  // We can always write to a non coherent cache if the block is
122  // present and therefore if we have reached this point then the
123  // block should not be in the cache.
124  assert(mshr || !blk || !blk->isValid());
125 
126  BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
127 }
128 
129 void
131 {
132  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
133  "is responding");
134 
135  panic_if(!(pkt->isRead() || pkt->isWrite()),
136  "Should only see read and writes at non-coherent cache\n");
137 
139 }
140 
141 PacketPtr
143  bool needs_writable,
144  bool is_whole_line_write) const
145 {
146  // We also fill for writebacks from the coherent caches above us,
147  // and they do not need responses
148  assert(cpu_pkt->needsResponse());
149 
150  // A miss can happen only due to missing block
151  assert(!blk || !blk->isValid());
152 
153  PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize);
154 
155  // the packet should be block aligned
156  assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
157 
158  pkt->allocate();
159  DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(),
160  cpu_pkt->print());
161  return pkt;
162 }
163 
164 
165 Cycles
167  PacketList &writebacks)
168 {
169  PacketPtr bus_pkt = createMissPacket(pkt, blk, true,
170  pkt->isWholeLineWrite(blkSize));
171  DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print());
172 
173  Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
174 
175  assert(bus_pkt->isResponse());
176  // At the moment the only supported downstream requests we issue
177  // are ReadReq and therefore here we should only see the
178  // corresponding responses
179  assert(bus_pkt->isRead());
180  assert(pkt->cmd != MemCmd::UpgradeResp);
181  assert(!bus_pkt->isInvalidate());
182  assert(!bus_pkt->hasSharers());
183 
184  // We are now dealing with the response handling
185  DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print());
186 
187  if (!bus_pkt->isError()) {
188  // Any reponse that does not have an error should be filling,
189  // afterall it is a read response
190  DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
191  bus_pkt->getAddr());
192  blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd));
193  assert(blk);
194  }
195  satisfyRequest(pkt, blk);
196 
197  maintainClusivity(true, blk);
198 
199  // Use the separate bus_pkt to generate response to pkt and
200  // then delete it.
201  if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) {
202  assert(pkt->needsResponse());
203  pkt->makeAtomicResponse();
204  if (bus_pkt->isError()) {
205  pkt->copyError(bus_pkt);
206  }
207  }
208 
209  delete bus_pkt;
210 
211  return latency;
212 }
213 
214 Tick
216 {
217  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
218  "is responding");
219 
220  panic_if(!(pkt->isRead() || pkt->isWrite()),
221  "Should only see read and writes at non-coherent cache\n");
222 
223  return BaseCache::recvAtomic(pkt);
224 }
225 
226 
227 void
229 {
230  panic_if(!from_cpu_side, "Non-coherent cache received functional snoop"
231  " request\n");
232 
233  BaseCache::functionalAccess(pkt, from_cpu_side);
234 }
235 
236 void
238  CacheBlk *blk)
239 {
240  // First offset for critical word first calculations
241  const int initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
242 
243  MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
244  for (auto &target: targets) {
245  Packet *tgt_pkt = target.pkt;
246 
247  switch (target.source) {
249  // handle deferred requests comming from a cache or core
250  // above
251 
252  Tick completion_time;
253  // Here we charge on completion_time the delay of the xbar if the
254  // packet comes from it, charged on headerDelay.
255  completion_time = pkt->headerDelay;
256 
257  satisfyRequest(tgt_pkt, blk);
258 
259  // How many bytes past the first request is this one
260  int transfer_offset;
261  transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset;
262  if (transfer_offset < 0) {
263  transfer_offset += blkSize;
264  }
265  // If not critical word (offset) return payloadDelay.
266  // responseLatency is the latency of the return path
267  // from lower level caches/memory to an upper level cache or
268  // the core.
269  completion_time += clockEdge(responseLatency) +
270  (transfer_offset ? pkt->payloadDelay : 0);
271 
272  assert(tgt_pkt->req->requestorId() < system->maxRequestors());
273  stats.cmdStats(tgt_pkt).missLatency[tgt_pkt->req->requestorId()] +=
274  completion_time - target.recvTime;
275 
276  tgt_pkt->makeTimingResponse();
277  if (pkt->isError())
278  tgt_pkt->copyError(pkt);
279 
280  // Reset the bus additional time as it is now accounted for
281  tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
282  cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
283  break;
284 
286  // handle deferred requests comming from a prefetcher
287  // attached to this cache
288  assert(tgt_pkt->cmd == MemCmd::HardPFReq);
289 
290  if (blk)
291  blk->status |= BlkHWPrefetched;
292 
293  // We have filled the block and the prefetcher does not
294  // require responses.
295  delete tgt_pkt;
296  break;
297 
298  default:
299  // we should never see FromSnoop Targets as this is a
300  // non-coherent cache
301  panic("Illegal target->source enum %d\n", target.source);
302  }
303  }
304 
305  // Reponses are filling and bring in writable blocks, therefore
306  // there should be no deferred targets and all the non-deferred
307  // targets are now serviced.
308  assert(mshr->getNumTargets() == 0);
309 }
310 
311 void
313 {
314  assert(pkt->isResponse());
315  // At the moment the only supported downstream requests we issue
316  // are ReadReq and therefore here we should only see the
317  // corresponding responses
318  assert(pkt->isRead());
319  assert(pkt->cmd != MemCmd::UpgradeResp);
320  assert(!pkt->isInvalidate());
321  // This cache is non-coherent and any memories below are
322  // non-coherent too (non-coherent caches or the main memory),
323  // therefore the fetched block can be marked as writable.
324  assert(!pkt->hasSharers());
325 
327 }
328 
329 PacketPtr
331 {
332  // A dirty block is always written back.
333 
334  // A clean block can we written back, if we turned on writebacks
335  // for clean blocks. This could be useful if there is a cache
336  // below and we want to make sure the block is cached but if the
337  // memory below is the main memory WritebackCleans are
338  // unnecessary.
339 
340  // If we clean writebacks are not enabled, we do not take any
341  // further action for evictions of clean blocks (i.e., CleanEvicts
342  // are unnecessary).
343  PacketPtr pkt = (blk->isDirty() || writebackClean) ?
344  writebackBlk(blk) : nullptr;
345 
346  invalidateBlock(blk);
347 
348  return pkt;
349 }
350 
352 NoncoherentCacheParams::create()
353 {
354  assert(tags);
355  assert(replacement_policy);
356 
357  return new NoncoherentCache(this);
358 }
MSHR::Target::FromPrefetcher
@ FromPrefetcher
Definition: mshr.hh:130
Packet::isError
bool isError() const
Definition: packet.hh:583
MSHR::Target::FromCPU
@ FromCPU
Definition: mshr.hh:128
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1016
BaseCache::maintainClusivity
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
Definition: base.cc:1294
Packet::isResponse
bool isResponse() const
Definition: packet.hh:560
Packet::makeTimingResponse
void makeTimingResponse()
Definition: packet.hh:1022
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:619
BaseCache::functionalAccess
virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side)
Performs the access specified by the request.
Definition: base.cc:620
Packet::hasSharers
bool hasSharers() const
Definition: packet.hh:646
NoncoherentCache::evictBlock
M5_NODISCARD PacketPtr evictBlock(CacheBlk *blk) override
Evict a cache block.
Definition: noncoherent_cache.cc:330
BaseCache::handleFill
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
Definition: base.cc:1306
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
MemCmd::HardPFReq
@ HardPFReq
Definition: packet.hh:94
BaseCache::writebackBlk
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
Definition: base.cc:1486
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
BaseCache::system
System * system
System we are currently operating in.
Definition: base.hh:921
mshr.hh
MSHR::getNumTargets
int getNumTargets() const
Returns the current number of allocated targets.
Definition: mshr.hh:422
BaseCache::blkSize
const unsigned blkSize
Block size of this cache.
Definition: base.hh:839
NoncoherentCache::NoncoherentCache
NoncoherentCache(const NoncoherentCacheParams *p)
Definition: noncoherent_cache.cc:59
Packet::isRead
bool isRead() const
Definition: packet.hh:556
MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:82
BaseCache::CacheCmdStats::missLatency
Stats::Vector missLatency
Total number of cycles per thread/command spent waiting for a miss.
Definition: base.hh:947
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
BaseCache::memSidePort
MemSidePort memSidePort
Definition: base.hh:309
Packet::isInvalidate
bool isInvalidate() const
Definition: packet.hh:571
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
NoncoherentCache::serviceMSHRTargets
void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk) override
Service non-deferred MSHR targets using the received response.
Definition: noncoherent_cache.cc:237
QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:90
NoncoherentCache
A non-coherent cache.
Definition: noncoherent_cache.hh:64
NoncoherentCache::access
bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks) override
Does all the processing necessary to perform the provided request.
Definition: noncoherent_cache.cc:75
Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:394
MSHR::extractServiceableTargets
TargetList extractServiceableTargets(PacketPtr pkt)
Extracts the subset of the targets that can be serviced given a received response.
Definition: mshr.cc:536
Packet::print
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:389
Packet::isSecure
bool isSecure() const
Definition: packet.hh:783
QueueEntry::Target::pkt
const PacketPtr pkt
Pending request packet.
Definition: queue_entry.hh:88
Packet::copyError
void copyError(Packet *pkt)
Definition: packet.hh:752
NoncoherentCache::recvTimingReq
void recvTimingReq(PacketPtr pkt) override
Performs the access specified by the request.
Definition: noncoherent_cache.cc:130
NoncoherentCache::satisfyRequest
void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false) override
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
Definition: noncoherent_cache.cc:65
X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:997
NoncoherentCache::createMissPacket
PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const override
Create an appropriate downstream bus request packet.
Definition: noncoherent_cache.cc:142
BaseCache::allocateWriteBuffer
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Definition: base.hh:1115
Packet::isWholeLineWrite
bool isWholeLineWrite(unsigned blk_size)
Definition: packet.hh:587
BaseCache::mshrQueue
MSHRQueue mshrQueue
Miss status registers.
Definition: base.hh:314
CacheBlk::isDirty
bool isDirty() const
Check to see if a block has been written.
Definition: cache_blk.hh:226
BaseCache::cpuSidePort
CpuSidePort cpuSidePort
Definition: base.hh:308
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
BaseCache::allocOnFill
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
Definition: base.hh:404
BaseCache::stats
BaseCache::CacheStats stats
Packet::getBlockAddr
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:778
BaseCache::invalidateBlock
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
Definition: base.cc:1460
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
BaseCache::recvTimingReq
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:334
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
CacheBlk::status
State status
The current status of this block.
Definition: cache_blk.hh:105
noncoherent_cache.hh
BaseCache::access
virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks)
Does all the processing necessary to perform the provided request.
Definition: base.cc:1030
Packet::getOffset
Addr getOffset(unsigned int blk_size) const
Definition: packet.hh:773
Queue::findMatch
Entry * findMatch(Addr blk_addr, bool is_secure, bool ignore_uncacheable=true) const
Find the first entry that matches the provided address.
Definition: queue.hh:162
MSHR::TargetList
Definition: mshr.hh:162
BaseCache
A basic cache interface.
Definition: base.hh:89
BlkHWPrefetched
@ BlkHWPrefetched
block was a hardware prefetch yet unaccessed
Definition: cache_blk.hh:73
ProbePoints::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:103
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
BaseCache::satisfyRequest
virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false)
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
Definition: base.cc:904
MSHR::getTarget
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
Definition: mshr.hh:449
NoncoherentCache::handleTimingReqMiss
void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time) override
Definition: noncoherent_cache.cc:114
BaseCache::writebackClean
const bool writebackClean
Determine if clean lines should be written back or not.
Definition: base.hh:626
Packet::cmd
MemCmd cmd
The command field of the packet.
Definition: packet.hh:335
CacheBlk::isValid
bool isValid() const
Checks that a block is valid.
Definition: cache_blk.hh:203
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
BlkWritable
@ BlkWritable
write permission
Definition: cache_blk.hh:67
NoncoherentCache::recvTimingResp
void recvTimingResp(PacketPtr pkt) override
Handles a response (cache line fill/write ack) from the bus.
Definition: noncoherent_cache.cc:312
NoncoherentCache::doWritebacksAtomic
void doWritebacksAtomic(PacketList &writebacks) override
Send writebacks down the memory hierarchy in atomic mode.
Definition: noncoherent_cache.cc:103
cache_blk.hh
CacheBlk
A Basic Cache block.
Definition: cache_blk.hh:84
System::maxRequestors
RequestorID maxRequestors()
Get the number of requestors registered in the system.
Definition: system.hh:503
types.hh
Clocked::ticksToCycles
Cycles ticksToCycles(Tick t) const
Definition: clocked_object.hh:219
BaseCache::handleTimingReqMiss
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
NoncoherentCache::functionalAccess
void functionalAccess(PacketPtr pkt, bool from_cpu_side) override
Performs the access specified by the request.
Definition: noncoherent_cache.cc:228
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
Packet::isWrite
bool isWrite() const
Definition: packet.hh:557
trace.hh
NoncoherentCache::handleAtomicReqMiss
Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks) override
Handle a request in atomic mode that missed in this cache.
Definition: noncoherent_cache.cc:166
BaseCache::responseLatency
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
Definition: base.hh:868
MemCmd::WriteClean
@ WriteClean
Definition: packet.hh:90
NoncoherentCache::doWritebacks
void doWritebacks(PacketList &writebacks, Tick forward_time) override
Insert writebacks into the write buffer.
Definition: noncoherent_cache.cc:93
BaseCache::recvTimingResp
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
Definition: base.cc:402
RequestPort::sendAtomic
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
Definition: port.hh:461
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
std::list
STL list class.
Definition: stl.hh:51
Packet::isWriteback
bool isWriteback() const
Definition: packet.hh:575
Packet::allocate
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1299
Cache
A coherent cache that can be arranged in flexible topologies.
Definition: cache.hh:63
BaseCache::recvAtomic
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:540
BaseCache::CacheStats::cmdStats
CacheCmdStats & cmdStats(const PacketPtr p)
Definition: base.hh:978
MemCmd::UpgradeResp
@ UpgradeResp
Definition: packet.hh:100
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
MSHR
Miss Status and handling Register.
Definition: mshr.hh:69
NoncoherentCache::recvAtomic
Tick recvAtomic(PacketPtr pkt) override
Performs the access specified by the request.
Definition: noncoherent_cache.cc:215

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