forwardLatency(p->tag_latency),
fillLatency(p->data_latency),
responseLatency(p->response_latency),
+ sequentialAccess(p->sequential_access),
numTarget(p->tgts_per_mshr),
forwardSnoops(true),
clusivity(p->clusivity),
// In this case we are considering request_time that takes
// into account the delay of the xbar, if any, and just
// lat, neglecting responseLatency, modelling hit latency
- // just as lookupLatency or or the value of lat overriden
- // by access(), that calls accessBlock() function.
+ // just as the value of lat overriden by access(), which calls
+ // the calculateAccessLatency() function.
cpuSidePort.schedTimingResp(pkt, request_time, true);
} else {
DPRINTF(Cache, "%s satisfied %s, no response needed\n", __func__,
// the delay provided by the crossbar
Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay;
- // We use lookupLatency here because it is used to specify the latency
- // to access.
- Cycles lat = lookupLatency;
+ Cycles lat;
CacheBlk *blk = nullptr;
bool satisfied = false;
{
PacketList writebacks;
// Note that lat is passed by reference here. The function
- // access() calls accessBlock() which can modify lat value.
+ // access() will set the lat value.
satisfied = access(pkt, blk, lat, writebacks);
// copy writebacks to write buffer here to ensure they logically
// Here we charge the headerDelay that takes into account the latencies
// of the bus, if the packet comes from it.
- // The latency charged it is just lat that is the value of lookupLatency
- // modified by access() function, or if not just lookupLatency.
+ // The latency charged is just the value set by the access() function.
// In case of a hit we are neglecting response latency.
// In case of a miss we are neglecting forward latency.
Tick request_time = clockEdge(lat) + pkt->headerDelay;
// Access path: requests coming in from the CPU side
//
/////////////////////////////////////////////////////
+Cycles
+BaseCache::calculateAccessLatency(const CacheBlk* blk,
+ const Cycles lookup_lat) const
+{
+ Cycles lat(lookup_lat);
+
+ if (blk != nullptr) {
+ // First access tags, then data
+ if (sequentialAccess) {
+ lat += dataLatency;
+ // Latency is dictated by the slowest of tag and data latencies
+ } else {
+ lat = std::max(lookup_lat, dataLatency);
+ }
+
+ // Check if the block to be accessed is available. If not, apply the
+ // access latency on top of block->whenReady.
+ if (blk->whenReady > curTick() &&
+ ticksToCycles(blk->whenReady - curTick()) > lat) {
+ lat += ticksToCycles(blk->whenReady - curTick());
+ }
+ }
+
+ return lat;
+}
bool
BaseCache::access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat,
"Should never see a write in a read-only cache %s\n",
name());
- // Here lat is the value passed as parameter to accessBlock() function
- // that can modify its value.
- blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), lat);
+ // Access block in the tags
+ Cycles tag_latency(0);
+ blk = tags->accessBlock(pkt->getAddr(), pkt->isSecure(), tag_latency);
+
+ // Calculate access latency
+ lat = calculateAccessLatency(blk, tag_latency);
DPRINTF(Cache, "%s for %s %s\n", __func__, pkt->print(),
blk ? "hit " + blk->print() : "miss");
*/
Addr regenerateBlkAddr(CacheBlk* blk);
+ /**
+ * Calculate access latency in ticks given a tag lookup latency, and
+ * whether access was a hit or miss.
+ *
+ * @param blk The cache block that was accessed.
+ * @param lookup_lat Latency of the respective tag lookup.
+ * @return The number of ticks that pass due to a block access.
+ */
+ Cycles calculateAccessLatency(const CacheBlk* blk,
+ const Cycles lookup_lat) const;
+
/**
* Does all the processing necessary to perform the provided request.
* @param pkt The memory request to perform.
*/
const Cycles responseLatency;
+ /**
+ * Whether tags and data are accessed sequentially.
+ */
+ const bool sequentialAccess;
+
/** The number of targets for each MSHR. */
const int numTarget;
tag_latency = Param.Cycles(Parent.tag_latency,
"The tag lookup latency for this cache")
- # Get the RAM access latency from the parent (cache)
- data_latency = Param.Cycles(Parent.data_latency,
- "The data access latency for this cache")
-
# Get the warmup percentage from the parent (cache)
warmup_percentage = Param.Percent(Parent.warmup_percentage,
"Percentage of tags to be touched to warm up the cache")
BaseTags::BaseTags(const Params *p)
: ClockedObject(p), blkSize(p->block_size), blkMask(blkSize - 1),
- size(p->size),
- lookupLatency(p->tag_latency),
- accessLatency(p->sequential_access ?
- p->tag_latency + p->data_latency :
- std::max(p->tag_latency, p->data_latency)),
+ size(p->size), lookupLatency(p->tag_latency),
cache(nullptr), indexingPolicy(p->indexing_policy),
warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)),
warmedUp(false), numBlocks(p->size / p->block_size),
const unsigned size;
/** The tag lookup latency of the cache. */
const Cycles lookupLatency;
- /**
- * The total access latency of the cache. This latency
- * is different depending on the cache access mode
- * (parallel or sequential)
- */
- const Cycles accessLatency;
+
/** Pointer to the parent cache. */
BaseCache *cache;
virtual CacheBlk* findVictim(Addr addr, const bool is_secure,
std::vector<CacheBlk*>& evict_blks) const = 0;
+ /**
+ * Access block and update replacement data. May not succeed, in which case
+ * nullptr is returned. This has all the implications of a cache access and
+ * should only be used as such. Returns the tag lookup latency as a side
+ * effect.
+ *
+ * @param addr The address to find.
+ * @param is_secure True if the target memory space is secure.
+ * @param lat The latency of the tag lookup.
+ * @return Pointer to the cache block if found.
+ */
virtual CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) = 0;
/**
/**
* Access block and update replacement data. May not succeed, in which case
- * nullptr is returned. This has all the implications of a cache
- * access and should only be used as such. Returns the access latency as a
- * side effect.
+ * nullptr is returned. This has all the implications of a cache access and
+ * should only be used as such. Returns the tag lookup latency as a side
+ * effect.
+ *
* @param addr The address to find.
* @param is_secure True if the target memory space is secure.
- * @param lat The access latency.
+ * @param lat The latency of the tag lookup.
* @return Pointer to the cache block if found.
*/
CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) override
dataAccesses += allocAssoc;
}
+ // If a cache hit
if (blk != nullptr) {
- // If a cache hit
- lat = accessLatency;
- // Check if the block to be accessed is available. If not,
- // apply the accessLatency on top of block->whenReady.
- if (blk->whenReady > curTick() &&
- cache->ticksToCycles(blk->whenReady - curTick()) >
- accessLatency) {
- lat = cache->ticksToCycles(blk->whenReady - curTick()) +
- accessLatency;
- }
-
// Update number of references to accessed block
blk->refCount++;
// Update replacement data of accessed block
replacementPolicy->touch(blk->replacementData);
- } else {
- // If a cache miss
- lat = lookupLatency;
}
+ // The tag lookup latency is the same for a hit or a miss
+ lat = lookupLatency;
+
return blk;
}
CachesMask mask = 0;
FALRUBlk* blk = static_cast<FALRUBlk*>(findBlock(addr, is_secure));
+ // If a cache hit
if (blk && blk->isValid()) {
- // If a cache hit
- lat = accessLatency;
- // Check if the block to be accessed is available. If not,
- // apply the accessLatency on top of block->whenReady.
- if (blk->whenReady > curTick() &&
- cache->ticksToCycles(blk->whenReady - curTick()) >
- accessLatency) {
- lat = cache->ticksToCycles(blk->whenReady - curTick()) +
- accessLatency;
- }
mask = blk->inCachesMask;
moveToHead(blk);
- } else {
- // If a cache miss
- lat = lookupLatency;
}
+
if (in_caches_mask) {
*in_caches_mask = mask;
}
cacheTracking.recordAccess(blk);
+ // The tag lookup latency is the same for a hit or a miss
+ lat = lookupLatency;
+
return blk;
}
* Access block and update replacement data. May not succeed, in which
* case nullptr pointer is returned. This has all the implications of a
* cache access and should only be used as such.
- * Returns the access latency and inCachesMask flags as a side effect.
+ * Returns tag lookup latency and the inCachesMask flags as a side effect.
+ *
* @param addr The address to look for.
* @param is_secure True if the target memory space is secure.
- * @param lat The latency of the access.
+ * @param lat The latency of the tag lookup.
* @param in_cache_mask Mask indicating the caches in which the blk fits.
* @return Pointer to the cache block.
*/
dataAccesses += allocAssoc*numBlocksPerSector;
}
+ // If a cache hit
if (blk != nullptr) {
- // If a cache hit
- lat = accessLatency;
- // Check if the block to be accessed is available. If not,
- // apply the accessLatency on top of block->whenReady.
- if (blk->whenReady > curTick() &&
- cache->ticksToCycles(blk->whenReady - curTick()) >
- accessLatency) {
- lat = cache->ticksToCycles(blk->whenReady - curTick()) +
- accessLatency;
- }
-
// Update number of references to accessed block
blk->refCount++;
// Update replacement data of accessed block, which is shared with
// the whole sector it belongs to
replacementPolicy->touch(sector_blk->replacementData);
- } else {
- // If a cache miss
- lat = lookupLatency;
}
+ // The tag lookup latency is the same for a hit or a miss
+ lat = lookupLatency;
+
return blk;
}
/**
* Access block and update replacement data. May not succeed, in which
* case nullptr is returned. This has all the implications of a cache
- * access and should only be used as such. Returns the access latency
+ * access and should only be used as such. Returns the tag lookup latency
* as a side effect.
*
* @param addr The address to find.
* @param is_secure True if the target memory space is secure.
- * @param lat The access latency.
+ * @param lat The latency of the tag lookup.
* @return Pointer to the cache block if found.
*/
CacheBlk* accessBlock(Addr addr, bool is_secure, Cycles &lat) override;