49#define SMMUTLB_SEED 0xEA752DFE
50#define ARMARCHTLB_SEED 0x8B021FA1
51#define IPACACHE_SEED 0xE5A0CC0F
52#define CONFIGCACHE_SEED 0xB56F74E8
53#define WALKCACHE_SEED 0x18ACF3D6
66 : replacementPolicy(decodePolicyName(policy_name)),
70 baseCacheStats(parent,
name)
76 if (policy_name ==
"rr") {
78 }
else if (policy_name ==
"rand") {
80 }
else if (policy_name ==
"lru") {
83 panic(
"Unknown cache replacement policy '%s'\n", policy_name);
90 : statistics::
Group(parent,
name.c_str()),
91 ADD_STAT(averageLookups, statistics::units::Rate<
92 statistics::units::Count, statistics::units::Second>::get(),
93 "Average number lookups per second"),
94 ADD_STAT(totalLookups, statistics::units::Count::get(),
95 "Total number of lookups"),
96 ADD_STAT(averageMisses, statistics::units::Rate<
97 statistics::units::Count, statistics::units::Second>::get(),
98 "Average number misses per second"),
99 ADD_STAT(totalMisses, statistics::units::Count::get(),
100 "Total number of misses"),
101 ADD_STAT(averageUpdates, statistics::units::Rate<
102 statistics::units::Count, statistics::units::Second>::get(),
103 "Average number updates per second"),
104 ADD_STAT(totalUpdates, statistics::units::Count::get(),
105 "Total number of updates"),
106 ADD_STAT(averageHitRate, statistics::units::Ratio::get(),
"Average hit rate"),
107 ADD_STAT(insertions, statistics::units::Count::get(),
108 "Number of insertions (not replacements)")
110 using namespace statistics;
155 const std::string &
name)
158 associativity(_associativity)
164 fatal(
"SMMUTLB must have at least one entry\n");
167 fatal(
"SMMUTLB associativity cannot be higher than "
168 "its number of entries\n");
173 fatal(
"Number of SMMUTLB entries must be divisible "
174 "by its associativity\n");
187 const Entry *result = NULL;
191 for (
size_t i = 0;
i <
set.size();
i++) {
194 if (
e.valid && (
e.va &
e.vaMask) == (
va &
e.vaMask) &&
195 e.sid==sid &&
e.ssid==ssid)
198 panic(
"SMMUTLB: duplicate entry found!\n");
220 const Entry *result = NULL;
222 for (
size_t s = 0;
s <
sets.size();
s++) {
225 for (
size_t i = 0;
i <
set.size();
i++) {
228 if (
e.valid &&
e.sid==sid &&
e.ssid==ssid) {
248 panic(
"Tried to store an invalid entry\n");
252 const Entry *existing =
256 *
const_cast<Entry *
> (existing) = incoming;
270 for (
size_t i = 0;
i <
set.size();
i++) {
273 if (
e.sid == sid &&
e.ssid == ssid)
281 for (
size_t s = 0;
s <
sets.size();
s++) {
284 for (
size_t i = 0;
i <
set.size();
i++) {
298 for (
size_t i = 0;
i <
set.size();
i++) {
301 if ((
e.va &
e.vaMask) == (
va &
e.vaMask) &&
302 e.asid==
asid &&
e.vmid==vmid)
314 for (
size_t i = 0;
i <
set.size();
i++) {
317 if ((
e.va &
e.vaMask) == (
va &
e.vaMask) &&
e.vmid==vmid)
325 for (
size_t s = 0;
s <
sets.size();
s++) {
328 for (
size_t i = 0;
i <
set.size();
i++) {
331 if (
e.asid==
asid &&
e.vmid==vmid)
340 for (
size_t s = 0;
s <
sets.size();
s++) {
343 for (
size_t i = 0;
i <
set.size();
i++) {
355 for (
size_t s = 0;
s <
sets.size();
s++) {
358 for (
size_t i = 0;
i <
set.size();
i++)
359 set[
i].valid =
false;
366 return (
va >> 12) %
sets.size();
372 return (sid^ssid) %
sets.size();
381 uint32_t lru_tick = UINT32_MAX;
385 set.size()-1 :
set.size();
387 for (
size_t i = 0;
i < max_idx;
i++) {
393 if (
set[
i].lastUsed < lru_tick) {
395 lru_tick =
set[
i].lastUsed;
407 panic(
"Unknown allocation mode %d\n", alloc);
417 panic(
"Unknown allocation mode %d\n", alloc);
438 associativity(_associativity)
444 fatal(
"ARMArchTLB must have at least one entry\n");
447 fatal(
"ARMArchTLB associativity cannot be higher than "
448 "its number of entries\n");
453 fatal(
"Number of ARMArchTLB entries must be divisible "
454 "by its associativity\n");
466 const Entry *result = NULL;
470 for (
size_t i = 0;
i <
set.size();
i++) {
473 if (
e.valid && (
e.va &
e.vaMask) == (
va &
e.vaMask) &&
474 e.asid==
asid &&
e.vmid==vmid)
477 panic(
"ARMArchTLB: duplicate entry found!\n");
500 panic(
"Tried to store an invalid entry\n");
504 const Entry *existing =
508 *
const_cast<Entry *
> (existing) = incoming;
522 for (
size_t i = 0;
i <
set.size();
i++) {
525 if ((
e.va &
e.vaMask) == (
va &
e.vaMask) &&
526 e.asid==
asid &&
e.vmid==vmid)
536 for (
size_t s = 0;
s <
sets.size();
s++) {
539 for (
size_t i = 0;
i <
set.size();
i++) {
542 if ((
e.va &
e.vaMask) == (
va &
e.vaMask) &&
e.vmid==vmid)
551 for (
size_t s = 0;
s <
sets.size();
s++) {
554 for (
size_t i = 0;
i <
set.size();
i++) {
557 if (
e.asid==
asid &&
e.vmid==vmid)
566 for (
size_t s = 0;
s <
sets.size();
s++) {
569 for (
size_t i = 0;
i <
set.size();
i++) {
581 for (
size_t s = 0;
s <
sets.size();
s++) {
584 for (
size_t i = 0;
i <
set.size();
i++)
585 set[
i].valid =
false;
592 return ((
va >> 12) ^
asid ^ vmid) %
sets.size();
599 uint32_t lru_tick = UINT32_MAX;
601 for (
size_t i = 0;
i <
set.size();
i++) {
607 if (
set[
i].lastUsed < lru_tick) {
609 lru_tick =
set[
i].lastUsed;
637 associativity(_associativity)
643 fatal(
"IPACache must have at least one entry\n");
646 fatal(
"IPACache associativity cannot be higher than "
647 "its number of entries\n");
652 fatal(
"Number of IPACache entries must be divisible "
653 "by its associativity\n");
665 const Entry *result = NULL;
669 for (
size_t i = 0;
i <
set.size();
i++) {
672 if (
e.valid && (
e.ipa &
e.ipaMask) == (ipa &
e.ipaMask) &&
676 panic(
"IPACache: duplicate entry found!\n");
699 panic(
"Tried to store an invalid entry\n");
706 *
const_cast<Entry *
> (existing) = incoming;
720 for (
size_t i = 0;
i <
set.size();
i++) {
723 if ((
e.ipa &
e.ipaMask) == (ipa &
e.ipaMask) &&
e.vmid==vmid)
731 for (
size_t s = 0;
s <
sets.size();
s++) {
734 for (
size_t i = 0;
i <
set.size();
i++) {
737 if ((
e.ipa &
e.ipaMask) == (ipa &
e.ipaMask))
746 for (
size_t s = 0;
s <
sets.size();
s++) {
749 for (
size_t i = 0;
i <
set.size();
i++) {
761 for (
size_t s = 0;
s <
sets.size();
s++) {
764 for (
size_t i = 0;
i <
set.size();
i++)
765 set[
i].valid =
false;
772 return ((
va >> 12) ^ vmid) %
sets.size();
779 uint32_t lru_tick = UINT32_MAX;
781 for (
size_t i = 0;
i <
set.size();
i++) {
787 if (
set[
i].lastUsed < lru_tick) {
789 lru_tick =
set[
i].lastUsed;
817 associativity(_associativity)
823 fatal(
"ConfigCache must have at least one entry\n");
826 fatal(
"ConfigCache associativity cannot be higher than "
827 "its number of entries\n");
832 fatal(
"Number of ConfigCache entries must be divisible "
833 "by its associativity\n");
845 const Entry *result = NULL;
849 for (
size_t i = 0;
i <
set.size();
i++) {
852 if (
e.valid &&
e.sid==sid &&
e.ssid==ssid)
855 panic(
"ConfigCache: duplicate entry found!\n");
878 panic(
"Tried to store an invalid entry\n");
885 *
const_cast<Entry *
> (existing) = incoming;
899 for (
size_t i = 0;
i <
set.size();
i++) {
902 if (
e.sid==sid &&
e.ssid==ssid)
910 for (
size_t s = 0;
s <
sets.size();
s++) {
913 for (
size_t i = 0;
i <
set.size();
i++) {
925 for (
size_t s = 0;
s <
sets.size();
s++) {
928 for (
size_t i = 0;
i <
set.size();
i++)
929 set[
i].valid =
false;
936 return (sid^ssid) %
sets.size();
943 uint32_t lru_tick = UINT32_MAX;
945 for (
size_t i = 0;
i <
set.size();
i++) {
951 if (
set[
i].lastUsed < lru_tick) {
953 lru_tick =
set[
i].lastUsed;
978 unsigned _associativity,
const std::string &policy,
982 associativity(_associativity),
985 unsigned numEntries = std::accumulate(&_sizes[0],
992 fatal(
"WalkCache must have at least one entry\n");
996 fatal(
"Number of WalkCache entries at each level must be "
997 "divisible by WalkCache associativity\n");
1004 fatal(
"WalkCache associativity cannot be higher than "
1005 "its number of entries\n");
1010 fatal(
"Number of WalkCache entries must be divisible "
1011 "by its associativity\n");
1022 uint16_t
asid, uint16_t vmid,
1023 unsigned stage,
unsigned level,
1026 const Entry *result = NULL;
1030 for (
size_t i = 0;
i <
set.size();
i++) {
1033 if (
e.valid && (
e.va &
e.vaMask) == (
va &
e.vaMask) &&
1034 e.asid==
asid &&
e.vmid==vmid &&
e.stage==stage &&
e.level==
level)
1037 panic(
"WalkCache: duplicate entry found!\n");
1053 if (result == NULL) {
1064 if (!incoming.
valid)
1065 panic(
"Tried to store an invalid entry\n");
1067 assert(incoming.
stage==1 || incoming.
stage==2);
1077 *
const_cast<Entry *
> (existing) = incoming;
1092 const bool leaf_only)
1094 for (
size_t s = 0;
s <
sets.size();
s++) {
1097 for (
size_t i = 0;
i <
set.size();
i++) {
1100 if ((!leaf_only ||
e.leaf) && (
e.va &
e.vaMask) == (
va &
e.vaMask)
1101 &&
e.asid ==
asid &&
e.vmid == vmid)
1112 for (
size_t s = 0;
s <
sets.size();
s++) {
1115 for (
size_t i = 0;
i <
set.size();
i++) {
1118 if ((!leaf_only ||
e.leaf) && (
e.va &
e.vaMask) == (
va &
e.vaMask)
1130 for (
size_t s = 0;
s <
sets.size();
s++) {
1133 for (
size_t i = 0;
i <
set.size();
i++) {
1136 if (
e.asid==
asid &&
e.vmid==vmid)
1145 for (
size_t s = 0;
s <
sets.size();
s++) {
1148 for (
size_t i = 0;
i <
set.size();
i++) {
1160 for (
size_t s = 0;
s <
sets.size();
s++) {
1163 for (
size_t i = 0;
i <
set.size();
i++)
1164 set[
i].valid =
false;
1170 unsigned stage,
unsigned level)
const
1198 unsigned stage,
unsigned level)
1201 uint32_t lru_tick = UINT32_MAX;
1203 for (
size_t i = 0;
i <
set.size();
i++) {
1204 if (!
set[
i].valid) {
1210 if (
set[
i].lastUsed < lru_tick) {
1212 lru_tick =
set[
i].lastUsed;
1233 : statistics::
Group(parent),
1234 ADD_STAT(totalLookupsByStageLevel, statistics::units::Count::get(),
1235 "Total number of lookups"),
1236 ADD_STAT(totalMissesByStageLevel, statistics::units::Count::get(),
1237 "Total number of misses"),
1238 ADD_STAT(totalUpdatesByStageLevel, statistics::units::Count::get(),
1239 "Total number of updates"),
1240 ADD_STAT(insertionsByStageLevel, statistics::units::Count::get(),
1241 "Number of insertions (not replacements)")
1243 using namespace statistics;
1258 for (
int s = 0;
s < 2;
s++) {
1272 csprintf(
"averageLookups_S%dL%d",
s+1,
l).c_str(),
1275 "Average number lookups per second");
1276 avg_lookup->flags(
pdf);
1284 csprintf(
"averageMisses_S%dL%d",
s+1,
l).c_str(),
1287 "Average number misses per second");
1288 avg_misses->flags(
pdf);
1296 csprintf(
"averageUpdates_S%dL%d",
s+1,
l).c_str(),
1299 "Average number updates per second");
1300 avg_updates->flags(
pdf);
1308 csprintf(
"averageHitRate_S%dL%d",
s+1,
l).c_str(),
1310 avg_hitrate->flags(
pdf);
1324 for (
auto avg_lookup : averageLookupsByStageLevel)
1327 for (
auto avg_miss : averageMissesByStageLevel)
1330 for (
auto avg_update : averageUpdatesByStageLevel)
1333 for (
auto avg_hitrate : averageHitRateByStageLevel)
void invalidateVAA(Addr va, uint16_t vmid)
size_t pickEntryIdxToReplace(const Set &set)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
void store(const Entry &incoming)
size_t pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const
ARMArchTLB(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
const Entry * lookup(Addr va, uint16_t asid, uint16_t vmid, bool updStats=true)
size_t pickSetIdx(uint32_t sid, uint32_t ssid) const
void invalidateSID(uint32_t sid)
const Entry * lookup(uint32_t sid, uint32_t ssid, bool updStats=true)
ConfigCache(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
void store(const Entry &incoming)
void invalidateSSID(uint32_t sid, uint32_t ssid)
size_t pickEntryIdxToReplace(const Set &set)
void store(const Entry &incoming)
const Entry * lookup(Addr ipa, uint16_t vmid, bool updStats=true)
void invalidateIPAA(Addr ipa)
IPACache(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
size_t pickSetIdx(Addr ipa, uint16_t vmid) const
size_t pickEntryIdxToReplace(const Set &set)
void invalidateVMID(uint16_t vmid)
void invalidateIPA(Addr ipa, uint16_t vmid)
void invalidateSID(uint32_t sid)
SMMUTLB(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent, const std::string &name)
const Entry * lookupAnyVA(uint32_t sid, uint32_t ssid, bool updStats=true)
void invalidateVAA(Addr va, uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
void store(const Entry &incoming, AllocPolicy alloc)
const Entry * lookup(uint32_t sid, uint32_t ssid, Addr va, bool updStats=true)
size_t pickSetIdx(uint32_t sid, uint32_t ssid) const
void invalidateVMID(uint16_t vmid)
size_t pickEntryIdxToReplace(const Set &set, AllocPolicy alloc)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
void invalidateSSID(uint32_t sid, uint32_t ssid)
static int decodePolicyName(const std::string &policy_name)
SMMUv3BaseCache(const std::string &policy_name, uint32_t seed, statistics::Group *parent, const std::string &name)
gem5::SMMUv3BaseCache::SMMUv3BaseCacheStats baseCacheStats
void store(const Entry &incoming)
const Entry * lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid, unsigned stage, unsigned level, bool updStats=true)
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
size_t pickEntryIdxToReplace(const Set &set, unsigned stage, unsigned level)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
size_t pickSetIdx(Addr va, Addr vaMask, unsigned stage, unsigned level) const
std::array< unsigned, 2 *WALK_CACHE_LEVELS > sizes
gem5::WalkCache::WalkCacheStats walkCacheStats
std::array< unsigned, 2 *WALK_CACHE_LEVELS > offsets
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
WalkCache(const std::array< unsigned, 2 *WALK_CACHE_LEVELS > &_sizes, unsigned _associativity, const std::string &policy, statistics::Group *parent)
Derived & ysubname(off_type index, const std::string &subname)
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.
Derived & init(size_type _x, size_type _y)
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
constexpr int findLsbSet(uint64_t val)
Returns the bit position of the LSB that is set in the input That function will either use a builtin ...
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
const FlagsType pdf
Print the percent of the total that this entry represents.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
@ SMMU_CACHE_REPL_ROUND_ROBIN
std::string csprintf(const char *format, const Args &...args)
statistics::Formula & simSeconds
#define WALK_CACHE_LEVELS
statistics::Formula averageLookups
statistics::Formula averageHitRate
statistics::Scalar insertions
statistics::Scalar totalMisses
statistics::Formula averageUpdates
statistics::Scalar totalUpdates
statistics::Scalar totalLookups
statistics::Formula averageMisses
SMMUv3BaseCacheStats(statistics::Group *parent, const std::string &name)
statistics::Vector2d totalLookupsByStageLevel
statistics::Vector2d totalMissesByStageLevel
WalkCacheStats(statistics::Group *parent)
std::vector< statistics::Formula * > averageMissesByStageLevel
statistics::Vector2d insertionsByStageLevel
std::vector< statistics::Formula * > averageHitRateByStageLevel
std::vector< statistics::Formula * > averageUpdatesByStageLevel
std::vector< statistics::Formula * > averageLookupsByStageLevel
statistics::Vector2d totalUpdatesByStageLevel
const std::string & name()