base.cc (13945:a573bed35a8b) | base.cc (13947:4cf8087cab09) |
---|---|
1/* 2 * Copyright (c) 2012-2013, 2018-2019 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 --- 37 unchanged lines hidden (view full) --- 46 * Definition of BaseCache functions. 47 */ 48 49#include "mem/cache/base.hh" 50 51#include "base/compiler.hh" 52#include "base/logging.hh" 53#include "debug/Cache.hh" | 1/* 2 * Copyright (c) 2012-2013, 2018-2019 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 --- 37 unchanged lines hidden (view full) --- 46 * Definition of BaseCache functions. 47 */ 48 49#include "mem/cache/base.hh" 50 51#include "base/compiler.hh" 52#include "base/logging.hh" 53#include "debug/Cache.hh" |
54#include "debug/CacheComp.hh" |
|
54#include "debug/CachePort.hh" 55#include "debug/CacheRepl.hh" 56#include "debug/CacheVerbose.hh" 57#include "mem/cache/compressors/base.hh" 58#include "mem/cache/mshr.hh" 59#include "mem/cache/prefetch/base.hh" 60#include "mem/cache/queue_entry.hh" | 55#include "debug/CachePort.hh" 56#include "debug/CacheRepl.hh" 57#include "debug/CacheVerbose.hh" 58#include "mem/cache/compressors/base.hh" 59#include "mem/cache/mshr.hh" 60#include "mem/cache/prefetch/base.hh" 61#include "mem/cache/queue_entry.hh" |
62#include "mem/cache/tags/super_blk.hh" |
|
61#include "params/BaseCache.hh" 62#include "params/WriteAllocator.hh" 63#include "sim/core.hh" 64 65class BaseMasterPort; 66class BaseSlavePort; 67 68using namespace std; --- 722 unchanged lines hidden (view full) --- 791 delete pkt; 792 } 793 } 794 } 795 796 return nullptr; 797} 798 | 63#include "params/BaseCache.hh" 64#include "params/WriteAllocator.hh" 65#include "sim/core.hh" 66 67class BaseMasterPort; 68class BaseSlavePort; 69 70using namespace std; --- 722 unchanged lines hidden (view full) --- 793 delete pkt; 794 } 795 } 796 } 797 798 return nullptr; 799} 800 |
801bool 802BaseCache::updateCompressionData(CacheBlk *blk, const uint64_t* data, 803 PacketList &writebacks) 804{ 805 // tempBlock does not exist in the tags, so don't do anything for it. 806 if (blk == tempBlock) { 807 return true; 808 } 809 810 // Get superblock of the given block 811 CompressionBlk* compression_blk = static_cast<CompressionBlk*>(blk); 812 const SuperBlk* superblock = static_cast<const SuperBlk*>( 813 compression_blk->getSectorBlock()); 814 815 // The compressor is called to compress the updated data, so that its 816 // metadata can be updated. 817 std::size_t compression_size = 0; 818 Cycles compression_lat = Cycles(0); 819 Cycles decompression_lat = Cycles(0); 820 compressor->compress(data, compression_lat, decompression_lat, 821 compression_size); 822 823 // If block's compression factor increased, it may not be co-allocatable 824 // anymore. If so, some blocks might need to be evicted to make room for 825 // the bigger block 826 827 // Get previous compressed size 828 const std::size_t M5_VAR_USED prev_size = compression_blk->getSizeBits(); 829 830 // Check if new data is co-allocatable 831 const bool is_co_allocatable = superblock->isCompressed(compression_blk) && 832 superblock->canCoAllocate(compression_size); 833 834 // If block was compressed, possibly co-allocated with other blocks, and 835 // cannot be co-allocated anymore, one or more blocks must be evicted to 836 // make room for the expanded block. As of now we decide to evict the co- 837 // allocated blocks to make room for the expansion, but other approaches 838 // that take the replacement data of the superblock into account may 839 // generate better results 840 std::vector<CacheBlk*> evict_blks; 841 const bool was_compressed = compression_blk->isCompressed(); 842 if (was_compressed && !is_co_allocatable) { 843 // Get all co-allocated blocks 844 for (const auto& sub_blk : superblock->blks) { 845 if (sub_blk->isValid() && (compression_blk != sub_blk)) { 846 // Check for transient state allocations. If any of the 847 // entries listed for eviction has a transient state, the 848 // allocation fails 849 const Addr repl_addr = regenerateBlkAddr(sub_blk); 850 const MSHR *repl_mshr = 851 mshrQueue.findMatch(repl_addr, sub_blk->isSecure()); 852 if (repl_mshr) { 853 DPRINTF(CacheRepl, "Aborting data expansion of %s due " \ 854 "to replacement of block in transient state: %s\n", 855 compression_blk->print(), sub_blk->print()); 856 // Too hard to replace block with transient state, so it 857 // cannot be evicted. Mark the update as failed and expect 858 // the caller to evict this block. Since this is called 859 // only when writebacks arrive, and packets do not contain 860 // compressed data, there is no need to decompress 861 compression_blk->setSizeBits(blkSize * 8); 862 compression_blk->setDecompressionLatency(Cycles(0)); 863 compression_blk->setUncompressed(); 864 return false; 865 } 866 867 evict_blks.push_back(sub_blk); 868 } 869 } 870 871 // Update the number of data expansions 872 dataExpansions++; 873 874 DPRINTF(CacheComp, "Data expansion: expanding [%s] from %d to %d bits" 875 "\n", blk->print(), prev_size, compression_size); 876 } 877 878 // We always store compressed blocks when possible 879 if (is_co_allocatable) { 880 compression_blk->setCompressed(); 881 } else { 882 compression_blk->setUncompressed(); 883 } 884 compression_blk->setSizeBits(compression_size); 885 compression_blk->setDecompressionLatency(decompression_lat); 886 887 // Evict valid blocks 888 for (const auto& evict_blk : evict_blks) { 889 if (evict_blk->isValid()) { 890 if (evict_blk->wasPrefetched()) { 891 unusedPrefetches++; 892 } 893 evictBlock(evict_blk, writebacks); 894 } 895 } 896 897 return true; 898} 899 |
|
799void 800BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) 801{ 802 assert(pkt->isRequest()); 803 804 assert(blk && blk->isValid()); 805 // Occasionally this is not true... if we are a lower-level cache 806 // satisfying a string of Read and ReadEx requests from --- 224 unchanged lines hidden (view full) --- 1031 // A writeback searches for the block, then writes the data. 1032 // As the block could not be found, it was a tag-only access. 1033 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1034 1035 return false; 1036 } 1037 1038 blk->status |= BlkReadable; | 900void 901BaseCache::satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool, bool) 902{ 903 assert(pkt->isRequest()); 904 905 assert(blk && blk->isValid()); 906 // Occasionally this is not true... if we are a lower-level cache 907 // satisfying a string of Read and ReadEx requests from --- 224 unchanged lines hidden (view full) --- 1132 // A writeback searches for the block, then writes the data. 1133 // As the block could not be found, it was a tag-only access. 1134 lat = calculateTagOnlyLatency(pkt->headerDelay, tag_latency); 1135 1136 return false; 1137 } 1138 1139 blk->status |= BlkReadable; |
1039 } else { 1040 if (compressor) { 1041 // This is an overwrite to an existing block, therefore we need 1042 // to check for data expansion (i.e., block was compressed with 1043 // a smaller size, and now it doesn't fit the entry anymore). 1044 // If that is the case we might need to evict blocks. 1045 // @todo Update compression data | 1140 } else if (compressor) { 1141 // This is an overwrite to an existing block, therefore we need 1142 // to check for data expansion (i.e., block was compressed with 1143 // a smaller size, and now it doesn't fit the entry anymore). 1144 // If that is the case we might need to evict blocks. 1145 if (!updateCompressionData(blk, pkt->getConstPtr<uint64_t>(), 1146 writebacks)) { 1147 // This is a failed data expansion (write), which happened 1148 // after finding the replacement entries and accessing the 1149 // block's data. There were no replaceable entries available 1150 // to make room for the expanded block, and since it does not 1151 // fit anymore and it has been properly updated to contain 1152 // the new data, forward it to the next level 1153 lat = calculateAccessLatency(blk, pkt->headerDelay, 1154 tag_latency); 1155 invalidateBlock(blk); 1156 return false; |
1046 } 1047 } 1048 1049 // only mark the block dirty if we got a writeback command, 1050 // and leave it as is for a clean writeback 1051 if (pkt->cmd == MemCmd::WritebackDirty) { 1052 // TODO: the coherent cache can assert(!blk->isDirty()); 1053 blk->status |= BlkDirty; --- 66 unchanged lines hidden (view full) --- 1120 lat = calculateTagOnlyLatency(pkt->headerDelay, 1121 tag_latency); 1122 1123 return false; 1124 } 1125 1126 blk->status |= BlkReadable; 1127 } | 1157 } 1158 } 1159 1160 // only mark the block dirty if we got a writeback command, 1161 // and leave it as is for a clean writeback 1162 if (pkt->cmd == MemCmd::WritebackDirty) { 1163 // TODO: the coherent cache can assert(!blk->isDirty()); 1164 blk->status |= BlkDirty; --- 66 unchanged lines hidden (view full) --- 1231 lat = calculateTagOnlyLatency(pkt->headerDelay, 1232 tag_latency); 1233 1234 return false; 1235 } 1236 1237 blk->status |= BlkReadable; 1238 } |
1128 } else { 1129 if (compressor) { 1130 // @todo Update compression data | 1239 } else if (compressor) { 1240 // This is an overwrite to an existing block, therefore we need 1241 // to check for data expansion (i.e., block was compressed with 1242 // a smaller size, and now it doesn't fit the entry anymore). 1243 // If that is the case we might need to evict blocks. 1244 if (!updateCompressionData(blk, pkt->getConstPtr<uint64_t>(), 1245 writebacks)) { 1246 // This is a failed data expansion (write), which happened 1247 // after finding the replacement entries and accessing the 1248 // block's data. There were no replaceable entries available 1249 // to make room for the expanded block, and since it does not 1250 // fit anymore and it has been properly updated to contain 1251 // the new data, forward it to the next level 1252 lat = calculateAccessLatency(blk, pkt->headerDelay, 1253 tag_latency); 1254 invalidateBlock(blk); 1255 return false; |
1131 } 1132 } 1133 1134 // at this point either this is a writeback or a write-through 1135 // write clean operation and the block is already in this 1136 // cache, we need to update the data and the block flags 1137 assert(blk); 1138 // TODO: the coherent cache can assert(!blk->isDirty()); --- 11 unchanged lines hidden (view full) --- 1150 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1151 1152 // When the packet metadata arrives, the tag lookup will be done while 1153 // the payload is arriving. Then the block will be ready to access as 1154 // soon as the fill is done 1155 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1156 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); 1157 | 1256 } 1257 } 1258 1259 // at this point either this is a writeback or a write-through 1260 // write clean operation and the block is already in this 1261 // cache, we need to update the data and the block flags 1262 assert(blk); 1263 // TODO: the coherent cache can assert(!blk->isDirty()); --- 11 unchanged lines hidden (view full) --- 1275 lat = calculateAccessLatency(blk, pkt->headerDelay, tag_latency); 1276 1277 // When the packet metadata arrives, the tag lookup will be done while 1278 // the payload is arriving. Then the block will be ready to access as 1279 // soon as the fill is done 1280 blk->setWhenReady(clockEdge(fillLatency) + pkt->headerDelay + 1281 std::max(cyclesToTicks(tag_latency), (uint64_t)pkt->payloadDelay)); 1282 |
1158 // if this a write-through packet it will be sent to cache 1159 // below | 1283 // If this a write-through packet it will be sent to cache below |
1160 return !pkt->writeThrough(); 1161 } else if (blk && (pkt->needsWritable() ? blk->isWritable() : 1162 blk->isReadable())) { 1163 // OK to satisfy access 1164 incHitCount(pkt); 1165 1166 // Calculate access latency based on the need to access the data array 1167 if (pkt->isRead() || pkt->isWrite()) { --- 1192 unchanged lines hidden (view full) --- 2360 for (int i = 0; i < system->maxMasters(); i++) { 2361 overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i)); 2362 } 2363 2364 replacements 2365 .name(name() + ".replacements") 2366 .desc("number of replacements") 2367 ; | 1284 return !pkt->writeThrough(); 1285 } else if (blk && (pkt->needsWritable() ? blk->isWritable() : 1286 blk->isReadable())) { 1287 // OK to satisfy access 1288 incHitCount(pkt); 1289 1290 // Calculate access latency based on the need to access the data array 1291 if (pkt->isRead() || pkt->isWrite()) { --- 1192 unchanged lines hidden (view full) --- 2484 for (int i = 0; i < system->maxMasters(); i++) { 2485 overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i)); 2486 } 2487 2488 replacements 2489 .name(name() + ".replacements") 2490 .desc("number of replacements") 2491 ; |
2492 2493 dataExpansions 2494 .name(name() + ".data_expansions") 2495 .desc("number of data expansions") 2496 .flags(nozero | nonan) 2497 ; |
|
2368} 2369 2370void 2371BaseCache::regProbePoints() 2372{ 2373 ppHit = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Hit"); 2374 ppMiss = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Miss"); 2375 ppFill = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Fill"); --- 221 unchanged lines hidden --- | 2498} 2499 2500void 2501BaseCache::regProbePoints() 2502{ 2503 ppHit = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Hit"); 2504 ppMiss = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Miss"); 2505 ppFill = new ProbePointArg<PacketPtr>(this->getProbeManager(), "Fill"); --- 221 unchanged lines hidden --- |