gem5  v21.0.1.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  assert(p.tags);
63  assert(p.replacement_policy);
64 }
65 
66 void
68 {
69  // As this a non-coherent cache located below the point of
70  // coherency, we do not expect requests that are typically used to
71  // keep caches coherent (e.g., InvalidateReq or UpdateReq).
72  assert(pkt->isRead() || pkt->isWrite());
73  BaseCache::satisfyRequest(pkt, blk);
74 }
75 
76 bool
78  PacketList &writebacks)
79 {
80  bool success = BaseCache::access(pkt, blk, lat, writebacks);
81 
82  if (pkt->isWriteback() || pkt->cmd == MemCmd::WriteClean) {
83  assert(blk && blk->isValid());
84  // Writeback and WriteClean can allocate and fill even if the
85  // referenced block was not present or it was invalid. If that
86  // is the case, make sure that the new block is marked as
87  // writable
89  }
90 
91  return success;
92 }
93 
94 void
96 {
97  while (!writebacks.empty()) {
98  PacketPtr wb_pkt = writebacks.front();
99  allocateWriteBuffer(wb_pkt, forward_time);
100  writebacks.pop_front();
101  }
102 }
103 
104 void
106 {
107  while (!writebacks.empty()) {
108  PacketPtr wb_pkt = writebacks.front();
109  memSidePort.sendAtomic(wb_pkt);
110  writebacks.pop_front();
111  delete wb_pkt;
112  }
113 }
114 
115 void
117  Tick forward_time, Tick request_time)
118 {
119  // miss
120  Addr blk_addr = pkt->getBlockAddr(blkSize);
121  MSHR *mshr = mshrQueue.findMatch(blk_addr, pkt->isSecure(), false);
122 
123  // We can always write to a non coherent cache if the block is
124  // present and therefore if we have reached this point then the
125  // block should not be in the cache.
126  assert(mshr || !blk || !blk->isValid());
127 
128  BaseCache::handleTimingReqMiss(pkt, mshr, blk, forward_time, request_time);
129 }
130 
131 void
133 {
134  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
135  "is responding");
136 
137  panic_if(!(pkt->isRead() || pkt->isWrite()),
138  "Should only see read and writes at non-coherent cache\n");
139 
141 }
142 
143 PacketPtr
145  bool needs_writable,
146  bool is_whole_line_write) const
147 {
148  // We also fill for writebacks from the coherent caches above us,
149  // and they do not need responses
150  assert(cpu_pkt->needsResponse());
151 
152  // A miss can happen only due to missing block
153  assert(!blk || !blk->isValid());
154 
155  PacketPtr pkt = new Packet(cpu_pkt->req, MemCmd::ReadReq, blkSize);
156 
157  // the packet should be block aligned
158  assert(pkt->getAddr() == pkt->getBlockAddr(blkSize));
159 
160  pkt->allocate();
161  DPRINTF(Cache, "%s created %s from %s\n", __func__, pkt->print(),
162  cpu_pkt->print());
163  return pkt;
164 }
165 
166 
167 Cycles
169  PacketList &writebacks)
170 {
171  PacketPtr bus_pkt = createMissPacket(pkt, blk, true,
172  pkt->isWholeLineWrite(blkSize));
173  DPRINTF(Cache, "Sending an atomic %s\n", bus_pkt->print());
174 
175  Cycles latency = ticksToCycles(memSidePort.sendAtomic(bus_pkt));
176 
177  assert(bus_pkt->isResponse());
178  // At the moment the only supported downstream requests we issue
179  // are ReadReq and therefore here we should only see the
180  // corresponding responses
181  assert(bus_pkt->isRead());
182  assert(pkt->cmd != MemCmd::UpgradeResp);
183  assert(!bus_pkt->isInvalidate());
184  assert(!bus_pkt->hasSharers());
185 
186  // We are now dealing with the response handling
187  DPRINTF(Cache, "Receive response: %s\n", bus_pkt->print());
188 
189  if (!bus_pkt->isError()) {
190  // Any reponse that does not have an error should be filling,
191  // afterall it is a read response
192  DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
193  bus_pkt->getAddr());
194  blk = handleFill(bus_pkt, blk, writebacks, allocOnFill(bus_pkt->cmd));
195  assert(blk);
196  }
197  satisfyRequest(pkt, blk);
198 
199  maintainClusivity(true, blk);
200 
201  // Use the separate bus_pkt to generate response to pkt and
202  // then delete it.
203  if (!pkt->isWriteback() && pkt->cmd != MemCmd::WriteClean) {
204  assert(pkt->needsResponse());
205  pkt->makeAtomicResponse();
206  if (bus_pkt->isError()) {
207  pkt->copyError(bus_pkt);
208  }
209  }
210 
211  delete bus_pkt;
212 
213  return latency;
214 }
215 
216 Tick
218 {
219  panic_if(pkt->cacheResponding(), "Should not see packets where cache "
220  "is responding");
221 
222  panic_if(!(pkt->isRead() || pkt->isWrite()),
223  "Should only see read and writes at non-coherent cache\n");
224 
225  return BaseCache::recvAtomic(pkt);
226 }
227 
228 
229 void
231 {
232  panic_if(!from_cpu_side, "Non-coherent cache received functional snoop"
233  " request\n");
234 
235  BaseCache::functionalAccess(pkt, from_cpu_side);
236 }
237 
238 void
240  CacheBlk *blk)
241 {
242  // First offset for critical word first calculations
243  const int initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
244 
245  MSHR::TargetList targets = mshr->extractServiceableTargets(pkt);
246  for (auto &target: targets) {
247  Packet *tgt_pkt = target.pkt;
248 
249  switch (target.source) {
251  // handle deferred requests comming from a cache or core
252  // above
253 
254  Tick completion_time;
255  // Here we charge on completion_time the delay of the xbar if the
256  // packet comes from it, charged on headerDelay.
257  completion_time = pkt->headerDelay;
258 
259  satisfyRequest(tgt_pkt, blk);
260 
261  // How many bytes past the first request is this one
262  int transfer_offset;
263  transfer_offset = tgt_pkt->getOffset(blkSize) - initial_offset;
264  if (transfer_offset < 0) {
265  transfer_offset += blkSize;
266  }
267  // If not critical word (offset) return payloadDelay.
268  // responseLatency is the latency of the return path
269  // from lower level caches/memory to an upper level cache or
270  // the core.
271  completion_time += clockEdge(responseLatency) +
272  (transfer_offset ? pkt->payloadDelay : 0);
273 
274  assert(tgt_pkt->req->requestorId() < system->maxRequestors());
275  stats.cmdStats(tgt_pkt).missLatency[tgt_pkt->req->requestorId()] +=
276  completion_time - target.recvTime;
277 
278  tgt_pkt->makeTimingResponse();
279  if (pkt->isError())
280  tgt_pkt->copyError(pkt);
281 
282  // Reset the bus additional time as it is now accounted for
283  tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
284  cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
285  break;
286 
288  // handle deferred requests comming from a prefetcher
289  // attached to this cache
290  assert(tgt_pkt->cmd == MemCmd::HardPFReq);
291 
292  if (blk)
293  blk->setPrefetched();
294 
295  // We have filled the block and the prefetcher does not
296  // require responses.
297  delete tgt_pkt;
298  break;
299 
300  default:
301  // we should never see FromSnoop Targets as this is a
302  // non-coherent cache
303  panic("Illegal target->source enum %d\n", target.source);
304  }
305  }
306 
307  // Reponses are filling and bring in writable blocks, therefore
308  // there should be no deferred targets and all the non-deferred
309  // targets are now serviced.
310  assert(mshr->getNumTargets() == 0);
311 }
312 
313 void
315 {
316  assert(pkt->isResponse());
317  // At the moment the only supported downstream requests we issue
318  // are ReadReq and therefore here we should only see the
319  // corresponding responses
320  assert(pkt->isRead());
321  assert(pkt->cmd != MemCmd::UpgradeResp);
322  assert(!pkt->isInvalidate());
323  // This cache is non-coherent and any memories below are
324  // non-coherent too (non-coherent caches or the main memory),
325  // therefore the fetched block can be marked as writable.
326  assert(!pkt->hasSharers());
327 
329 }
330 
331 PacketPtr
333 {
334  // A dirty block is always written back.
335 
336  // A clean block can we written back, if we turned on writebacks
337  // for clean blocks. This could be useful if there is a cache
338  // below and we want to make sure the block is cached but if the
339  // memory below is the main memory WritebackCleans are
340  // unnecessary.
341 
342  // If we clean writebacks are not enabled, we do not take any
343  // further action for evictions of clean blocks (i.e., CleanEvicts
344  // are unnecessary).
346  writebackBlk(blk) : nullptr;
347 
348  invalidateBlock(blk);
349 
350  return pkt;
351 }
MSHR::Target::FromPrefetcher
@ FromPrefetcher
Definition: mshr.hh:130
Packet::isError
bool isError() const
Definition: packet.hh:584
MSHR::Target::FromCPU
@ FromCPU
Definition: mshr.hh:128
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1017
BaseCache::maintainClusivity
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
Definition: base.cc:1401
Packet::isResponse
bool isResponse() const
Definition: packet.hh:561
Packet::makeTimingResponse
void makeTimingResponse()
Definition: packet.hh:1023
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:620
BaseCache::functionalAccess
virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side)
Performs the access specified by the request.
Definition: base.cc:631
Packet::hasSharers
bool hasSharers() const
Definition: packet.hh:647
NoncoherentCache::evictBlock
M5_NODISCARD PacketPtr evictBlock(CacheBlk *blk) override
Evict a cache block.
Definition: noncoherent_cache.cc:332
BaseCache::handleFill
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
Definition: base.cc:1413
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:755
MemCmd::HardPFReq
@ HardPFReq
Definition: packet.hh:95
BaseCache::writebackBlk
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
Definition: base.cc:1597
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:413
BaseCache::system
System * system
System we are currently operating in.
Definition: base.hh:978
mshr.hh
MSHR::getNumTargets
int getNumTargets() const
Returns the current number of allocated targets.
Definition: mshr.hh:422
NoncoherentCache::NoncoherentCache
NoncoherentCache(const NoncoherentCacheParams &p)
Definition: noncoherent_cache.cc:59
BaseCache::blkSize
const unsigned blkSize
Block size of this cache.
Definition: base.hh:880
Packet::isRead
bool isRead() const
Definition: packet.hh:557
MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:83
BaseCache::CacheCmdStats::missLatency
Stats::Vector missLatency
Total number of cycles per thread/command spent waiting for a miss.
Definition: base.hh:1004
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
BaseCache::memSidePort
MemSidePort memSidePort
Definition: base.hh:331
Packet::isInvalidate
bool isInvalidate() const
Definition: packet.hh:572
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:341
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:239
QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:90
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:77
Packet::headerDelay
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:395
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:784
QueueEntry::Target::pkt
const PacketPtr pkt
Pending request packet.
Definition: queue_entry.hh:88
Packet::copyError
void copyError(Packet *pkt)
Definition: packet.hh:753
NoncoherentCache::recvTimingReq
void recvTimingReq(PacketPtr pkt) override
Performs the access specified by the request.
Definition: noncoherent_cache.cc:132
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:67
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:144
BaseCache::allocateWriteBuffer
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Definition: base.hh:1178
Packet::isWholeLineWrite
bool isWholeLineWrite(unsigned blk_size)
Definition: packet.hh:588
BaseCache::mshrQueue
MSHRQueue mshrQueue
Miss status registers.
Definition: base.hh:336
BaseCache::cpuSidePort
CpuSidePort cpuSidePort
Definition: base.hh:330
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
BaseCache::allocOnFill
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
Definition: base.hh:433
BaseCache::stats
BaseCache::CacheStats stats
Packet::getBlockAddr
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:779
BaseCache::invalidateBlock
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
Definition: base.cc:1568
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:571
BaseCache::recvTimingReq
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:344
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
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:1132
Packet::getOffset
Addr getOffset(unsigned int blk_size) const
Definition: packet.hh:774
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
TaggedEntry::isValid
virtual bool isValid() const
Checks if the entry is valid.
Definition: tagged_entry.hh:54
MSHR::TargetList
Definition: mshr.hh:162
BaseCache
A basic cache interface.
Definition: base.hh:89
CacheBlk::WritableBit
@ WritableBit
write permission
Definition: cache_blk.hh:77
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:148
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:991
CacheBlk::setPrefetched
void setPrefetched()
Marks this blocks as a recently prefetched block.
Definition: cache_blk.hh:254
MSHR::getTarget
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
Definition: mshr.hh:449
CacheBlk::isSet
bool isSet(unsigned bits) const
Checks the given coherence bits are set.
Definition: cache_blk.hh:235
CacheBlk::setCoherenceBits
void setCoherenceBits(unsigned bits)
Sets the corresponding coherence bits.
Definition: cache_blk.hh:216
NoncoherentCache::handleTimingReqMiss
void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time) override
Definition: noncoherent_cache.cc:116
BaseCache::writebackClean
const bool writebackClean
Determine if clean lines should be written back or not.
Definition: base.hh:667
Packet::cmd
MemCmd cmd
The command field of the packet.
Definition: packet.hh:336
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
NoncoherentCache::recvTimingResp
void recvTimingResp(PacketPtr pkt) override
Handles a response (cache line fill/write ack) from the bus.
Definition: noncoherent_cache.cc:314
NoncoherentCache::doWritebacksAtomic
void doWritebacksAtomic(PacketList &writebacks) override
Send writebacks down the memory hierarchy in atomic mode.
Definition: noncoherent_cache.cc:105
cache_blk.hh
CacheBlk
A Basic Cache block.
Definition: cache_blk.hh:67
System::maxRequestors
RequestorID maxRequestors()
Get the number of requestors registered in the system.
Definition: system.hh:498
types.hh
Clocked::ticksToCycles
Cycles ticksToCycles(Tick t) const
Definition: clocked_object.hh:219
CacheBlk::DirtyBit
@ DirtyBit
dirty (modified)
Definition: cache_blk.hh:84
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:258
NoncoherentCache::functionalAccess
void functionalAccess(PacketPtr pkt, bool from_cpu_side) override
Performs the access specified by the request.
Definition: noncoherent_cache.cc:230
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
Packet::isWrite
bool isWrite() const
Definition: packet.hh:558
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:168
BaseCache::responseLatency
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
Definition: base.hh:909
MemCmd::WriteClean
@ WriteClean
Definition: packet.hh:91
NoncoherentCache::doWritebacks
void doWritebacks(PacketList &writebacks, Tick forward_time) override
Insert writebacks into the write buffer.
Definition: noncoherent_cache.cc:95
BaseCache::recvTimingResp
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
Definition: base.cc:412
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:576
Packet::allocate
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1300
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:551
BaseCache::CacheStats::cmdStats
CacheCmdStats & cmdStats(const PacketPtr p)
Definition: base.hh:1035
MemCmd::UpgradeResp
@ UpgradeResp
Definition: packet.hh:101
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:217

Generated on Tue Jun 22 2021 15:28:29 for gem5 by doxygen 1.8.17