gem5  v20.0.0.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 }
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->masterId() < system->maxMasters());
273  stats.cmdStats(tgt_pkt).missLatency[tgt_pkt->req->masterId()] +=
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 }
Miss Status and Handling Register (MSHR) declaration.
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
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
#define DPRINTF(x,...)
Definition: trace.hh:225
void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time) override
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
Definition: base.cc:1485
State status
The current status of this block.
Definition: cache_blk.hh:105
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:81
Stats::Vector missLatency
Total number of cycles per thread/command spent waiting for a miss.
Definition: base.hh:947
bool isValid() const
Checks that a block is valid.
Definition: cache_blk.hh:203
CpuSidePort cpuSidePort
Definition: base.hh:308
void makeTimingResponse()
Definition: packet.hh:949
int getNumTargets() const
Returns the current number of allocated targets.
Definition: mshr.hh:422
System * system
System we are currently operating in.
Definition: base.hh:921
bool cacheResponding() const
Definition: packet.hh:585
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
BaseCache::CacheStats stats
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
Definition: base.cc:1459
A non-coherent cache.
void doWritebacks(PacketList &writebacks, Tick forward_time) override
Insert writebacks into the write buffer.
void doWritebacksAtomic(PacketList &writebacks) override
Send writebacks down the memory hierarchy in atomic mode.
bool isWrite() const
Definition: packet.hh:523
bool isInvalidate() const
Definition: packet.hh:537
bool isRead() const
Definition: packet.hh:522
Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks) override
Handle a request in atomic mode that missed in this cache.
MemSidePort memSidePort
Definition: base.hh:309
block was a hardware prefetch yet unaccessed
Definition: cache_blk.hh:73
CacheCmdStats & cmdStats(const PacketPtr p)
Definition: base.hh:978
Addr getBlockAddr(unsigned int blk_size) const
Definition: packet.hh:744
RequestPtr req
A pointer to the original request.
Definition: packet.hh:321
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
Definition: base.hh:868
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:334
void recvTimingResp(PacketPtr pkt) override
Handles a response (cache line fill/write ack) from the bus.
A coherent cache that can be arranged in flexible topologies.
Definition: cache.hh:63
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
Definition: base.cc:540
A Basic Cache block.
Definition: cache_blk.hh:84
void functionalAccess(PacketPtr pkt, bool from_cpu_side) override
Performs the access specified by the request.
bool needsResponse() const
Definition: packet.hh:536
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:360
bool isError() const
Definition: packet.hh:549
Addr getOffset(unsigned int blk_size) const
Definition: packet.hh:739
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:90
void makeAtomicResponse()
Definition: packet.hh:943
uint64_t Tick
Tick count type.
Definition: types.hh:61
bool isResponse() const
Definition: packet.hh:526
Miss Status and handling Register.
Definition: mshr.hh:69
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
Definition: base.cc:402
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
Definition: mshr.hh:449
Tick recvAtomic(PacketPtr pkt) override
Performs the access specified by the request.
Addr getAddr() const
Definition: packet.hh:720
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Definition: base.hh:1115
A basic cache interface.
Definition: base.hh:89
NoncoherentCache(const NoncoherentCacheParams *p)
STL list class.
Definition: stl.hh:51
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:378
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
Definition: base.cc:1306
const bool writebackClean
Determine if clean lines should be written back or not.
Definition: base.hh:626
const unsigned blkSize
Block size of this cache.
Definition: base.hh:839
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
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
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...
Bitfield< 15 > system
Definition: misc.hh:997
MasterID maxMasters()
Get the number of masters registered in the system.
Definition: system.hh:373
bool hasSharers() const
Definition: packet.hh:612
write permission
Definition: cache_blk.hh:67
Definitions of a simple cache block class.
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
void recvTimingReq(PacketPtr pkt) override
Performs the access specified by the request.
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
Definition: base.hh:404
Cycles ticksToCycles(Tick t) const
M5_NODISCARD PacketPtr evictBlock(CacheBlk *blk) override
Evict a cache block.
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:373
MemCmd cmd
The command field of the packet.
Definition: packet.hh:316
TargetList extractServiceableTargets(PacketPtr pkt)
Extracts the subset of the targets that can be serviced given a received response.
Definition: mshr.cc:536
const PacketPtr pkt
Pending request packet.
Definition: queue_entry.hh:88
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...
void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk) override
Service non-deferred MSHR targets using the received response.
bool isSecure() const
Definition: packet.hh:749
PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const override
Create an appropriate downstream bus request packet.
void copyError(Packet *pkt)
Definition: packet.hh:718
Specifies a non-coherent cache.
bool isWholeLineWrite(unsigned blk_size)
Definition: packet.hh:553
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:423
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:181
BaseTags * tags
Tag and data Storage.
Definition: base.hh:320
bool isWriteback() const
Definition: packet.hh:541
bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks) override
Does all the processing necessary to perform the provided request.
virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side)
Performs the access specified by the request.
Definition: base.cc:620
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:103
MSHRQueue mshrQueue
Miss status registers.
Definition: base.hh:314
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
Definition: base.cc:1294
bool isDirty() const
Check to see if a block has been written.
Definition: cache_blk.hh:226

Generated on Thu May 28 2020 16:21:34 for gem5 by doxygen 1.8.13