ARM: Add some TLB statistics for ARM

This commit is contained in:
Ali Saidi 2010-11-08 13:58:25 -06:00
parent a1e8225975
commit 057b451773
2 changed files with 125 additions and 20 deletions

View file

@ -152,6 +152,8 @@ TLB::insert(Addr addr, TlbEntry &entry)
for(int i = size-1; i > 0; i--) for(int i = size-1; i > 0; i--)
table[i] = table[i-1]; table[i] = table[i-1];
table[0] = entry; table[0] = entry;
inserts++;
} }
void void
@ -178,13 +180,17 @@ TLB::flushAll()
TlbEntry *te; TlbEntry *te;
while (x < size) { while (x < size) {
te = &table[x]; te = &table[x];
if (te->valid) if (te->valid) {
DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n",
te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap);
flushedEntries++;
}
x++; x++;
} }
memset(table, 0, sizeof(TlbEntry[size])); memset(table, 0, sizeof(TlbEntry[size]));
flushTlb++;
} }
@ -199,8 +205,10 @@ TLB::flushMvaAsid(Addr mva, uint64_t asn)
DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n",
te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap);
te->valid = false; te->valid = false;
flushedEntries++;
te = lookup(mva,asn); te = lookup(mva,asn);
} }
flushTlbMvaAsid++;
} }
void void
@ -217,9 +225,11 @@ TLB::flushAsid(uint64_t asn)
te->valid = false; te->valid = false;
DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n",
te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap);
flushedEntries++;
} }
x++; x++;
} }
flushTlbAsid++;
} }
void void
@ -237,9 +247,11 @@ TLB::flushMva(Addr mva)
te->valid = false; te->valid = false;
DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n", DPRINTF(TLB, " - %#x, asn %d ppn %#x size: %#x ap:%d\n",
te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap); te->vpn << te->N, te->asid, te->pfn << te->N, te->size, te->ap);
flushedEntries++;
} }
x++; x++;
} }
flushTlbMva++;
} }
void void
@ -268,34 +280,47 @@ TLB::unserialize(Checkpoint *cp, const string &section)
void void
TLB::regStats() TLB::regStats()
{ {
read_hits instHits
.name(name() + ".inst_hits")
.desc("ITB inst hits")
;
instMisses
.name(name() + ".inst_misses")
.desc("ITB inst misses")
;
instAccesses
.name(name() + ".inst_accesses")
.desc("ITB inst accesses")
;
readHits
.name(name() + ".read_hits") .name(name() + ".read_hits")
.desc("DTB read hits") .desc("DTB read hits")
; ;
read_misses readMisses
.name(name() + ".read_misses") .name(name() + ".read_misses")
.desc("DTB read misses") .desc("DTB read misses")
; ;
readAccesses
read_accesses
.name(name() + ".read_accesses") .name(name() + ".read_accesses")
.desc("DTB read accesses") .desc("DTB read accesses")
; ;
write_hits writeHits
.name(name() + ".write_hits") .name(name() + ".write_hits")
.desc("DTB write hits") .desc("DTB write hits")
; ;
write_misses writeMisses
.name(name() + ".write_misses") .name(name() + ".write_misses")
.desc("DTB write misses") .desc("DTB write misses")
; ;
writeAccesses
write_accesses
.name(name() + ".write_accesses") .name(name() + ".write_accesses")
.desc("DTB write accesses") .desc("DTB write accesses")
; ;
@ -315,9 +340,57 @@ TLB::regStats()
.desc("DTB accesses") .desc("DTB accesses")
; ;
hits = read_hits + write_hits; flushTlb
misses = read_misses + write_misses; .name(name() + ".flush_tlb")
accesses = read_accesses + write_accesses; .desc("Number of times complete TLB was flushed")
;
flushTlbMva
.name(name() + ".flush_tlb_mva")
.desc("Number of times TLB was flushed by MVA")
;
flushTlbMvaAsid
.name(name() + ".flush_tlb_mva_asid")
.desc("Number of times TLB was flushed by MVA & ASID")
;
flushTlbAsid
.name(name() + ".flush_tlb_asid")
.desc("Number of times TLB was flushed by ASID")
;
flushedEntries
.name(name() + ".flush_entries")
.desc("Number of entries that have been flushed from TLB")
;
alignFaults
.name(name() + ".align_faults")
.desc("Number of TLB faults due to alignment restrictions")
;
prefetchFaults
.name(name() + ".prefetch_faults")
.desc("Number of TLB faults due to prefetch")
;
domainFaults
.name(name() + ".domain_faults")
.desc("Number of TLB faults due to domain restrictions")
;
permsFaults
.name(name() + ".perms_faults")
.desc("Number of TLB faults due to permissions restrictions")
;
instAccesses = instHits + instMisses;
readAccesses = readHits + readMisses;
writeAccesses = writeHits + writeMisses;
hits = readHits + writeHits + instHits;
misses = readMisses + writeMisses + instMisses;
accesses = readAccesses + writeAccesses + instAccesses;
} }
#if !FULL_SYSTEM #if !FULL_SYSTEM
@ -400,6 +473,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
assert(flags & MustBeOne); assert(flags & MustBeOne);
if (sctlr.a || !(flags & AllowUnaligned)) { if (sctlr.a || !(flags & AllowUnaligned)) {
if (vaddr & flags & AlignmentMask) { if (vaddr & flags & AlignmentMask) {
alignFaults++;
return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault); return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault);
} }
} }
@ -441,8 +515,17 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
if (req->isPrefetch()){ if (req->isPrefetch()){
//if the request is a prefetch don't attempt to fill the TLB //if the request is a prefetch don't attempt to fill the TLB
//or go any further with the memory access //or go any further with the memory access
prefetchFaults++;
return new PrefetchAbort(vaddr, ArmFault::PrefetchTLBMiss); return new PrefetchAbort(vaddr, ArmFault::PrefetchTLBMiss);
} }
if (is_fetch)
instMisses++;
else if (is_write)
writeMisses++;
else
readMisses++;
// start translation table walk, pass variables rather than // start translation table walk, pass variables rather than
// re-retreaving in table walker for speed // re-retreaving in table walker for speed
DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n", DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n",
@ -461,6 +544,13 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
if (!te) if (!te)
printTlb(); printTlb();
assert(te); assert(te);
} else {
if (is_fetch)
instHits++;
else if (is_write)
writeHits++;
else
readHits++;
} }
// Set memory attributes // Set memory attributes
@ -474,6 +564,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
uint32_t dacr = tc->readMiscReg(MISCREG_DACR); uint32_t dacr = tc->readMiscReg(MISCREG_DACR);
switch ( (dacr >> (te->domain * 2)) & 0x3) { switch ( (dacr >> (te->domain * 2)) & 0x3) {
case 0: case 0:
domainFaults++;
DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x" DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x"
" write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp); " write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp);
if (is_fetch) if (is_fetch)
@ -548,12 +639,14 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
panic("Unknown permissions\n"); panic("Unknown permissions\n");
} }
if ((is_fetch) && (abt || te->xn)) { if ((is_fetch) && (abt || te->xn)) {
permsFaults++;
DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d priv:%d" DPRINTF(TLB, "TLB Fault: Prefetch abort on permission check. AP:%d priv:%d"
" write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp); " write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp);
return new PrefetchAbort(vaddr, return new PrefetchAbort(vaddr,
(te->sNp ? ArmFault::Permission0 : (te->sNp ? ArmFault::Permission0 :
ArmFault::Permission1)); ArmFault::Permission1));
} else if (abt) { } else if (abt) {
permsFaults++;
DPRINTF(TLB, "TLB Fault: Data abort on permission check. AP:%d priv:%d" DPRINTF(TLB, "TLB Fault: Data abort on permission check. AP:%d priv:%d"
" write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp); " write:%d sNp:%d\n", ap, is_priv, is_write, te->sNp);
return new DataAbort(vaddr, te->domain, is_write, return new DataAbort(vaddr, te->domain, is_write,

View file

@ -102,14 +102,26 @@ class TLB : public BaseTLB
TlbEntry *lookup(Addr vpn, uint8_t asn, bool functional = false); TlbEntry *lookup(Addr vpn, uint8_t asn, bool functional = false);
// Access Stats // Access Stats
mutable Stats::Scalar read_hits; mutable Stats::Scalar instHits;
mutable Stats::Scalar read_misses; mutable Stats::Scalar instMisses;
mutable Stats::Scalar read_acv; mutable Stats::Scalar readHits;
mutable Stats::Scalar read_accesses; mutable Stats::Scalar readMisses;
mutable Stats::Scalar write_hits; mutable Stats::Scalar writeHits;
mutable Stats::Scalar write_misses; mutable Stats::Scalar writeMisses;
mutable Stats::Scalar write_acv; mutable Stats::Scalar inserts;
mutable Stats::Scalar write_accesses; mutable Stats::Scalar flushTlb;
mutable Stats::Scalar flushTlbMva;
mutable Stats::Scalar flushTlbMvaAsid;
mutable Stats::Scalar flushTlbAsid;
mutable Stats::Scalar flushedEntries;
mutable Stats::Scalar alignFaults;
mutable Stats::Scalar prefetchFaults;
mutable Stats::Scalar domainFaults;
mutable Stats::Scalar permsFaults;
Stats::Formula readAccesses;
Stats::Formula writeAccesses;
Stats::Formula instAccesses;
Stats::Formula hits; Stats::Formula hits;
Stats::Formula misses; Stats::Formula misses;
Stats::Formula accesses; Stats::Formula accesses;