2 * Copyright (c) 2010-2018 ARM Limited
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.
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.
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.
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.
41 * Authors: Erik Hallnor
55 #include "mem/cache/noncoherent_cache.hh"
59 #include "base/logging.hh"
60 #include "base/trace.hh"
61 #include "base/types.hh"
62 #include "debug/Cache.hh"
63 #include "mem/cache/blk.hh"
64 #include "mem/cache/mshr.hh"
65 #include "params/NoncoherentCache.hh"
67 NoncoherentCache::NoncoherentCache(const NoncoherentCacheParams
*p
)
68 : BaseCache(p
, p
->system
->cacheLineSize())
73 NoncoherentCache::satisfyRequest(PacketPtr pkt
, CacheBlk
*blk
, bool, bool)
75 // As this a non-coherent cache located below the point of
76 // coherency, we do not expect requests that are typically used to
77 // keep caches coherent (e.g., InvalidateReq or UpdateReq).
78 assert(pkt
->isRead() || pkt
->isWrite());
79 BaseCache::satisfyRequest(pkt
, blk
);
83 NoncoherentCache::access(PacketPtr pkt
, CacheBlk
*&blk
, Cycles
&lat
,
84 PacketList
&writebacks
)
86 bool success
= BaseCache::access(pkt
, blk
, lat
, writebacks
);
88 if (pkt
->isWriteback() || pkt
->cmd
== MemCmd::WriteClean
) {
89 assert(blk
&& blk
->isValid());
90 // Writeback and WriteClean can allocate and fill even if the
91 // referenced block was not present or it was invalid. If that
92 // is the case, make sure that the new block is marked as
94 blk
->status
|= BlkWritable
;
101 NoncoherentCache::doWritebacks(PacketList
& writebacks
, Tick forward_time
)
103 while (!writebacks
.empty()) {
104 PacketPtr wb_pkt
= writebacks
.front();
105 allocateWriteBuffer(wb_pkt
, forward_time
);
106 writebacks
.pop_front();
111 NoncoherentCache::doWritebacksAtomic(PacketList
& writebacks
)
113 while (!writebacks
.empty()) {
114 PacketPtr wb_pkt
= writebacks
.front();
115 memSidePort
.sendAtomic(wb_pkt
);
116 writebacks
.pop_front();
122 NoncoherentCache::handleTimingReqMiss(PacketPtr pkt
, CacheBlk
*blk
,
123 Tick forward_time
, Tick request_time
)
126 Addr blk_addr
= pkt
->getBlockAddr(blkSize
);
127 MSHR
*mshr
= mshrQueue
.findMatch(blk_addr
, pkt
->isSecure(), false);
129 // We can always write to a non coherent cache if the block is
130 // present and therefore if we have reached this point then the
131 // block should not be in the cache.
132 assert(mshr
|| !blk
|| !blk
->isValid());
134 BaseCache::handleTimingReqMiss(pkt
, mshr
, blk
, forward_time
, request_time
);
138 NoncoherentCache::recvTimingReq(PacketPtr pkt
)
140 panic_if(pkt
->cacheResponding(), "Should not see packets where cache "
143 panic_if(!(pkt
->isRead() || pkt
->isWrite()),
144 "Should only see read and writes at non-coherent cache\n");
146 BaseCache::recvTimingReq(pkt
);
150 NoncoherentCache::createMissPacket(PacketPtr cpu_pkt
, CacheBlk
*blk
,
151 bool needs_writable
) const
153 // We also fill for writebacks from the coherent caches above us,
154 // and they do not need responses
155 assert(cpu_pkt
->needsResponse());
157 // A miss can happen only due to missing block
158 assert(!blk
|| !blk
->isValid());
160 PacketPtr pkt
= new Packet(cpu_pkt
->req
, MemCmd::ReadReq
, blkSize
);
162 // the packet should be block aligned
163 assert(pkt
->getAddr() == pkt
->getBlockAddr(blkSize
));
166 DPRINTF(Cache
, "%s created %s from %s\n", __func__
, pkt
->print(),
173 NoncoherentCache::handleAtomicReqMiss(PacketPtr pkt
, CacheBlk
*&blk
,
174 PacketList
&writebacks
)
176 PacketPtr bus_pkt
= createMissPacket(pkt
, blk
, true);
177 DPRINTF(Cache
, "Sending an atomic %s\n", bus_pkt
->print());
179 Cycles latency
= ticksToCycles(memSidePort
.sendAtomic(bus_pkt
));
181 assert(bus_pkt
->isResponse());
182 // At the moment the only supported downstream requests we issue
183 // are ReadReq and therefore here we should only see the
184 // corresponding responses
185 assert(bus_pkt
->isRead());
186 assert(pkt
->cmd
!= MemCmd::UpgradeResp
);
187 assert(!bus_pkt
->isInvalidate());
188 assert(!bus_pkt
->hasSharers());
190 // We are now dealing with the response handling
191 DPRINTF(Cache
, "Receive response: %s\n", bus_pkt
->print());
193 if (!bus_pkt
->isError()) {
194 // Any reponse that does not have an error should be filling,
195 // afterall it is a read response
196 DPRINTF(Cache
, "Block for addr %#llx being updated in Cache\n",
198 blk
= handleFill(bus_pkt
, blk
, writebacks
, allocOnFill(bus_pkt
->cmd
));
201 satisfyRequest(pkt
, blk
);
203 maintainClusivity(true, blk
);
205 // Use the separate bus_pkt to generate response to pkt and
207 if (!pkt
->isWriteback() && pkt
->cmd
!= MemCmd::WriteClean
) {
208 assert(pkt
->needsResponse());
209 pkt
->makeAtomicResponse();
210 if (bus_pkt
->isError()) {
211 pkt
->copyError(bus_pkt
);
221 NoncoherentCache::recvAtomic(PacketPtr pkt
)
223 panic_if(pkt
->cacheResponding(), "Should not see packets where cache "
226 panic_if(!(pkt
->isRead() || pkt
->isWrite()),
227 "Should only see read and writes at non-coherent cache\n");
229 return BaseCache::recvAtomic(pkt
);
234 NoncoherentCache::functionalAccess(PacketPtr pkt
, bool from_cpu_side
)
236 panic_if(!from_cpu_side
, "Non-coherent cache received functional snoop"
239 BaseCache::functionalAccess(pkt
, from_cpu_side
);
243 NoncoherentCache::serviceMSHRTargets(MSHR
*mshr
, const PacketPtr pkt
,
244 CacheBlk
*blk
, PacketList
&writebacks
)
246 MSHR::Target
*initial_tgt
= mshr
->getTarget();
247 // First offset for critical word first calculations
248 const int initial_offset
= initial_tgt
->pkt
->getOffset(blkSize
);
250 MSHR::TargetList targets
= mshr
->extractServiceableTargets(pkt
);
251 for (auto &target
: targets
) {
252 Packet
*tgt_pkt
= target
.pkt
;
254 switch (target
.source
) {
255 case MSHR::Target::FromCPU
:
256 // handle deferred requests comming from a cache or core
259 Tick completion_time
;
260 // Here we charge on completion_time the delay of the xbar if the
261 // packet comes from it, charged on headerDelay.
262 completion_time
= pkt
->headerDelay
;
264 satisfyRequest(tgt_pkt
, blk
);
266 // How many bytes past the first request is this one
268 transfer_offset
= tgt_pkt
->getOffset(blkSize
) - initial_offset
;
269 if (transfer_offset
< 0) {
270 transfer_offset
+= blkSize
;
272 // If not critical word (offset) return payloadDelay.
273 // responseLatency is the latency of the return path
274 // from lower level caches/memory to an upper level cache or
276 completion_time
+= clockEdge(responseLatency
) +
277 (transfer_offset
? pkt
->payloadDelay
: 0);
279 assert(tgt_pkt
->req
->masterId() < system
->maxMasters());
280 missLatency
[tgt_pkt
->cmdToIndex()][tgt_pkt
->req
->masterId()] +=
281 completion_time
- target
.recvTime
;
283 tgt_pkt
->makeTimingResponse();
285 tgt_pkt
->copyError(pkt
);
287 // Reset the bus additional time as it is now accounted for
288 tgt_pkt
->headerDelay
= tgt_pkt
->payloadDelay
= 0;
289 cpuSidePort
.schedTimingResp(tgt_pkt
, completion_time
, true);
292 case MSHR::Target::FromPrefetcher
:
293 // handle deferred requests comming from a prefetcher
294 // attached to this cache
295 assert(tgt_pkt
->cmd
== MemCmd::HardPFReq
);
298 blk
->status
|= BlkHWPrefetched
;
300 // We have filled the block and the prefetcher does not
301 // require responses.
306 // we should never see FromSnoop Targets as this is a
307 // non-coherent cache
308 panic("Illegal target->source enum %d\n", target
.source
);
312 // Reponses are filling and bring in writable blocks, therefore
313 // there should be no deferred targets and all the non-deferred
314 // targets are now serviced.
315 assert(mshr
->getNumTargets() == 0);
319 NoncoherentCache::recvTimingResp(PacketPtr pkt
)
321 assert(pkt
->isResponse());
322 // At the moment the only supported downstream requests we issue
323 // are ReadReq and therefore here we should only see the
324 // corresponding responses
325 assert(pkt
->isRead());
326 assert(pkt
->cmd
!= MemCmd::UpgradeResp
);
327 assert(!pkt
->isInvalidate());
328 // This cache is non-coherent and any memories below are
329 // non-coherent too (non-coherent caches or the main memory),
330 // therefore the fetched block can be marked as writable.
331 assert(!pkt
->hasSharers());
333 BaseCache::recvTimingResp(pkt
);
337 NoncoherentCache::evictBlock(CacheBlk
*blk
)
339 // A dirty block is always written back.
341 // A clean block can we written back, if we turned on writebacks
342 // for clean blocks. This could be useful if there is a cache
343 // below and we want to make sure the block is cached but if the
344 // memory below is the main memory WritebackCleans are
347 // If we clean writebacks are not enabled, we do not take any
348 // further action for evictions of clean blocks (i.e., CleanEvicts
350 PacketPtr pkt
= (blk
->isDirty() || writebackClean
) ?
351 writebackBlk(blk
) : nullptr;
353 invalidateBlock(blk
);
359 NoncoherentCache::evictBlock(CacheBlk
*blk
, PacketList
&writebacks
)
361 PacketPtr pkt
= evictBlock(blk
);
363 writebacks
.push_back(pkt
);
368 NoncoherentCacheParams::create()
371 assert(replacement_policy
);
373 return new NoncoherentCache(this);