Go to the documentation of this file.
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"),
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"),
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"),
105 "Total number of updates"),
106 ADD_STAT(averageHitRate, statistics::units::Ratio::get(),
"Average hit rate"),
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);
WalkCacheStats(statistics::Group *parent)
const Entry * lookup(uint32_t sid, uint32_t ssid, bool updStats=true)
statistics::Formula averageMisses
#define fatal(...)
This implements a cprintf based fatal() function.
void invalidateVMID(uint16_t vmid)
SMMUv3BaseCacheStats(statistics::Group *parent, const std::string &name)
Derived & ysubname(off_type index, const std::string &subname)
const Entry * lookup(Addr va, Addr vaMask, uint16_t asid, uint16_t vmid, unsigned stage, unsigned level, bool updStats=true)
statistics::Formula averageUpdates
IPACache(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
std::array< unsigned, 2 *WALK_CACHE_LEVELS > offsets
void store(const Entry &incoming)
size_t pickSetIdx(uint32_t sid, uint32_t ssid) const
void store(const Entry &incoming)
statistics::Vector2d totalMissesByStageLevel
void invalidateSID(uint32_t sid)
SMMUv3BaseCache(const std::string &policy_name, uint32_t seed, statistics::Group *parent, const std::string &name)
WalkCache(const std::array< unsigned, 2 *WALK_CACHE_LEVELS > &_sizes, unsigned _associativity, const std::string &policy, statistics::Group *parent)
Derived & init(size_type _x, size_type _y)
std::vector< statistics::Formula * > averageLookupsByStageLevel
void invalidateIPA(Addr ipa, uint16_t vmid)
ConfigCache(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
gem5::SMMUv3BaseCache::SMMUv3BaseCacheStats baseCacheStats
statistics::Formula averageHitRate
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.
void invalidateVMID(uint16_t vmid)
size_t pickSetIdx(Addr va, Addr vaMask, unsigned stage, unsigned level) const
SMMUTLB(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent, const std::string &name)
std::string csprintf(const char *format, const Args &...args)
size_t pickEntryIdxToReplace(const Set &set, AllocPolicy alloc)
statistics::Scalar totalLookups
const Entry * lookup(uint32_t sid, uint32_t ssid, Addr va, bool updStats=true)
statistics::Formula averageLookups
void invalidateIPAA(Addr ipa)
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...
const FlagsType pdf
Print the percent of the total that this entry represents.
size_t pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const
ARMArchTLB(unsigned numEntries, unsigned _associativity, const std::string &policy, statistics::Group *parent)
#define WALK_CACHE_LEVELS
statistics::Vector2d insertionsByStageLevel
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
constexpr int findLsbSet(uint64_t val)
Returns the bit position of the LSB that is set in the input.
size_t pickSetIdx(uint32_t sid, uint32_t ssid) const
std::vector< statistics::Formula * > averageHitRateByStageLevel
const Entry * lookup(Addr va, uint16_t asid, uint16_t vmid, bool updStats=true)
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
size_t pickEntryIdxToReplace(const Set &set)
void store(const Entry &incoming)
void store(const Entry &incoming, AllocPolicy alloc)
statistics::Vector2d totalUpdatesByStageLevel
void invalidateVMID(uint16_t vmid)
size_t pickEntryIdxToReplace(const Set &set, unsigned stage, unsigned level)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
void invalidateASID(uint16_t asid, uint16_t vmid)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
statistics::Scalar totalUpdates
void invalidateASID(uint16_t asid, uint16_t vmid)
const std::string & name()
void invalidateVMID(uint16_t vmid)
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
@ SMMU_CACHE_REPL_ROUND_ROBIN
size_t pickEntryIdxToReplace(const Set &set)
std::vector< statistics::Formula * > averageMissesByStageLevel
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
void store(const Entry &incoming)
statistics::Vector2d totalLookupsByStageLevel
statistics::Formula & simSeconds
const Entry * lookup(Addr ipa, uint16_t vmid, bool updStats=true)
void invalidateSID(uint32_t sid)
std::array< unsigned, 2 *WALK_CACHE_LEVELS > sizes
static int decodePolicyName(const std::string &policy_name)
statistics::Scalar insertions
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
const Entry * lookupAnyVA(uint32_t sid, uint32_t ssid, bool updStats=true)
void invalidateASID(uint16_t asid, uint16_t vmid)
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::vector< statistics::Formula * > averageUpdatesByStageLevel
statistics::Scalar totalMisses
size_t pickEntryIdxToReplace(const Set &set)
void invalidateSSID(uint32_t sid, uint32_t ssid)
size_t pickSetIdx(Addr ipa, uint16_t vmid) const
gem5::WalkCache::WalkCacheStats walkCacheStats
void invalidateSSID(uint32_t sid, uint32_t ssid)
#define panic(...)
This implements a cprintf based panic() function.
void invalidateVAA(Addr va, uint16_t vmid)
void invalidateVAA(Addr va, uint16_t vmid)
Generated on Sun Jul 30 2023 01:56:55 for gem5 by doxygen 1.8.17