34 #include "debug/RubyCache.hh" 35 #include "debug/RubyCacheTrace.hh" 36 #include "debug/RubyResourceStalls.hh" 37 #include "debug/RubyStats.hh" 39 #include "mem/ruby/protocol/AccessPermission.hh" 53 RubyCacheParams::create()
60 dataArray(p->dataArrayBanks, p->dataAccessLatency,
61 p->start_index_bit, p->ruby_system),
62 tagArray(p->tagArrayBanks, p->tagAccessLatency,
63 p->start_index_bit, p->ruby_system)
129 if (
m_cache[cacheSet][it->second]->m_Permission !=
130 AccessPermission_NotPresent)
161 assert (way < m_cache_assoc);
177 DPRINTF(RubyCache,
"address: %#x\n", address);
187 if (entry->
m_Permission == AccessPermission_Read_Write) {
190 if ((entry->
m_Permission == AccessPermission_Read_Only) &&
191 (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) {
205 DPRINTF(RubyCache,
"address: %#x\n", address);
216 return m_cache[cacheSet][loc]->m_Permission !=
217 AccessPermission_NotPresent;
234 DPRINTF(RubyCache,
"No tag match for address: %#x\n", address);
237 DPRINTF(RubyCache,
"address: %#x found\n", address);
272 DPRINTF(RubyCache,
"address: %#x\n", address);
278 if (!
set[
i] ||
set[
i]->m_Permission == AccessPermission_NotPresent) {
279 if (
set[
i] && (
set[
i] != entry)) {
280 warn_once(
"This protocol contains a cache entry handling bug: " 281 "Entries in the cache should never be NotPresent! If\n" 282 "this entry (%#x) is not tracked elsewhere, it will memory " 283 "leak here. Fix your protocol to eliminate these!",
288 set[
i]->m_Permission = AccessPermission_Invalid;
289 DPRINTF(RubyCache,
"Allocate clearing lock for addr: %x\n",
291 set[
i]->m_locked = -1;
293 set[
i]->setPosition(cacheSet,
i);
301 panic(
"Allocate didn't find an available entry");
309 DPRINTF(RubyCache,
"address: %#x\n", address);
333 candidates.push_back(static_cast<ReplaceableEntry*>(
337 getVictim(candidates)->getWay()]->m_Address;
347 if (loc == -1)
return NULL;
358 if (loc == -1)
return NULL;
378 uint32_t cacheSet = e->
getSet();
379 uint32_t loc = e->
getWay();
411 if (
m_cache[
set][loc] != NULL) {
412 ret =
m_cache[
set][loc]->getNumValidBlocks();
422 uint64_t warmedUpBlocks = 0;
430 RubyRequestType request_type = RubyRequestType_NULL;
431 if (perm == AccessPermission_Read_Only) {
433 request_type = RubyRequestType_IFETCH;
435 request_type = RubyRequestType_LD;
437 }
else if (perm == AccessPermission_Read_Write) {
438 request_type = RubyRequestType_ST;
441 if (request_type != RubyRequestType_NULL) {
443 lastAccessTick =
m_cache[
i][
j]->getLastAccess();
445 0, request_type, lastAccessTick,
453 DPRINTF(RubyCacheTrace,
"%s: %lli blocks of %lli total blocks" 454 "recorded %.2f%% \n",
name().c_str(), warmedUpBlocks,
455 totalBlocks, (
float(warmedUpBlocks) /
float(totalBlocks)) * 100.0);
461 out <<
"Cache dump: " <<
name() << endl;
465 out <<
" Index: " <<
i 469 out <<
" Index: " <<
i 471 <<
" entry: NULL" << endl;
480 out <<
"printData() not supported" << endl;
486 DPRINTF(RubyCache,
"Setting Lock for addr: %#x to %d\n", address, context);
491 m_cache[cacheSet][loc]->setLocked(context);
497 DPRINTF(RubyCache,
"Clear Lock for addr: %#x\n", address);
502 m_cache[cacheSet][loc]->clearLocked();
512 DPRINTF(RubyCache,
"Testing Lock for addr: %#llx cur %d con %d\n",
513 address,
m_cache[cacheSet][loc]->m_locked, context);
514 return m_cache[cacheSet][loc]->isLocked(context);
524 .
desc(
"Number of cache demand hits")
529 .
desc(
"Number of cache demand misses")
534 .
desc(
"Number of cache demand accesses")
540 .
name(
name() +
".total_sw_prefetches")
541 .
desc(
"Number of software prefetches")
546 .
name(
name() +
".total_hw_prefetches")
547 .
desc(
"Number of hardware prefetches")
553 .
desc(
"Number of prefetches")
560 .
init(RubyRequestType_NUM)
564 for (
int i = 0;
i < RubyAccessMode_NUM;
i++) {
566 .
subname(
i, RubyAccessMode_to_string(RubyAccessMode(
i)))
572 .
name(
name() +
".num_data_array_reads")
573 .
desc(
"number of data array reads")
578 .
name(
name() +
".num_data_array_writes")
579 .
desc(
"number of data array writes")
584 .
name(
name() +
".num_tag_array_reads")
585 .
desc(
"number of tag array reads")
590 .
name(
name() +
".num_tag_array_writes")
591 .
desc(
"number of tag array writes")
596 .
name(
name() +
".num_tag_array_stalls")
597 .
desc(
"number of stalls caused by tag array")
602 .
name(
name() +
".num_data_array_stalls")
603 .
desc(
"number of stalls caused by data array")
613 DPRINTF(RubyStats,
"Recorded statistic: %s\n",
614 CacheRequestType_to_string(requestType));
615 switch(requestType) {
616 case CacheRequestType_DataArrayRead:
621 case CacheRequestType_DataArrayWrite:
626 case CacheRequestType_TagArrayRead:
631 case CacheRequestType_TagArrayWrite:
637 warn(
"CacheMemory access_type not found: %s",
638 CacheRequestType_to_string(requestType));
649 if (res == CacheResourceType_TagArray) {
653 "Tag array stall on addr %#x in set %d\n",
658 }
else if (res == CacheResourceType_DataArray) {
662 "Data array stall on addr %#x in set %d\n",
668 panic(
"Unrecognized cache resource type.");
675 return (
m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
681 return (
m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
Stats::Scalar m_demand_misses
#define panic(...)
This implements a cprintf based panic() function.
const FlagsType pdf
Print the percent of the total that this entry represents.
Addr cacheProbe(Addr address) const
Stats::Vector m_accessModeType
void recordCacheContents(int cntrl, CacheRecorder *tr) const
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...
Addr bitSelect(Addr addr, unsigned int small, unsigned int big)
void recordRequestType(CacheRequestType requestType, Addr addr)
Stats::Formula m_demand_accesses
bool tryAccess(int64_t idx)
void print(std::ostream &out) const
virtual DataBlock & getDataBlk()
bool isBlockNotBusy(int64_t cache_set, int64_t loc)
virtual void touch(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Update replacement data.
bool testCacheAccess(Addr address, RubyRequestType type, DataBlock *&data_ptr)
int findTagInSetIgnorePermissions(int64_t cacheSet, Addr tag) const
Stats::Scalar m_hw_prefetches
void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock &data)
void clearLocked(Addr addr)
Overload hash function for BasicBlockRange type.
AbstractCacheEntry * allocate(Addr address, AbstractCacheEntry *new_entry)
bool isLocked(Addr addr, int context)
void regStats()
Callback to set stat parameters.
bool m_use_occupancy
Set to true when using WeightedLRU replacement policy, otherwise, set to false.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Stats::Scalar numTagArrayStalls
void printData(std::ostream &out) const
Derived & init(size_type size)
Set this vector to have the given size.
std::enable_if< std::is_integral< T >::value, int >::type floorLog2(T x)
void deallocate(Addr address)
void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
bool cacheAvail(Addr address) const
BaseReplacementPolicy * m_replacementPolicy_ptr
We use BaseReplacementPolicy from Classic system here, hence we can use different replacement policie...
std::unordered_map< Addr, int > m_tag_index
Tick curTick()
The current simulated tick.
void setMRU(Addr address)
std::vector< std::vector< ReplData > > replacement_data
We store all the ReplacementData in a 2-dimensional array.
uint64_t Tick
Tick count type.
CacheMemory(const Params *p)
bool isBlockInvalid(int64_t cache_set, int64_t loc)
bool tryCacheAccess(Addr address, RubyRequestType type, DataBlock *&data_ptr)
Stats::Scalar m_demand_hits
int findTagInSet(int64_t line, Addr tag) const
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
virtual std::shared_ptr< ReplacementData > instantiateEntry()=0
Instantiate a replacement data entry.
Addr makeLineAddress(Addr addr)
Stats::Scalar numDataArrayWrites
Addr getAddressAtIdx(int idx) const
const FlagsType total
Print the total.
bool m_is_instruction_only_cache
virtual void invalidate(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Invalidate replacement data to set it as the next probable victim.
virtual void reset(const std::shared_ptr< ReplacementData > &replacement_data) const =0
Reset replacement data.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
AccessPermission m_Permission
virtual const std::string name() const
bool isTagPresent(Addr address) const
uint32_t getWay() const
Get way number.
void reserve(int64_t idx)
Stats::Scalar m_sw_prefetches
int getReplacementWeight(int64_t set, int64_t loc)
void setLocked(Addr addr, int context)
ostream & operator<<(ostream &out, const CacheMemory &obj)
Stats::Scalar numTagArrayWrites
Stats::Scalar numDataArrayStalls
Stats::Scalar numDataArrayReads
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
uint32_t getSet() const
Get set number.
virtual void regStats()
Callback to set stat parameters.
Stats::Scalar numTagArrayReads
Stats::Formula m_prefetches
const FlagsType nozero
Don't print if this is zero.
bool checkResourceAvailable(CacheResourceType res, Addr addr)
AbstractCacheEntry * lookup(Addr address)
static uint32_t getBlockSizeBytes()
Abstract superclass for simulation objects.
int64_t addressToCacheSet(Addr address) const
std::vector< std::vector< AbstractCacheEntry * > > m_cache