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 ---