for(int i = size-1; i > 0; i--)
table[i] = table[i-1];
table[0] = entry;
+
+ inserts++;
}
void
TlbEntry *te;
while (x < size) {
te = &table[x];
- if (te->valid)
+ if (te->valid) {
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);
+ flushedEntries++;
+ }
x++;
}
memset(table, 0, sizeof(TlbEntry[size]));
+
+ flushTlb++;
}
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->valid = false;
+ flushedEntries++;
te = lookup(mva,asn);
}
+ flushTlbMvaAsid++;
}
void
te->valid = false;
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);
+ flushedEntries++;
}
x++;
}
+ flushTlbAsid++;
}
void
te->valid = false;
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);
+ flushedEntries++;
}
x++;
}
+ flushTlbMva++;
}
void
void
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")
.desc("DTB read hits")
;
- read_misses
+ readMisses
.name(name() + ".read_misses")
.desc("DTB read misses")
;
-
- read_accesses
+ readAccesses
.name(name() + ".read_accesses")
.desc("DTB read accesses")
;
- write_hits
+ writeHits
.name(name() + ".write_hits")
.desc("DTB write hits")
;
- write_misses
+ writeMisses
.name(name() + ".write_misses")
.desc("DTB write misses")
;
-
- write_accesses
+ writeAccesses
.name(name() + ".write_accesses")
.desc("DTB write accesses")
;
.desc("DTB accesses")
;
- hits = read_hits + write_hits;
- misses = read_misses + write_misses;
- accesses = read_accesses + write_accesses;
+ flushTlb
+ .name(name() + ".flush_tlb")
+ .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
assert(flags & MustBeOne);
if (sctlr.a || !(flags & AllowUnaligned)) {
if (vaddr & flags & AlignmentMask) {
+ alignFaults++;
return new DataAbort(vaddr, 0, is_write, ArmFault::AlignmentFault);
}
}
if (req->isPrefetch()){
//if the request is a prefetch don't attempt to fill the TLB
//or go any further with the memory access
+ prefetchFaults++;
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
// re-retreaving in table walker for speed
DPRINTF(TLB, "TLB Miss: Starting hardware table walker for %#x(%d)\n",
if (!te)
printTlb();
assert(te);
+ } else {
+ if (is_fetch)
+ instHits++;
+ else if (is_write)
+ writeHits++;
+ else
+ readHits++;
}
// Set memory attributes
uint32_t dacr = tc->readMiscReg(MISCREG_DACR);
switch ( (dacr >> (te->domain * 2)) & 0x3) {
case 0:
+ domainFaults++;
DPRINTF(TLB, "TLB Fault: Data abort on domain. DACR: %#x domain: %#x"
" write:%d sNp:%d\n", dacr, te->domain, is_write, te->sNp);
if (is_fetch)
panic("Unknown permissions\n");
}
if ((is_fetch) && (abt || te->xn)) {
+ permsFaults++;
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);
return new PrefetchAbort(vaddr,
(te->sNp ? ArmFault::Permission0 :
ArmFault::Permission1));
} else if (abt) {
+ permsFaults++;
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);
return new DataAbort(vaddr, te->domain, is_write,
TlbEntry *lookup(Addr vpn, uint8_t asn, bool functional = false);
// Access Stats
- mutable Stats::Scalar read_hits;
- mutable Stats::Scalar read_misses;
- mutable Stats::Scalar read_acv;
- mutable Stats::Scalar read_accesses;
- mutable Stats::Scalar write_hits;
- mutable Stats::Scalar write_misses;
- mutable Stats::Scalar write_acv;
- mutable Stats::Scalar write_accesses;
+ mutable Stats::Scalar instHits;
+ mutable Stats::Scalar instMisses;
+ mutable Stats::Scalar readHits;
+ mutable Stats::Scalar readMisses;
+ mutable Stats::Scalar writeHits;
+ mutable Stats::Scalar writeMisses;
+ mutable Stats::Scalar inserts;
+ 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 misses;
Stats::Formula accesses;