50#include "debug/Cache.hh"
51#include "debug/CacheComp.hh"
52#include "debug/CachePort.hh"
53#include "debug/CacheRepl.hh"
54#include "debug/CacheVerbose.hh"
55#include "debug/HWPrefetch.hh"
63#include "params/BaseCache.hh"
64#include "params/WriteAllocator.hh"
72 const std::string &_label)
75 queue(_cache, *this, true, _label),
76 blocked(false), mustSendRetry(false),
99 lookupLatency(
p.tag_latency),
100 dataLatency(
p.data_latency),
101 forwardLatency(
p.tag_latency),
102 fillLatency(
p.data_latency),
103 responseLatency(
p.response_latency),
104 sequentialAccess(
p.sequential_access),
105 numTarget(
p.tgts_per_mshr),
107 clusivity(
p.clusivity),
108 isReadOnly(
p.is_read_only),
109 replaceExpansions(
p.replace_expansions),
110 moveContractions(
p.move_contractions),
113 noTargetMSHR(
nullptr),
114 missCount(
p.max_miss_count),
115 addrRanges(
p.addr_ranges.begin(),
p.addr_ranges.end()),
133 prefetcher->setParentInfo(
system, getProbeManager(), getBlockSize());
136 "The tags of compressed cache %s must derive from CompressedTags",
139 "Compressed cache %s does not have a compression algorithm",
name());
141 compressor->setCache(
this);
153 DPRINTF(CachePort,
"Port is blocking new requests\n");
159 DPRINTF(CachePort,
"Port descheduled retry\n");
168 DPRINTF(CachePort,
"Port is accepting new requests\n");
172 cache.schedule(sendRetryEvent,
curTick() + 1);
179 DPRINTF(CachePort,
"Port is sending retry\n");
182 mustSendRetry =
false;
200 fatal(
"Cache ports on %s are not connected\n",
name());
208 if (if_name ==
"mem_side") {
210 }
else if (if_name ==
"cpu_side") {
221 if (
r.contains(
addr)) {
298 DPRINTF(
Cache,
"%s satisfied %s, no response needed\n", __func__,
311 Tick forward_time,
Tick request_time)
314 pkt && pkt->
isWrite() && !pkt->
req->isUncacheable()) {
396 pkt->
req->isCacheMaintenance());
430 bool satisfied =
false;
435 satisfied =
access(pkt, blk, lat, writebacks);
472 Tick next_pf_time = std::max(
500 "%s saw a non-zero packet delay\n",
name());
502 const bool is_error = pkt->
isError();
505 DPRINTF(
Cache,
"%s: Cache received %s with error\n", __func__,
515 assert(pkt->
req->isUncacheable());
534 if (pkt->
req->isUncacheable()) {
556 if (is_fill && !is_error) {
557 DPRINTF(
Cache,
"Block for addr %#llx being updated in Cache\n",
562 blk =
handleFill(pkt, blk, writebacks, allocate);
563 assert(blk !=
nullptr);
583 !pkt->
req->isCacheInvalidate()) {
616 Tick next_pf_time = std::max(
633 DPRINTF(CacheVerbose,
"%s: Leaving with %s\n", __func__, pkt->
print());
651 bool satisfied =
access(pkt, blk, lat, writebacks);
658 DPRINTF(CacheVerbose,
"%s: packet %s found block: %s\n",
661 writebacks.push_back(wb_pkt);
668 assert(writebacks.empty());
736 bool have_data = blk && blk->
isValid()
746 bool done = have_dirty ||
752 DPRINTF(CacheVerbose,
"%s: %s %s%s%s\n", __func__, pkt->
print(),
753 (blk && blk->
isValid()) ?
"valid " :
"",
754 have_data ?
"data " :
"", done ?
"done " :
"");
808 uint64_t overwrite_val;
810 uint64_t condition_val64;
811 uint32_t condition_val32;
816 assert(
sizeof(uint64_t) >= pkt->
getSize());
827 overwrite_mem =
true;
830 pkt->
writeData((uint8_t *)&overwrite_val);
833 if (pkt->
req->isCondSwap()) {
834 if (pkt->
getSize() ==
sizeof(uint64_t)) {
835 condition_val64 = pkt->
req->getExtraData();
836 overwrite_mem = !std::memcmp(&condition_val64, blk_data,
838 }
else if (pkt->
getSize() ==
sizeof(uint32_t)) {
839 condition_val32 = (uint32_t)pkt->
req->getExtraData();
840 overwrite_mem = !std::memcmp(&condition_val32, blk_data,
843 panic(
"Invalid size for conditional read/write\n");
847 std::memcpy(blk_data, &overwrite_val, pkt->
getSize());
873 if (conflict_mshr && conflict_mshr->
order < wq_entry->
order) {
875 return conflict_mshr;
882 }
else if (miss_mshr) {
898 return conflict_mshr;
908 assert(!miss_mshr && !wq_entry);
915 DPRINTF(HWPrefetch,
"Prefetch %#x has hit in cache, "
916 "dropped.\n", pf_addr);
921 DPRINTF(HWPrefetch,
"Prefetch %#x has hit in a MSHR, "
922 "dropped.\n", pf_addr);
927 DPRINTF(HWPrefetch,
"Prefetch %#x has hit in the "
928 "Write Buffer, dropped.\n", pf_addr);
953 bool replacement =
false;
954 for (
const auto& blk : evict_blks) {
955 if (blk->isValid()) {
976 for (
auto& blk : evict_blks) {
977 if (blk->isValid()) {
999 const auto comp_data =
1001 std::size_t compression_size = comp_data->getSizeBits();
1005 [[maybe_unused]]
const std::size_t prev_size =
1012 bool is_data_expansion =
false;
1013 bool is_data_contraction =
false;
1016 std::string op_name =
"";
1018 op_name =
"expansion";
1019 is_data_expansion =
true;
1022 op_name =
"contraction";
1023 is_data_contraction =
true;
1030 if (is_data_expansion || is_data_contraction) {
1032 bool victim_itself =
false;
1037 compression_size, evict_blks,
1047 if (blk == victim) {
1048 victim_itself =
true;
1049 auto it = std::find_if(evict_blks.begin(), evict_blks.end(),
1050 [&blk](
CacheBlk* evict_blk){ return evict_blk == blk; });
1051 evict_blks.erase(it);
1055 DPRINTF(CacheRepl,
"Data %s replacement victim: %s\n",
1056 op_name, victim->
print());
1062 for (
auto& sub_blk : superblock->
blks) {
1063 if (sub_blk->isValid() && (blk != sub_blk)) {
1064 evict_blks.push_back(sub_blk);
1074 DPRINTF(CacheComp,
"Data %s: [%s] from %d to %d bits\n",
1075 op_name, blk->
print(), prev_size, compression_size);
1087 if (is_data_expansion) {
1089 }
else if (is_data_contraction) {
1104 assert(blk && blk->
isValid());
1165 DPRINTF(CacheVerbose,
"%s for %s (write)\n", __func__, pkt->
print());
1166 }
else if (pkt->
isRead()) {
1190 DPRINTF(CacheVerbose,
"%s for %s (invalidation)\n", __func__,
1202 const Cycles lookup_lat)
const
1211 const Cycles lookup_lat)
const
1215 if (blk !=
nullptr) {
1229 if (when_ready >
tick &&
1251 "Should never see a write in a read-only cache %s\n",
1259 blk ?
"hit " + blk->
print() :
"miss");
1261 if (pkt->
req->isCacheMaintenance()) {
1334 DPRINTF(
Cache,
"Clean writeback %#llx to block with MSHR, "
1335 "dropping\n", pkt->
getAddr());
1345 const bool has_old_data = blk && blk->
isValid();
1417 const bool has_old_data = blk && blk->
isValid();
1505 pkt->
req->setExtraData(0);
1515 if (from_cache && blk && blk->
isValid() &&
1531 const bool has_old_data = blk && blk->
isValid();
1532 const std::string old_state = (debug::Cache && blk) ? blk->
print() :
"";
1553 is_secure ?
"s" :
"ns");
1563 assert(blk->
isSecure() == is_secure);
1596 "in read-only cache %s\n",
name());
1601 DPRINTF(
Cache,
"Block addr %#llx (%s) moving from %s to %s\n",
1602 addr, is_secure ?
"s" :
"ns", old_state, blk->
print());
1627 const bool is_secure = pkt->
isSecure();
1632 std::size_t blk_size_bits =
blkSize*8;
1643 pkt->
getConstPtr<uint64_t>(), compression_lat, decompression_lat);
1644 blk_size_bits = comp_data->getSizeBits();
1653 evict_blks, partition_id);
1660 DPRINTF(CacheRepl,
"Replacement victim: %s\n", victim->
print());
1705 writebacks.push_back(pkt);
1713 "Writeback from read-only cache");
1714 assert(blk && blk->
isValid() &&
1731 DPRINTF(
Cache,
"Create Writeback %s writable: %d, dirty: %d\n",
1773 req->setFlags(dest);
1836 RequestPtr request = std::make_shared<Request>(
1857 warn_once(
"Invalidating dirty cache lines. " \
1858 "Expect things to break.\n");
1875 nextReady = std::min(nextReady,
1904 DPRINTF(CacheVerbose,
"Delaying pkt %s %llu ticks to allow "
1905 "for write coalescing\n", tgt_pkt->
print(), delay);
1929 pkt =
new Packet(tgt_pkt,
false,
true);
1964 bool pending_modified_resp = !pkt->
hasSharers() &&
1973 DPRINTF(CacheVerbose,
"%s: packet %s found block: %s\n",
1978 writebacks.push_back(wb_pkt);
2016 warn(
"*** The cache still contains dirty data. ***\n");
2017 warn(
" Make sure to drain the system using the correct flags.\n");
2018 warn(
" This checkpoint will not restore correctly " \
2019 "and dirty data in the cache will be lost!\n");
2026 bool bad_checkpoint(dirty);
2033 bool bad_checkpoint;
2035 if (bad_checkpoint) {
2036 fatal(
"Restoring from checkpoints with dirty caches is not "
2037 "supported in the classic memory system. Please remove any "
2038 "caches or drain them properly before taking checkpoints.\n");
2044 const std::string &
name)
2046 ADD_STAT(hits, statistics::units::Count::get(),
2047 (
"number of " +
name +
" hits").c_str()),
2048 ADD_STAT(misses, statistics::units::Count::get(),
2049 (
"number of " +
name +
" misses").c_str()),
2051 (
"number of " +
name +
" hit ticks").c_str()),
2053 (
"number of " +
name +
" miss ticks").c_str()),
2054 ADD_STAT(accesses, statistics::units::Count::get(),
2055 (
"number of " +
name +
" accesses(hits+misses)").c_str()),
2056 ADD_STAT(missRate, statistics::units::Ratio::get(),
2057 (
"miss rate for " +
name +
" accesses").c_str()),
2058 ADD_STAT(avgMissLatency, statistics::units::Rate<
2059 statistics::units::
Tick, statistics::units::Count>::get(),
2060 (
"average " +
name +
" miss latency").c_str()),
2061 ADD_STAT(mshrHits, statistics::units::Count::get(),
2062 (
"number of " +
name +
" MSHR hits").c_str()),
2063 ADD_STAT(mshrMisses, statistics::units::Count::get(),
2064 (
"number of " +
name +
" MSHR misses").c_str()),
2065 ADD_STAT(mshrUncacheable, statistics::units::Count::get(),
2066 (
"number of " +
name +
" MSHR uncacheable").c_str()),
2067 ADD_STAT(mshrMissLatency, statistics::units::
Tick::get(),
2068 (
"number of " +
name +
" MSHR miss ticks").c_str()),
2069 ADD_STAT(mshrUncacheableLatency, statistics::units::
Tick::get(),
2070 (
"number of " +
name +
" MSHR uncacheable ticks").c_str()),
2071 ADD_STAT(mshrMissRate, statistics::units::Ratio::get(),
2072 (
"mshr miss rate for " +
name +
" accesses").c_str()),
2073 ADD_STAT(avgMshrMissLatency, statistics::units::Rate<
2074 statistics::units::
Tick, statistics::units::Count>::get(),
2075 (
"average " +
name +
" mshr miss latency").c_str()),
2076 ADD_STAT(avgMshrUncacheableLatency, statistics::units::Rate<
2077 statistics::units::
Tick, statistics::units::Count>::get(),
2078 (
"average " +
name +
" mshr uncacheable latency").c_str())
2085 using namespace statistics;
2092 .init(max_requestors)
2095 for (
int i = 0;
i < max_requestors;
i++) {
2101 .init(max_requestors)
2104 for (
int i = 0;
i < max_requestors;
i++) {
2110 .init(max_requestors)
2113 for (
int i = 0;
i < max_requestors;
i++) {
2119 .init(max_requestors)
2122 for (
int i = 0;
i < max_requestors;
i++) {
2128 accesses = hits + misses;
2129 for (
int i = 0;
i < max_requestors;
i++) {
2135 missRate = misses / accesses;
2136 for (
int i = 0;
i < max_requestors;
i++) {
2142 avgMissLatency = missLatency / misses;
2143 for (
int i = 0;
i < max_requestors;
i++) {
2150 .init(max_requestors)
2153 for (
int i = 0;
i < max_requestors;
i++) {
2159 .init(max_requestors)
2162 for (
int i = 0;
i < max_requestors;
i++) {
2168 .init(max_requestors)
2171 for (
int i = 0;
i < max_requestors;
i++) {
2177 .init(max_requestors)
2180 for (
int i = 0;
i < max_requestors;
i++) {
2185 mshrUncacheableLatency
2186 .init(max_requestors)
2189 for (
int i = 0;
i < max_requestors;
i++) {
2195 mshrMissRate = mshrMisses / accesses;
2197 for (
int i = 0;
i < max_requestors;
i++) {
2203 avgMshrMissLatency = mshrMissLatency / mshrMisses;
2204 for (
int i = 0;
i < max_requestors;
i++) {
2210 avgMshrUncacheableLatency = mshrUncacheableLatency / mshrUncacheable;
2211 for (
int i = 0;
i < max_requestors;
i++) {
2217 : statistics::
Group(&
c), cache(
c),
2219 ADD_STAT(demandHits, statistics::units::Count::get(),
2220 "number of demand (read+write) hits"),
2221 ADD_STAT(overallHits, statistics::units::Count::get(),
2222 "number of overall hits"),
2223 ADD_STAT(demandHitLatency, statistics::units::
Tick::get(),
2224 "number of demand (read+write) hit ticks"),
2225 ADD_STAT(overallHitLatency, statistics::units::
Tick::get(),
2226 "number of overall hit ticks"),
2227 ADD_STAT(demandMisses, statistics::units::Count::get(),
2228 "number of demand (read+write) misses"),
2229 ADD_STAT(overallMisses, statistics::units::Count::get(),
2230 "number of overall misses"),
2231 ADD_STAT(demandMissLatency, statistics::units::
Tick::get(),
2232 "number of demand (read+write) miss ticks"),
2233 ADD_STAT(overallMissLatency, statistics::units::
Tick::get(),
2234 "number of overall miss ticks"),
2235 ADD_STAT(demandAccesses, statistics::units::Count::get(),
2236 "number of demand (read+write) accesses"),
2237 ADD_STAT(overallAccesses, statistics::units::Count::get(),
2238 "number of overall (read+write) accesses"),
2239 ADD_STAT(demandMissRate, statistics::units::Ratio::get(),
2240 "miss rate for demand accesses"),
2241 ADD_STAT(overallMissRate, statistics::units::Ratio::get(),
2242 "miss rate for overall accesses"),
2243 ADD_STAT(demandAvgMissLatency, statistics::units::Rate<
2244 statistics::units::
Tick, statistics::units::Count>::get(),
2245 "average overall miss latency in ticks"),
2246 ADD_STAT(overallAvgMissLatency, statistics::units::Rate<
2247 statistics::units::
Tick, statistics::units::Count>::get(),
2248 "average overall miss latency"),
2249 ADD_STAT(blockedCycles, statistics::units::Cycle::get(),
2250 "number of cycles access was blocked"),
2251 ADD_STAT(blockedCauses, statistics::units::Count::get(),
2252 "number of times access was blocked"),
2253 ADD_STAT(avgBlocked, statistics::units::Rate<
2254 statistics::units::Cycle, statistics::units::Count>::get(),
2255 "average number of cycles each access was blocked"),
2256 ADD_STAT(writebacks, statistics::units::Count::get(),
2257 "number of writebacks"),
2258 ADD_STAT(demandMshrHits, statistics::units::Count::get(),
2259 "number of demand (read+write) MSHR hits"),
2260 ADD_STAT(overallMshrHits, statistics::units::Count::get(),
2261 "number of overall MSHR hits"),
2262 ADD_STAT(demandMshrMisses, statistics::units::Count::get(),
2263 "number of demand (read+write) MSHR misses"),
2264 ADD_STAT(overallMshrMisses, statistics::units::Count::get(),
2265 "number of overall MSHR misses"),
2266 ADD_STAT(overallMshrUncacheable, statistics::units::Count::get(),
2267 "number of overall MSHR uncacheable misses"),
2268 ADD_STAT(demandMshrMissLatency, statistics::units::
Tick::get(),
2269 "number of demand (read+write) MSHR miss ticks"),
2270 ADD_STAT(overallMshrMissLatency, statistics::units::
Tick::get(),
2271 "number of overall MSHR miss ticks"),
2272 ADD_STAT(overallMshrUncacheableLatency, statistics::units::
Tick::get(),
2273 "number of overall MSHR uncacheable ticks"),
2274 ADD_STAT(demandMshrMissRate, statistics::units::Ratio::get(),
2275 "mshr miss ratio for demand accesses"),
2276 ADD_STAT(overallMshrMissRate, statistics::units::Ratio::get(),
2277 "mshr miss ratio for overall accesses"),
2278 ADD_STAT(demandAvgMshrMissLatency, statistics::units::Rate<
2279 statistics::units::
Tick, statistics::units::Count>::get(),
2280 "average overall mshr miss latency"),
2281 ADD_STAT(overallAvgMshrMissLatency, statistics::units::Rate<
2282 statistics::units::
Tick, statistics::units::Count>::get(),
2283 "average overall mshr miss latency"),
2284 ADD_STAT(overallAvgMshrUncacheableLatency, statistics::units::Rate<
2285 statistics::units::
Tick, statistics::units::Count>::get(),
2286 "average overall mshr uncacheable latency"),
2287 ADD_STAT(replacements, statistics::units::Count::get(),
2288 "number of replacements"),
2289 ADD_STAT(dataExpansions, statistics::units::Count::get(),
2290 "number of data expansions"),
2291 ADD_STAT(dataContractions, statistics::units::Count::get(),
2292 "number of data contractions"),
2293 cmd(
MemCmd::NUM_MEM_CMDS)
2302 using namespace statistics;
2309 for (
auto &cs : cmd)
2310 cs->regStatsFromParent();
2315#define SUM_DEMAND(s) \
2316 (cmd[MemCmd::ReadReq]->s + cmd[MemCmd::WriteReq]->s + \
2317 cmd[MemCmd::WriteLineReq]->s + cmd[MemCmd::ReadExReq]->s + \
2318 cmd[MemCmd::ReadCleanReq]->s + cmd[MemCmd::ReadSharedReq]->s)
2321#define SUM_NON_DEMAND(s) \
2322 (cmd[MemCmd::SoftPFReq]->s + cmd[MemCmd::HardPFReq]->s + \
2323 cmd[MemCmd::SoftPFExReq]->s)
2327 for (
int i = 0;
i < max_requestors;
i++) {
2333 for (
int i = 0;
i < max_requestors;
i++) {
2339 for (
int i = 0;
i < max_requestors;
i++) {
2345 for (
int i = 0;
i < max_requestors;
i++) {
2351 for (
int i = 0;
i < max_requestors;
i++) {
2356 overallMissLatency = demandMissLatency +
SUM_NON_DEMAND(missLatency);
2357 for (
int i = 0;
i < max_requestors;
i++) {
2363 for (
int i = 0;
i < max_requestors;
i++) {
2367 overallHitLatency = demandHitLatency +
SUM_NON_DEMAND(hitLatency);
2368 for (
int i = 0;
i < max_requestors;
i++) {
2373 demandAccesses = demandHits + demandMisses;
2374 for (
int i = 0;
i < max_requestors;
i++) {
2379 overallAccesses = overallHits + overallMisses;
2380 for (
int i = 0;
i < max_requestors;
i++) {
2385 demandMissRate = demandMisses / demandAccesses;
2386 for (
int i = 0;
i < max_requestors;
i++) {
2391 overallMissRate = overallMisses / overallAccesses;
2392 for (
int i = 0;
i < max_requestors;
i++) {
2397 demandAvgMissLatency = demandMissLatency / demandMisses;
2398 for (
int i = 0;
i < max_requestors;
i++) {
2403 overallAvgMissLatency = overallMissLatency / overallMisses;
2404 for (
int i = 0;
i < max_requestors;
i++) {
2425 avgBlocked = blockedCycles / blockedCauses;
2428 .init(max_requestors)
2431 for (
int i = 0;
i < max_requestors;
i++) {
2437 for (
int i = 0;
i < max_requestors;
i++) {
2443 for (
int i = 0;
i < max_requestors;
i++) {
2449 for (
int i = 0;
i < max_requestors;
i++) {
2454 overallMshrMisses = demandMshrMisses +
SUM_NON_DEMAND(mshrMisses);
2455 for (
int i = 0;
i < max_requestors;
i++) {
2460 demandMshrMissLatency =
SUM_DEMAND(mshrMissLatency);
2461 for (
int i = 0;
i < max_requestors;
i++) {
2466 overallMshrMissLatency =
2468 for (
int i = 0;
i < max_requestors;
i++) {
2473 overallMshrUncacheable =
2475 for (
int i = 0;
i < max_requestors;
i++) {
2481 overallMshrUncacheableLatency =
2484 for (
int i = 0;
i < max_requestors;
i++) {
2489 demandMshrMissRate = demandMshrMisses / demandAccesses;
2490 for (
int i = 0;
i < max_requestors;
i++) {
2495 overallMshrMissRate = overallMshrMisses / overallAccesses;
2496 for (
int i = 0;
i < max_requestors;
i++) {
2501 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
2502 for (
int i = 0;
i < max_requestors;
i++) {
2507 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
2508 for (
int i = 0;
i < max_requestors;
i++) {
2513 overallAvgMshrUncacheableLatency =
2514 overallMshrUncacheableLatency / overallMshrUncacheable;
2515 for (
int i = 0;
i < max_requestors;
i++) {
2516 overallAvgMshrUncacheableLatency.subname(
i,
2547 assert(!cache.system->bypassCaches());
2552 cache.recvTimingSnoopResp(pkt);
2563 }
else if (
blocked || mustSendRetry) {
2565 mustSendRetry =
true;
2568 mustSendRetry =
false;
2577 if (cache.system->bypassCaches()) {
2580 [[maybe_unused]]
bool success = cache.memSidePort.sendTimingReq(pkt);
2583 }
else if (tryTiming(pkt)) {
2584 cache.recvTimingReq(pkt);
2593 if (cache.system->bypassCaches()) {
2595 return cache.memSidePort.sendAtomic(pkt);
2597 return cache.recvAtomic(pkt);
2604 if (cache.system->bypassCaches()) {
2607 cache.memSidePort.sendFunctional(pkt);
2612 cache.functionalAccess(pkt,
true);
2618 return cache.getAddrRanges();
2624 const std::string &_label)
2637 cache->recvTimingResp(pkt);
2646 assert(!cache->system->bypassCaches());
2649 cache->recvTimingSnoopReq(pkt);
2656 assert(!cache->system->bypassCaches());
2658 return cache->recvAtomicSnoop(pkt);
2665 assert(!cache->system->bypassCaches());
2670 cache->functionalAccess(pkt,
false);
2677 assert(!waitingOnRetry);
2682 assert(deferredPacketReadyTime() ==
MaxTick);
2685 QueueEntry* entry = cache.getNextQueueEntry();
2704 if (!waitingOnRetry) {
2705 schedSendEvent(cache.nextQueueReadyTime());
2711 const std::string &_label)
2713 _reqQueue(*_cache, *this, _snoopRespQueue, _label),
2714 _snoopRespQueue(*_cache, *this, true, _label), cache(_cache)
2723 if (nextAddr == write_addr) {
2724 delayCtr[blk_addr] = delayThreshold;
2726 if (
mode != WriteMode::NO_ALLOCATE) {
2727 byteCount += write_size;
2730 if (
mode == WriteMode::ALLOCATE &&
2731 byteCount > coalesceLimit) {
2732 mode = WriteMode::COALESCE;
2734 }
else if (
mode == WriteMode::COALESCE &&
2735 byteCount > noAllocateLimit) {
2738 mode = WriteMode::NO_ALLOCATE;
2745 byteCount = write_size;
2746 mode = WriteMode::ALLOCATE;
2747 resetDelay(blk_addr);
2749 nextAddr = write_addr + write_size;
virtual void sendDeferredPacket()
Override the normal sendDeferredPacket and do not only consider the transmit list (used for responses...
A cache request port is used for the memory-side port of the cache, and in addition to the basic timi...
A cache response port is used for the CPU-side port of the cache, and it is basically a simple timing...
CacheResponsePort(const std::string &_name, BaseCache &_cache, const std::string &_label)
void clearBlocked()
Return to normal operation and accept new requests.
EventFunctionWrapper sendRetryEvent
void setBlocked()
Do not accept any new requests.
virtual bool recvTimingSnoopResp(PacketPtr pkt) override
Receive a timing snoop response from the peer.
virtual Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
CpuSidePort(const std::string &_name, BaseCache &_cache, const std::string &_label)
virtual bool recvTimingReq(PacketPtr pkt) override
Receive a timing request from the peer.
virtual bool tryTiming(PacketPtr pkt) override
Availability request from the peer.
virtual void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
virtual AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
virtual Tick recvAtomicSnoop(PacketPtr pkt)
Receive an atomic snoop request packet from our peer.
virtual void recvFunctionalSnoop(PacketPtr pkt)
Receive a functional snoop request packet from the peer.
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
virtual void recvTimingSnoopReq(PacketPtr pkt)
Receive a timing snoop request from the peer.
MemSidePort(const std::string &_name, BaseCache *_cache, const std::string &_label)
virtual void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk)=0
Service non-deferred MSHR targets using the received response.
virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side)
Performs the access specified by the request.
const bool isReadOnly
Is this cache read only, for example the instruction cache, or table-walker cache.
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
gem5::BaseCache::CacheAccessorImpl accessor
virtual void doWritebacks(PacketList &writebacks, Tick forward_time)=0
Insert writebacks into the write buffer.
const Cycles fillLatency
The latency to fill a cache block.
const Cycles dataLatency
The latency of data access of a cache.
void invalidateVisitor(CacheBlk &blk)
Cache block visitor that invalidates all blocks in the cache.
virtual Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks)=0
Handle a request in atomic mode that missed in this cache.
virtual void doWritebacksAtomic(PacketList &writebacks)=0
Send writebacks down the memory hierarchy in atomic mode.
void updateBlockData(CacheBlk *blk, const PacketPtr cpkt, bool has_old_data)
Update the data contents of a block.
PacketPtr tempBlockWriteback
Writebacks from the tempBlock, resulting on the response path in atomic mode, must happen after the c...
MSHR * allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send=true)
bool isDirty() const
Determine if there are any dirty blocks in the cache.
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
MSHR * noTargetMSHR
Pointer to the MSHR that has no targets.
const bool writebackClean
Determine if clean lines should be written back or not.
bool sendWriteQueuePacket(WriteQueueEntry *wq_entry)
Similar to sendMSHR, but for a write-queue entry instead.
bool inRange(Addr addr) const
Determine if an address is in the ranges covered by this cache.
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
bool forwardSnoops
Do we forward snoops from mem side port through to cpu side port?
uint64_t order
Increasing order number assigned to each incoming request.
void incHitCount(PacketPtr pkt)
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...
virtual void memWriteback() override
Write back dirty blocks in the cache using functional accesses.
bool updateCompressionData(CacheBlk *&blk, const uint64_t *data, PacketList &writebacks)
When a block is overwriten, its compression information must be updated, and it may need to be recomp...
bool isBlocked() const
Returns true if the cache is blocked for accesses.
gem5::BaseCache::CacheStats stats
const Cycles lookupLatency
The latency of tag lookup of a cache.
Cycles calculateAccessLatency(const CacheBlk *blk, const uint32_t delay, const Cycles lookup_lat) const
Calculate access latency in ticks given a tag lookup latency, and whether access was a hit or miss.
Tick nextQueueReadyTime() const
Find next request ready time from among possible sources.
void regProbePoints() override
Registers probes.
virtual void memInvalidate() override
Invalidates all blocks in the cache.
MSHRQueue mshrQueue
Miss status registers.
virtual PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const =0
Create an appropriate downstream bus request packet.
ProbePointArg< CacheAccessProbeArg > * ppFill
To probe when a cache fill occurs.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
QueueEntry * getNextQueueEntry()
Return the next queue entry to service, either a pending miss from the MSHR queue,...
void handleUncacheableWriteResp(PacketPtr pkt)
Handling the special case of uncacheable write responses to make recvTimingResp less cluttered.
const unsigned blkSize
Block size of this cache.
void writebackTempBlockAtomic()
Send the outstanding tempBlock writeback.
const Cycles forwardLatency
This is the forward latency of the cache.
compression::Base * compressor
Compression method being used.
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
Create a writeclean request for the given block.
void schedMemSideSendEvent(Tick time)
Schedule a send event for the memory-side port.
virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void cmpAndSwap(CacheBlk *blk, PacketPtr pkt)
Handle doing the Compare and Swap function for SPARC.
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks)
Does all the processing necessary to perform the provided request.
void setBlocked(BlockedCause cause)
Marks the access path of the cache as blocked for the given cause.
BaseCache(const BaseCacheParams &p, unsigned blk_size)
Addr regenerateBlkAddr(CacheBlk *blk)
Regenerate block address using tags.
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
CacheBlk * allocateBlock(const PacketPtr pkt, PacketList &writebacks)
Allocate a new block and perform any necessary writebacks.
ProbePointArg< CacheDataUpdateProbeArg > * ppDataUpdate
To probe when the contents of a block are updated.
prefetch::Base * prefetcher
Prefetcher.
uint8_t blocked
Bit vector of the blocking reasons for the access path.
TempCacheBlk * tempBlock
Temporary cache block for occasional transitory use.
const AddrRangeList addrRanges
The address range to which the cache responds on the CPU side.
ProbePointArg< CacheAccessProbeArg > * ppHit
To probe when a cache hit occurs.
const int numTarget
The number of targets for each MSHR.
const bool moveContractions
Similar to data expansions, after a block improves its compression, it may need to be moved elsewhere...
WriteAllocator *const writeAllocator
The writeAllocator drive optimizations for streaming writes.
void markInService(MSHR *mshr, bool pending_modified_resp)
Mark a request as in service (sent downstream in the memory system), effectively making this MSHR the...
void allocateWriteBuffer(PacketPtr pkt, Tick time)
Cycles calculateTagOnlyLatency(const uint32_t delay, const Cycles lookup_lat) const
Calculate latency of accesses that only touch the tag array.
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
void incMissCount(PacketPtr pkt)
WriteQueue writeBuffer
Write/writeback buffer.
const bool replaceExpansions
when a data expansion of a compressed block happens it will not be able to co-allocate where it is at...
void serialize(CheckpointOut &cp) const override
Serialize the state of the caches.
bool coalesce() const
Checks if the cache is coalescing writes.
const bool sequentialAccess
Whether tags and data are accessed sequentially.
bool handleEvictions(std::vector< CacheBlk * > &evict_blks, PacketList &writebacks)
Try to evict the given blocks.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
void clearBlocked(BlockedCause cause)
Marks the cache as unblocked for the given cause.
virtual PacketPtr evictBlock(CacheBlk *blk)=0
Evict a cache block.
void writebackVisitor(CacheBlk &blk)
Cache block visitor that writes back dirty cache blocks using functional writes.
EventFunctionWrapper writebackTempBlockAtomicEvent
An event to writeback the tempBlock after recvAtomic finishes.
BaseTags * tags
Tag and data Storage.
const enums::Clusivity clusivity
Clusivity with respect to the upstream cache, determining if we fill into both this cache and the cac...
ProbePointArg< CacheAccessProbeArg > * ppMiss
To probe when a cache miss occurs.
virtual bool sendMSHRQueuePacket(MSHR *mshr)
Take an MSHR, turn it into a suitable downstream packet, and send it out.
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
System * system
System we are currently operating in.
partitioning_policy::PartitionManager * partitionManager
Partitioning manager.
Information provided to probes on a cache event.
Simple class to provide virtual print() method on cache blocks without allocating a vtable pointer fo...
void setWhenReady(const Tick tick)
Set tick at which block's data will be available for access.
@ ReadableBit
Read permission.
@ WritableBit
write permission
@ DirtyBit
dirty (modified)
uint32_t getSrcRequestorId() const
Get the requestor id associated to this block.
Tick getWhenReady() const
Get tick at which block's data will be available for access.
void clearPrefetched()
Clear the prefetching bit.
uint64_t getPartitionId() const
Getter for _partitionId.
std::string print() const override
Pretty-print tag, set and way, and interpret state bits to readable form including mapping to a MOESI...
bool isSet(unsigned bits) const
Checks the given coherence bits are set.
bool checkWrite(PacketPtr pkt)
Handle interaction of load-locked operations and stores.
void clearCoherenceBits(unsigned bits)
Clear the corresponding coherence bits.
uint32_t getTaskId() const
Get the task id associated to this block.
void trackLoadLocked(PacketPtr pkt)
Track the fact that a local locked was issued to the block.
bool wasPrefetched() const
Check if this block was the result of a hardware prefetch, yet to be touched.
uint8_t * data
Contains a copy of the data in this block for easy access.
void setCoherenceBits(unsigned bits)
Sets the corresponding coherence bits.
A coherent cache that can be arranged in flexible topologies.
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
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...
Tick cyclesToTicks(Cycles c) const
Cycles ticksToCycles(Tick t) const
A superblock is composed of sub-blocks, and each sub-block has information regarding its superblock a...
std::size_t getSizeBits() const
void setSizeBits(const std::size_t size)
Set size, in bits, of this compressed block's data.
void setDecompressionLatency(const Cycles lat)
Set number of cycles needed to decompress this block.
OverwriteType
When an overwrite happens, the data size may change an not fit in its current container any longer.
@ DATA_EXPANSION
New data contents are considered larger than previous contents.
@ DATA_CONTRACTION
New data contents are considered smaller than previous contents.
OverwriteType checkExpansionContraction(const std::size_t size) const
Determines if changing the size of the block will cause a data expansion (new size is bigger) or cont...
Cycles is a wrapper class for representing cycle counts, i.e.
void delay(MSHR *mshr, Tick delay_ticks)
Adds a delay to the provided MSHR and moves MSHRs that will be ready earlier than this entry to the t...
void deallocate(MSHR *mshr) override
Deallocate a MSHR and its targets.
bool canPrefetch() const
Returns true if sufficient mshrs for prefetch.
void markPending(MSHR *mshr)
Mark an in service entry as pending, used to resend a request.
void markInService(MSHR *mshr, bool pending_modified_resp)
Mark the given MSHR as in service.
Miss Status and handling Register.
bool wasWholeLineWrite
Track if we sent this as a whole line write or not.
bool isPendingModified() const
void promoteReadable()
Promotes deferred targets that do not require writable.
int getNumTargets() const
Returns the current number of allocated targets.
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
bool needsWritable() const
The pending* and post* flags are only valid if inService is true.
bool isForward
True if the entry is just a simple forward from an upper level.
bool hasLockedRMWReadTarget()
Determine if there are any LockedRMWReads in the Targets list.
bool promoteDeferredTargets()
bool isWholeLineWrite() const
Check if this MSHR contains only compatible writes, and if they span the entire cache line.
void allocateTarget(PacketPtr target, Tick when, Counter order, bool alloc_on_fill)
Add a request to the list of targets.
void promoteWritable()
Promotes deferred targets that do not require writable.
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void writeDataToBlock(uint8_t *blk_data, int blkSize) const
Copy data from the packet to the provided block pointer, which is aligned to the given block size.
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
void setWriteThrough()
A writeback/writeclean cmd gets propagated further downstream by the receiver when the flag is set.
void makeTimingResponse()
bool needsWritable() const
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
bool isCleanEviction() const
Is this packet a clean eviction, including both actual clean evict packets, but also clean writebacks...
bool needsResponse() const
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
SenderState * senderState
This packet's sender state.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Addr getOffset(unsigned int blk_size) const
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
bool writeThrough() const
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
void setDataFromBlock(const uint8_t *blk_data, int blkSize)
Copy data into the packet from the provided block pointer, which is aligned to the given block size.
bool trySatisfyFunctional(PacketPtr other)
Check a functional request against a memory value stored in another packet (i.e.
Addr getBlockAddr(unsigned int blk_size) const
RequestPtr req
A pointer to the original request.
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
void setCacheResponding()
Snoop flags.
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
bool isExpressSnoop() const
const T * getConstPtr() const
void setHasSharers()
On fills, the hasSharers flag is used by the caches in combination with the cacheResponding flag,...
bool cacheResponding() const
void makeAtomicResponse()
void setSatisfied()
Set when a request hits in a cache and the cache is not going to respond.
MemCmd cmd
The command field of the packet.
bool isInvalidate() const
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
void allocate()
Allocate memory for the packet.
Ports are used to interface objects to each other.
bool isConnected() const
Is this port currently connected to a peer?
ProbePointArg generates a point for the class of Arg.
A queue entry is holding packets that will be serviced as soon as resources are available.
const Tick recvTime
Time when request was received (for stats)
PacketPtr pkt
Pending request packet.
A queue entry base class, to be used by both the MSHRs and write-queue entries.
virtual bool sendPacket(BaseCache &cache)=0
Send this queue entry as a downstream packet, with the exact behaviour depending on the specific entr...
virtual Target * getTarget()=0
Returns a pointer to the first target.
Addr blkAddr
Block aligned address.
Counter order
Order number assigned to disambiguate writes and misses.
bool inService
True if the entry has been sent downstream.
bool isSecure
True if the entry targets the secure memory space.
Entry * findMatch(Addr blk_addr, bool is_secure, bool ignore_uncacheable=true) const
Find the first entry that matches the provided address.
Entry * findPending(const QueueEntry *entry) const
Find any pending requests that overlap the given request of a different queue.
bool trySatisfyFunctional(PacketPtr pkt)
Tick nextReadyTime() const
Entry * getNext() const
Returns the WriteQueueEntry at the head of the readyList.
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
bool trySatisfyFunctional(PacketPtr pkt)
Check the list of buffered packets against the supplied functional request.
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
@ SECURE
The request targets the secure memory space.
@ funcRequestorId
This requestor id is used for functional requests that don't come from a particular device.
@ wbRequestorId
This requestor id is used for writeback requests by the caches.
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
bool isSnooping() const
Find out if the peer request port is snooping or not.
void sendRangeChange() const
Called by the owner to send a range change.
std::vector< SectorSubBlk * > blks
List of blocks associated to this sector.
SectorBlk * getSectorBlock() const
Get sector block associated to this block.
A basic compression superblock.
std::string getRequestorName(RequestorID requestor_id)
Get the name of an object for a given request id.
RequestorID maxRequestors()
Get the number of requestors registered in the system.
virtual bool isValid() const
Checks if the entry is valid.
bool isSecure() const
Check if this block holds data from the secure memory space.
Special instance of CacheBlk for use with tempBlk that deals with its block address regeneration.
Addr getAddr() const
Get block's address.
void invalidate() override
Invalidate the block and clear all state.
void insert(const KeyType &tag) override
Insert the block by assigning it a tag and marking it valid.
bool coalesce() const
Should writes be coalesced? This is true if the mode is set to NO_ALLOCATE.
bool delay(Addr blk_addr)
Access whether we need to delay the current write.
void reset()
Reset the write allocator state, meaning that it allocates for writes and has not recorded any inform...
bool allocate() const
Should writes allocate?
void updateMode(Addr write_addr, unsigned write_size, Addr blk_addr)
Update the write mode based on the current write packet.
void resetDelay(Addr blk_addr)
Clear delay counter for the input block.
int getNumTargets() const
Returns the current number of allocated targets.
Target * getTarget() override
Returns a reference to the first target.
Cycles getDecompressionLatency(const CacheBlk *blk)
Get the decompression latency if the block is compressed.
static void setSizeBits(CacheBlk *blk, const std::size_t size_bits)
Set the size of the compressed block, in bits.
static void setDecompressionLatency(CacheBlk *blk, const Cycles lat)
Set the decompression latency of compressed block.
virtual std::unique_ptr< CompressionData > compress(const std::vector< Chunk > &chunks, Cycles &comp_lat, Cycles &decomp_lat)=0
Apply the compression process to the cache line.
virtual uint64_t readPacketPartitionID(PacketPtr pkt) const
PartitionManager interface to retrieve PartitionID from a packet; This base implementation returns ze...
void incrDemandMhsrMisses()
virtual PacketPtr getPacket()=0
virtual Tick nextPrefetchReadyTime() const =0
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
static const Priority Delayed_Writeback_Pri
For some reason "delayed" inter-cluster writebacks are scheduled before regular writebacks (which hav...
void deschedule(Event &event)
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define gem5_assert(cond,...)
The assert macro will function like a normal assert, but will use panic instead of straight abort().
#define fatal(...)
This implements a cprintf based fatal() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
ProbeManager * getProbeManager()
Get the probe manager for this object.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
virtual void regStats()
Callback to set stat parameters.
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
#define SUM_NON_DEMAND(s)
Declares a basic cache interface BaseCache.
Definition of a basic cache compressor.
Miss and writeback queue declarations.
Miss Status and Handling Register (MSHR) declaration.
const FlagsType nonan
Don't print if this is NAN.
const FlagsType nozero
Don't print if this is zero.
const FlagsType total
Print the total.
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< Request > RequestPtr
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
uint64_t Tick
Tick count type.
static constexpr auto genTagExtractor(BTBIndexingPolicy *ip)
This helper generates a tag extractor function object which will be typically used by Replaceable ent...
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
void regStatsFromParent()
Callback to register stats from parent CacheStats::regStats().
statistics::Vector mshrUncacheableLatency
Total tick latency of each MSHR miss, per command and thread.
statistics::Vector mshrHits
Number of misses that hit in the MSHRs per command and thread.
CacheCmdStats(BaseCache &c, const std::string &name)
statistics::Vector mshrMisses
Number of misses that miss in the MSHRs, per command and thread.
statistics::Vector mshrMissLatency
Total tick latency of each MSHR miss, per command and thread.
statistics::Scalar replacements
Number of replacements of valid blocks.
statistics::Scalar dataContractions
Number of data contractions (blocks that had their compression factor improved).
void regStats() override
Callback to set stat parameters.
statistics::Scalar dataExpansions
Number of data expansions.
std::vector< std::unique_ptr< CacheCmdStats > > cmd
Per-command statistics.
statistics::Vector writebacks
Number of blocks written back per thread.
CacheCmdStats & cmdStats(const PacketPtr p)
A data contents update is composed of the updated block's address, the old contents,...
bool hwPrefetched
Set if the update is from a prefetch or evicting a prefetched block that was never used.
std::vector< uint64_t > newData
The new data contents.
std::vector< uint64_t > oldData
The stale data contents.
Copyright (c) 2018 Inria All rights reserved.
const std::string & name()