Deleted Added
sdiff udiff text old ( 11194:c3ba89c653a9 ) new ( 11197:f8fdd931e674 )
full compact
1/*
2 * Copyright (c) 2010-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

--- 54 unchanged lines hidden (view full) ---

63#include "mem/cache/prefetch/base.hh"
64#include "sim/sim_exit.hh"
65
66Cache::Cache(const CacheParams *p)
67 : BaseCache(p, p->system->cacheLineSize()),
68 tags(p->tags),
69 prefetcher(p->prefetcher),
70 doFastWrites(true),
71 prefetchOnAccess(p->prefetch_on_access)
72{
73 tempBlock = new CacheBlk();
74 tempBlock->data = new uint8_t[blkSize];
75
76 cpuSidePort = new CpuSidePort(p->name + ".cpu_side", this,
77 "CpuSidePort");
78 memSidePort = new MemSidePort(p->name + ".mem_side", this,
79 "MemSidePort");

--- 113 unchanged lines hidden (view full) ---

193 assert(pkt->cmd == MemCmd::ReadExReq ||
194 pkt->cmd == MemCmd::SCUpgradeFailReq);
195
196 // if we have a dirty copy, make sure the recipient
197 // keeps it marked dirty
198 if (blk->isDirty()) {
199 pkt->assertMemInhibit();
200 }
201 // on ReadExReq we give up our copy unconditionally
202 if (blk != tempBlock)
203 tags->invalidate(blk);
204 blk->invalidate();
205 } else if (blk->isWritable() && !pending_downgrade &&
206 !pkt->sharedAsserted() &&
207 pkt->cmd != MemCmd::ReadCleanReq) {
208 // we can give the requester an exclusive copy (by not
209 // asserting shared line) on a read request if:
210 // - we have an exclusive copy at this level (& below)
211 // - we don't have a pending snoop from below
212 // signaling another read request
213 // - no other cache above has a copy (otherwise it
214 // would have asseretd shared line on request)
215 // - we are not satisfying an instruction fetch (this
216 // prevents dirty data in the i-cache)
217
218 if (blk->isDirty()) {
219 // special considerations if we're owner:
220 if (!deferred_response) {
221 // if we are responding immediately and can
222 // signal that we're transferring ownership
223 // along with exclusivity, do so
224 pkt->assertMemInhibit();
225 blk->status &= ~BlkDirty;
226 } else {
227 // if we're responding after our own miss,
228 // there's a window where the recipient didn't
229 // know it was getting ownership and may not
230 // have responded to snoops correctly, so we
231 // can't pass off ownership *or* exclusivity
232 pkt->assertShared();
233 }
234 }
235 } else {
236 // otherwise only respond with a shared copy
237 pkt->assertShared();
238 }
239 }
240 } else {
241 // Upgrade or Invalidate, since we have it Exclusively (E or
242 // M), we ack then invalidate.
243 assert(pkt->isUpgrade() || pkt->isInvalidate());
244 assert(blk != tempBlock);
245 tags->invalidate(blk);
246 blk->invalidate();
247 DPRINTF(Cache, "%s for %s addr %#llx size %d (invalidation)\n",
248 __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize());
249 }
250}
251
252
253/////////////////////////////////////////////////////
254//

--- 501 unchanged lines hidden (view full) ---

756 }
757 // We use forward_time here because it is the same
758 // considering new targets. We have multiple
759 // requests for the same address here. It
760 // specifies the latency to allocate an internal
761 // buffer and to schedule an event to the queued
762 // port and also takes into account the additional
763 // delay of the xbar.
764 mshr->allocateTarget(pkt, forward_time, order++);
765 if (mshr->getNumTargets() == numTarget) {
766 noTargetMSHR = mshr;
767 setBlocked(Blocked_NoTargets);
768 // need to be careful with this... if this mshr isn't
769 // ready yet (i.e. time > curTick()), we don't want to
770 // move it ahead of mshrs that are ready
771 // mshrQueue.moveToFront(mshr);
772 }

--- 249 unchanged lines hidden (view full) ---

1022 // an invalidate request
1023 satisfyCpuSideRequest(pkt, blk);
1024 }
1025 } else if (pkt->cmd == MemCmd::WriteLineReq) {
1026 // note the use of pkt, not bus_pkt here.
1027
1028 // write-line request to the cache that promoted
1029 // the write to a whole line
1030 blk = handleFill(pkt, blk, writebacks);
1031 satisfyCpuSideRequest(pkt, blk);
1032 } else if (bus_pkt->isRead() ||
1033 bus_pkt->cmd == MemCmd::UpgradeResp) {
1034 // we're updating cache state to allow us to
1035 // satisfy the upstream request from the cache
1036 blk = handleFill(bus_pkt, blk, writebacks);
1037 satisfyCpuSideRequest(pkt, blk);
1038 } else {
1039 // we're satisfying the upstream request without
1040 // modifying cache state, e.g., a write-through
1041 pkt->makeAtomicResponse();
1042 }
1043 }
1044 delete bus_pkt;

--- 6 unchanged lines hidden (view full) ---

1051 // rely on bandwidth contention to throttle them; these will tend
1052 // to pollute the cache in atomic mode since there is no bandwidth
1053 // contention. If we ever do want to enable prefetching in atomic
1054 // mode, though, this is the place to do it... see timingAccess()
1055 // for an example (though we'd want to issue the prefetch(es)
1056 // immediately rather than calling requestMemSideBus() as we do
1057 // there).
1058
1059 // Handle writebacks (from the response handling) if needed
1060 doWritebacksAtomic(writebacks);
1061
1062 if (pkt->needsResponse()) {
1063 pkt->makeAtomicResponse();
1064 }
1065
1066 return lat * clockPeriod();
1067}
1068
1069

--- 139 unchanged lines hidden (view full) ---

1209 (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp);
1210
1211 CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure());
1212
1213 if (is_fill && !is_error) {
1214 DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n",
1215 pkt->getAddr());
1216
1217 blk = handleFill(pkt, blk, writebacks);
1218 assert(blk != NULL);
1219 }
1220
1221 // allow invalidation responses originating from write-line
1222 // requests to be discarded
1223 bool is_invalidate = pkt->isInvalidate();
1224
1225 // First offset for critical word first calculations

--- 27 unchanged lines hidden (view full) ---

1253 // state. We "catch up" with that logic here, which is duplicated
1254 // from above.
1255 if (tgt_pkt->cmd == MemCmd::WriteLineReq) {
1256 assert(!is_error);
1257 // we got the block in exclusive state, so promote any
1258 // deferred targets if possible
1259 mshr->promoteExclusive();
1260 // NB: we use the original packet here and not the response!
1261 blk = handleFill(tgt_pkt, blk, writebacks);
1262 assert(blk != NULL);
1263
1264 // treat as a fill, and discard the invalidation
1265 // response
1266 is_fill = true;
1267 is_invalidate = false;
1268 }
1269

--- 87 unchanged lines hidden (view full) ---

1357 mshr->popTarget();
1358 }
1359
1360 if (blk && blk->isValid()) {
1361 // an invalidate response stemming from a write line request
1362 // should not invalidate the block, so check if the
1363 // invalidation should be discarded
1364 if (is_invalidate || mshr->hasPostInvalidate()) {
1365 assert(blk != tempBlock);
1366 tags->invalidate(blk);
1367 blk->invalidate();
1368 } else if (mshr->hasPostDowngrade()) {
1369 blk->status &= ~BlkWritable;
1370 }
1371 }
1372
1373 if (mshr->promoteDeferredTargets()) {
1374 // avoid later read getting stale data while write miss is
1375 // outstanding.. see comment in timingAccess()

--- 207 unchanged lines hidden (view full) ---

1583 writebacks.push_back(cleanEvictBlk(blk));
1584 }
1585 }
1586 }
1587
1588 return blk;
1589}
1590
1591
1592// Note that the reason we return a list of writebacks rather than
1593// inserting them directly in the write buffer is that this function
1594// is called by both atomic and timing-mode accesses, and in atomic
1595// mode we don't mess with the write buffer (we just perform the
1596// writebacks atomically once the original request is complete).
1597CacheBlk*
1598Cache::handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks)
1599{
1600 assert(pkt->isResponse() || pkt->cmd == MemCmd::WriteLineReq);
1601 Addr addr = pkt->getAddr();
1602 bool is_secure = pkt->isSecure();
1603#if TRACING_ON
1604 CacheBlk::State old_state = blk ? blk->status : 0;
1605#endif
1606

--- 7 unchanged lines hidden (view full) ---

1614 // better have read new data...
1615 assert(pkt->hasData());
1616
1617 // only read responses and write-line requests have data;
1618 // note that we don't write the data here for write-line - that
1619 // happens in the subsequent satisfyCpuSideRequest.
1620 assert(pkt->isRead() || pkt->cmd == MemCmd::WriteLineReq);
1621
1622 // need to do a replacement
1623 blk = allocateBlock(addr, is_secure, writebacks);
1624 if (blk == NULL) {
1625 // No replaceable block... just use temporary storage to
1626 // complete the current request and then get rid of it
1627 assert(!tempBlock->isValid());
1628 blk = tempBlock;
1629 tempBlock->set = tags->extractSet(addr);
1630 tempBlock->tag = tags->extractTag(addr);
1631 // @todo: set security state as well...
1632 DPRINTF(Cache, "using temp block for %#llx (%s)\n", addr,
1633 is_secure ? "s" : "ns");
1634 } else {

--- 237 unchanged lines hidden (view full) ---

1872
1873 if (respond) {
1874 // prevent anyone else from responding, cache as well as
1875 // memory, and also prevent any memory from even seeing the
1876 // request (with current inhibited semantics), note that this
1877 // applies both to reads and writes and that for writes it
1878 // works thanks to the fact that we still have dirty data and
1879 // will write it back at a later point
1880 pkt->assertMemInhibit();
1881 if (have_exclusive) {
1882 // in the case of an uncacheable request there is no point
1883 // in setting the exclusive flag, but since the recipient
1884 // does not care there is no harm in doing so, in any case
1885 // it is just a hint
1886 pkt->setSupplyExclusive();
1887 }

--- 18 unchanged lines hidden (view full) ---

1906 assert(pkt->needsResponse());
1907 delete pkt->req;
1908 delete pkt;
1909 }
1910
1911 // Do this last in case it deallocates block data or something
1912 // like that
1913 if (invalidate) {
1914 if (blk != tempBlock)
1915 tags->invalidate(blk);
1916 blk->invalidate();
1917 }
1918
1919 DPRINTF(Cache, "new state is %s\n", blk->print());
1920
1921 return snoop_delay;
1922}
1923
1924

--- 613 unchanged lines hidden ---