47#include "debug/HtmMem.hh"
48#include "debug/RubyCache.hh"
49#include "debug/RubyCacheTrace.hh"
50#include "debug/RubyResourceStalls.hh"
51#include "debug/RubyStats.hh"
53#include "mem/ruby/protocol/AccessPermission.hh"
72 dataArray(
p.dataArrayBanks,
p.dataAccessLatency,
73 p.start_index_bit,
p.ruby_system),
74 tagArray(
p.tagArrayBanks,
p.tagAccessLatency,
75 p.start_index_bit,
p.ruby_system),
76 atomicALUArray(
p.atomicALUs,
p.atomicLatency *
77 p.ruby_system->clockPeriod()),
78 cacheMemoryStats(this)
144 if (
m_cache[cacheSet][it->second]->m_Permission !=
145 AccessPermission_NotPresent)
191 DPRINTF(RubyCache,
"trying to access address: %#x\n", address);
193 if (entry !=
nullptr) {
199 if (entry->
m_Permission == AccessPermission_Read_Write) {
200 DPRINTF(RubyCache,
"Have permission to access address: %#x\n",
204 if ((entry->
m_Permission == AccessPermission_Read_Only) &&
205 (
type == RubyRequestType_LD ||
type == RubyRequestType_IFETCH)) {
206 DPRINTF(RubyCache,
"Have permission to access address: %#x\n",
212 DPRINTF(RubyCache,
"Do not have permission to access address: %#x\n",
222 DPRINTF(RubyCache,
"testing address: %#x\n", address);
224 if (entry !=
nullptr) {
230 DPRINTF(RubyCache,
"have permission for address %#x?: %d\n",
233 return entry->
m_Permission != AccessPermission_NotPresent;
236 DPRINTF(RubyCache,
"do not have permission for address %#x\n",
247 if (entry ==
nullptr) {
249 DPRINTF(RubyCache,
"No tag match for address: %#x\n", address);
252 DPRINTF(RubyCache,
"address: %#x found\n", address);
287 DPRINTF(RubyCache,
"allocating address: %#x\n", address);
293 if (!
set[
i] ||
set[
i]->m_Permission == AccessPermission_NotPresent) {
295 warn_once(
"This protocol contains a cache entry handling bug: "
296 "Entries in the cache should never be NotPresent! If\n"
297 "this entry (%#x) is not tracked elsewhere, it will memory "
298 "leak here. Fix your protocol to eliminate these!",
303 set[
i]->m_Permission = AccessPermission_Invalid;
304 DPRINTF(RubyCache,
"Allocate clearing lock for addr: 0x%x\n",
306 set[
i]->m_locked = -1;
308 set[
i]->setPosition(cacheSet,
i);
319 panic(
"Allocate didn't find an available entry");
325 DPRINTF(RubyCache,
"deallocating address: %#x\n", address);
327 assert(entry !=
nullptr);
329 uint32_t cache_set = entry->
getSet();
330 uint32_t way = entry->
getWay();
332 m_cache[cache_set][way] = NULL;
350 getVictim(candidates)->getWay()]->m_Address;
360 if (loc == -1)
return NULL;
371 if (loc == -1)
return NULL;
380 if (entry !=
nullptr) {
389 assert(entry !=
nullptr);
398 if (entry !=
nullptr) {
430 uint64_t warmedUpBlocks = 0;
438 RubyRequestType request_type = RubyRequestType_NULL;
439 if (
perm == AccessPermission_Read_Only) {
441 request_type = RubyRequestType_IFETCH;
443 request_type = RubyRequestType_LD;
445 }
else if (
perm == AccessPermission_Read_Write) {
446 request_type = RubyRequestType_ST;
449 if (request_type != RubyRequestType_NULL) {
451 lastAccessTick =
m_cache[
i][j]->getLastAccess();
453 0, request_type, lastAccessTick,
461 DPRINTF(RubyCacheTrace,
"%s: %lli blocks of %lli total blocks"
462 "recorded %.2f%% \n",
name().c_str(), warmedUpBlocks,
463 totalBlocks, (
float(warmedUpBlocks) /
float(totalBlocks)) * 100.0);
469 out <<
"Cache dump: " <<
name() << std::endl;
473 out <<
" Index: " <<
i
475 <<
" entry: " << *
m_cache[
i][j] << std::endl;
477 out <<
" Index: " <<
i
479 <<
" entry: NULL" << std::endl;
488 out <<
"printData() not supported" << std::endl;
494 DPRINTF(RubyCache,
"Setting Lock for addr: %#x to %d\n", address, context);
496 assert(entry !=
nullptr);
503 DPRINTF(RubyCache,
"Clear Lock for addr: %#x\n", address);
505 assert(entry !=
nullptr);
515 for (
auto j =
set.begin(); j !=
set.end(); ++j) {
517 if (line && line->
isLocked(context)) {
518 DPRINTF(RubyCache,
"Clear Lock for addr: %#x\n",
530 assert(entry !=
nullptr);
531 DPRINTF(RubyCache,
"Testing Lock for addr: %#llx cur %d con %d\n",
538 : statistics::
Group(parent),
539 ADD_STAT(numDataArrayReads,
"Number of data array reads"),
540 ADD_STAT(numDataArrayWrites,
"Number of data array writes"),
541 ADD_STAT(numTagArrayReads,
"Number of tag array reads"),
542 ADD_STAT(numTagArrayWrites,
"Number of tag array writes"),
543 ADD_STAT(numTagArrayStalls,
"Number of stalls caused by tag array"),
544 ADD_STAT(numDataArrayStalls,
"Number of stalls caused by data array"),
545 ADD_STAT(numAtomicALUOperations,
"Number of atomic ALU operations"),
546 ADD_STAT(numAtomicALUArrayStalls,
"Number of stalls caused by atomic ALU array"),
547 ADD_STAT(htmTransCommitReadSet,
"Read set size of a committed "
549 ADD_STAT(htmTransCommitWriteSet,
"Write set size of a committed "
551 ADD_STAT(htmTransAbortReadSet,
"Read set size of a aborted transaction"),
552 ADD_STAT(htmTransAbortWriteSet,
"Write set size of a aborted "
554 ADD_STAT(m_demand_hits,
"Number of cache demand hits"),
555 ADD_STAT(m_demand_misses,
"Number of cache demand misses"),
556 ADD_STAT(m_demand_accesses,
"Number of cache demand accesses",
557 m_demand_hits + m_demand_misses),
558 ADD_STAT(m_prefetch_hits,
"Number of cache prefetch hits"),
559 ADD_STAT(m_prefetch_misses,
"Number of cache prefetch misses"),
560 ADD_STAT(m_prefetch_accesses,
"Number of cache prefetch accesses",
561 m_prefetch_hits + m_prefetch_misses),
618 .
init(RubyRequestType_NUM)
621 for (
int i = 0;
i < RubyAccessMode_NUM;
i++) {
623 .
subname(
i, RubyAccessMode_to_string(RubyAccessMode(
i)))
634 DPRINTF(RubyStats,
"Recorded statistic: %s\n",
635 CacheRequestType_to_string(requestType));
636 switch(requestType) {
637 case CacheRequestType_DataArrayRead:
642 case CacheRequestType_DataArrayWrite:
647 case CacheRequestType_TagArrayRead:
652 case CacheRequestType_TagArrayWrite:
657 case CacheRequestType_AtomicALUOperation:
663 warn(
"CacheMemory access_type not found: %s",
664 CacheRequestType_to_string(requestType));
675 if (res == CacheResourceType_TagArray) {
679 "Tag array stall on addr %#x in set %d\n",
684 }
else if (res == CacheResourceType_DataArray) {
688 "Data array stall on addr %#x in set %d\n",
693 }
else if (res == CacheResourceType_AtomicALUArray) {
697 "Atomic ALU array stall on addr %#x in line address %#x\n",
703 panic(
"Unrecognized cache resource type.");
710 return (
m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
716 return (
m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
724 uint64_t htmReadSetSize = 0;
725 uint64_t htmWriteSetSize = 0;
732 for (
auto j =
set.begin(); j !=
set.end(); ++j)
736 if (line !=
nullptr) {
751 DPRINTF(HtmMem,
"htmAbortTransaction: read set=%u write set=%u\n",
752 htmReadSetSize, htmWriteSetSize);
758 uint64_t htmReadSetSize = 0;
759 uint64_t htmWriteSetSize = 0;
766 for (
auto j =
set.begin(); j !=
set.end(); ++j)
769 if (line !=
nullptr) {
781 DPRINTF(HtmMem,
"htmCommitTransaction: read set=%u write set=%u\n",
782 htmReadSetSize, htmWriteSetSize);
virtual std::string name() const
A replaceable entry is a basic entry in a 2d table-like structure that needs to have replacement func...
std::shared_ptr< replacement_policy::ReplacementData > replacementData
Replacement data associated to this entry.
uint32_t getWay() const
Get way number.
uint32_t getSet() const
Get set number.
Abstract superclass for simulation objects.
virtual void invalidate(const std::shared_ptr< ReplacementData > &replacement_data)=0
Invalidate replacement data to set it as the next probable victim.
virtual void reset(const std::shared_ptr< ReplacementData > &replacement_data, const PacketPtr pkt)
Reset replacement data.
virtual void touch(const std::shared_ptr< ReplacementData > &replacement_data, const PacketPtr pkt)
Update replacement data.
virtual std::shared_ptr< ReplacementData > instantiateEntry()=0
Instantiate a replacement data entry.
bool tryAccess(Addr addr)
bool getInHtmWriteSet() const
virtual void invalidateEntry()
virtual DataBlock & getDataBlk()
void setInHtmReadSet(bool val)
AccessPermission m_Permission
bool getInHtmReadSet() const
bool isLocked(int context) const
void setInHtmWriteSet(bool val)
void setLocked(int context)
void setLastAccess(Tick tick)
void reserve(int64_t idx)
bool tryAccess(int64_t idx)
bool isTagPresent(Addr address) const
Addr getAddressAtIdx(int idx) const
void clearLockedAll(int context)
bool testCacheAccess(Addr address, RubyRequestType type, DataBlock *&data_ptr)
ALUFreeListArray atomicALUArray
bool m_use_occupancy
Set to true when using WeightedLRU replacement policy, otherwise, set to false.
void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
std::vector< std::vector< ReplData > > replacement_data
We store all the ReplacementData in a 2-dimensional array.
void print(std::ostream &out) const
void recordCacheContents(int cntrl, CacheRecorder *tr) const
void setMRU(Addr address)
bool m_is_instruction_only_cache
gem5::ruby::CacheMemory::CacheMemoryStats cacheMemoryStats
void deallocate(Addr address)
void htmCommitTransaction()
int findTagInSet(int64_t line, Addr tag) const
void setLocked(Addr addr, int context)
int findTagInSetIgnorePermissions(int64_t cacheSet, Addr tag) const
bool isBlockInvalid(int64_t cache_set, int64_t loc)
int64_t addressToCacheSet(Addr address) const
void htmAbortTransaction()
bool tryCacheAccess(Addr address, RubyRequestType type, DataBlock *&data_ptr)
void profilePrefetchMiss()
void clearLocked(Addr addr)
void profilePrefetchHit()
bool isBlockNotBusy(int64_t cache_set, int64_t loc)
Addr cacheProbe(Addr address) const
void recordRequestType(CacheRequestType requestType, Addr addr)
void printData(std::ostream &out) const
bool cacheAvail(Addr address) const
CacheMemory(const Params &p)
replacement_policy::Base * m_replacementPolicy_ptr
We use the replacement policies from the Classic memory system.
std::unordered_map< Addr, int > m_tag_index
AbstractCacheEntry * allocate(Addr address, AbstractCacheEntry *new_entry)
int getReplacementWeight(int64_t set, int64_t loc)
std::vector< std::vector< AbstractCacheEntry * > > m_cache
bool checkResourceAvailable(CacheResourceType res, Addr addr)
AbstractCacheEntry * lookup(Addr address)
bool isLocked(Addr addr, int context)
void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock &data)
static uint32_t getBlockSizeBytes()
Derived & subname(off_type index, const std::string &name)
Set the subfield name for the given index, and marks this stat to print at the end of simulation.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Histogram & init(size_type size)
Set the parameters of this histogram.
Derived & init(size_type size)
Set this vector to have the given size.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
static constexpr std::enable_if_t< std::is_integral_v< T >, int > floorLog2(T x)
#define panic(...)
This implements a cprintf based panic() function.
Addr makeLineAddress(Addr addr)
std::ostream & operator<<(std::ostream &os, const BoolVec &myvector)
Addr bitSelect(Addr addr, unsigned int small, unsigned int big)
const FlagsType pdf
Print the percent of the total that this entry represents.
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.
const FlagsType dist
Print the distribution.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
statistics::Histogram htmTransCommitWriteSet
statistics::Scalar m_prefetch_misses
statistics::Scalar numTagArrayWrites
statistics::Scalar numAtomicALUOperations
statistics::Scalar numDataArrayStalls
statistics::Scalar numTagArrayReads
statistics::Scalar numTagArrayStalls
statistics::Scalar m_demand_hits
statistics::Histogram htmTransCommitReadSet
statistics::Vector m_accessModeType
statistics::Scalar m_demand_misses
statistics::Scalar numDataArrayWrites
statistics::Formula m_prefetch_accesses
statistics::Scalar m_prefetch_hits
statistics::Histogram htmTransAbortWriteSet
statistics::Scalar numAtomicALUArrayStalls
statistics::Scalar numDataArrayReads
statistics::Histogram htmTransAbortReadSet
CacheMemoryStats(statistics::Group *parent)