Bug fixes in the TLB

Make our replacement algorithm same as legion (although not same as the spec)
itb should be 64 entries not 48

src/arch/sparc/tlb.cc:
    Bug fixes in the TLB
    Make our replacement algorithm same as legion (although not same as the spec)
src/arch/sparc/tlb.hh:
    Make our replacement algorithm same as legion (although not same as the spec)
src/python/m5/objects/SparcTLB.py:
    itb should be 64 entries too

--HG--
extra : convert_revision : 1b5cb3597091e3cfe293e94f6f2219b1e621c35f
This commit is contained in:
Ali Saidi 2006-12-27 14:38:07 -05:00
parent ff88f3b13a
commit ba14d6d0e1
3 changed files with 97 additions and 30 deletions

View file

@ -45,7 +45,8 @@ namespace SparcISA
{ {
TLB::TLB(const std::string &name, int s) TLB::TLB(const std::string &name, int s)
: SimObject(name), size(s), usedEntries(0), cacheValid(false) : SimObject(name), size(s), usedEntries(0), lastReplaced(0),
cacheValid(false)
{ {
// To make this work you'll have to change the hypervisor and OS // To make this work you'll have to change the hypervisor and OS
if (size > 64) if (size > 64)
@ -53,13 +54,16 @@ TLB::TLB(const std::string &name, int s)
tlb = new TlbEntry[size]; tlb = new TlbEntry[size];
memset(tlb, 0, sizeof(TlbEntry) * size); memset(tlb, 0, sizeof(TlbEntry) * size);
for (int x = 0; x < size; x++)
freeList.push_back(&tlb[x]);
} }
void void
TLB::clearUsedBits() TLB::clearUsedBits()
{ {
MapIter i; MapIter i;
for (i = lookupTable.begin(); i != lookupTable.end();) { for (i = lookupTable.begin(); i != lookupTable.end(); i++) {
TlbEntry *t = i->second; TlbEntry *t = i->second;
if (!t->pte.locked()) { if (!t->pte.locked()) {
t->used = false; t->used = false;
@ -77,32 +81,76 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
MapIter i; MapIter i;
TlbEntry *new_entry = NULL; TlbEntry *new_entry = NULL;
TlbRange tr;
int x; int x;
cacheValid = false; cacheValid = false;
tr.va = va;
tr.size = PTE.size() - 1;
tr.contextId = context_id;
tr.partitionId = partition_id;
tr.real = real;
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n",
va, PTE.paddr(), partition_id, context_id, (int)real, entry);
// Demap any entry that conflicts
i = lookupTable.find(tr);
if (i != lookupTable.end()) {
i->second->valid = false;
if (i->second->used) {
i->second->used = false;
usedEntries--;
}
freeList.push_front(i->second);
DPRINTF(TLB, "TLB: Found conflicting entry %#X , deleting it\n",
i->second);
lookupTable.erase(i);
}
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d\n",
va, PTE.paddr(), partition_id, context_id, (int)real);
if (entry != -1) { if (entry != -1) {
assert(entry < size && entry >= 0); assert(entry < size && entry >= 0);
new_entry = &tlb[entry]; new_entry = &tlb[entry];
} else { } else {
if (!freeList.empty()) {
new_entry = freeList.front();
} else {
x = lastReplaced;
do {
++x;
if (x == size)
x = 0;
if (x == lastReplaced)
goto insertAllLocked;
} while (tlb[x].pte.locked());
lastReplaced = x;
new_entry = &tlb[x];
lookupTable.erase(new_entry->range);
}
/*
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (!tlb[x].valid || !tlb[x].used) { if (!tlb[x].valid || !tlb[x].used) {
new_entry = &tlb[x]; new_entry = &tlb[x];
break; break;
} }
} }*/
} }
insertAllLocked:
// Update the last ently if their all locked // Update the last ently if their all locked
if (!new_entry) if (!new_entry) {
new_entry = &tlb[size-1]; new_entry = &tlb[size-1];
lookupTable.erase(new_entry->range);
}
freeList.remove(new_entry);
DPRINTF(TLB, "Using entry: %#X\n", new_entry);
assert(PTE.valid()); assert(PTE.valid());
new_entry->range.va = va; new_entry->range.va = va;
new_entry->range.size = PTE.size(); new_entry->range.size = PTE.size() - 1;
new_entry->range.partitionId = partition_id; new_entry->range.partitionId = partition_id;
new_entry->range.contextId = context_id; new_entry->range.contextId = context_id;
new_entry->range.real = real; new_entry->range.real = real;
@ -112,17 +160,6 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
usedEntries++; usedEntries++;
// Demap any entry that conflicts
i = lookupTable.find(new_entry->range);
if (i != lookupTable.end()) {
i->second->valid = false;
if (i->second->used) {
i->second->used = false;
usedEntries--;
}
DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n");
lookupTable.erase(i);
}
i = lookupTable.insert(new_entry->range, new_entry); i = lookupTable.insert(new_entry->range, new_entry);
assert(i != lookupTable.end()); assert(i != lookupTable.end());
@ -219,6 +256,8 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
i->second->used = false; i->second->used = false;
usedEntries--; usedEntries--;
} }
freeList.push_front(i->second);
DPRINTF(TLB, "Freeing TLB entry : %#X\n", i->second);
lookupTable.erase(i); lookupTable.erase(i);
} }
} }
@ -233,6 +272,10 @@ TLB::demapContext(int partition_id, int context_id)
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (tlb[x].range.contextId == context_id && if (tlb[x].range.contextId == context_id &&
tlb[x].range.partitionId == partition_id) { tlb[x].range.partitionId == partition_id) {
if (tlb[x].valid == true) {
freeList.push_front(&tlb[x]);
DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]);
}
tlb[x].valid = false; tlb[x].valid = false;
if (tlb[x].used) { if (tlb[x].used) {
tlb[x].used = false; tlb[x].used = false;
@ -251,6 +294,10 @@ TLB::demapAll(int partition_id)
cacheValid = false; cacheValid = false;
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) { if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
if (tlb[x].valid == true){
freeList.push_front(&tlb[x]);
DPRINTF(TLB, "Freeing TLB entry : %#X\n", &tlb[x]);
}
tlb[x].valid = false; tlb[x].valid = false;
if (tlb[x].used) { if (tlb[x].used) {
tlb[x].used = false; tlb[x].used = false;
@ -267,7 +314,10 @@ TLB::invalidateAll()
int x; int x;
cacheValid = false; cacheValid = false;
freeList.clear();
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (tlb[x].valid == true)
freeList.push_back(&tlb[x]);
tlb[x].valid = false; tlb[x].valid = false;
} }
usedEntries = 0; usedEntries = 0;
@ -275,17 +325,26 @@ TLB::invalidateAll()
uint64_t uint64_t
TLB::TteRead(int entry) { TLB::TteRead(int entry) {
if (entry >= size)
panic("entry: %d\n", entry);
assert(entry < size); assert(entry < size);
if (tlb[entry].valid)
return tlb[entry].pte(); return tlb[entry].pte();
else
return (uint64_t)-1ll;
} }
uint64_t uint64_t
TLB::TagRead(int entry) { TLB::TagRead(int entry) {
assert(entry < size); assert(entry < size);
uint64_t tag; uint64_t tag;
if (!tlb[entry].valid)
return (uint64_t)-1ll;
tag = tlb[entry].range.contextId | tlb[entry].range.va | tag = tlb[entry].range.contextId;
(uint64_t)tlb[entry].range.partitionId << 61; tag |= tlb[entry].range.va;
tag |= (uint64_t)tlb[entry].range.partitionId << 61;
tag |= tlb[entry].range.real ? ULL(1) << 60 : 0; tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
tag |= (uint64_t)~tlb[entry].pte._size() << 56; tag |= (uint64_t)~tlb[entry].pte._size() << 56;
return tag; return tag;
@ -501,13 +560,13 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
// Be fast if we can! // Be fast if we can!
if (cacheValid && cacheState == tlbdata) { if (cacheValid && cacheState == tlbdata) {
if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) { cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr) {
req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
vaddr & cacheEntry[0]->pte.size()-1 ); vaddr & cacheEntry[0]->pte.size()-1 );
return NoFault; return NoFault;
} }
if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) { cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr) {
req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
vaddr & cacheEntry[1]->pte.size()-1 ); vaddr & cacheEntry[1]->pte.size()-1 );
return NoFault; return NoFault;
@ -667,8 +726,12 @@ continueDtbFlow:
} }
// cache translation date for next translation // cache translation date for next translation
cacheValid = true;
cacheState = tlbdata; cacheState = tlbdata;
if (!cacheValid) {
cacheEntry[1] = NULL;
cacheEntry[0] = NULL;
}
if (cacheEntry[0] != e && cacheEntry[1] != e) { if (cacheEntry[0] != e && cacheEntry[1] != e) {
cacheEntry[1] = cacheEntry[0]; cacheEntry[1] = cacheEntry[0];
cacheEntry[0] = e; cacheEntry[0] = e;
@ -677,7 +740,7 @@ continueDtbFlow:
if (implicit) if (implicit)
cacheAsi[0] = (ASI)0; cacheAsi[0] = (ASI)0;
} }
cacheValid = true;
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) | req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
vaddr & e->pte.size()-1); vaddr & e->pte.size()-1);
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
@ -696,7 +759,7 @@ handleQueueRegAccess:
writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
return new PrivilegedAction; return new PrivilegedAction;
} }
if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) { if (!hpriv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
return new DataAccessException; return new DataAccessException;
} }

View file

@ -54,10 +54,13 @@ class TLB : public SimObject
int size; int size;
int usedEntries; int usedEntries;
int lastReplaced;
uint64_t cacheState; uint64_t cacheState;
bool cacheValid; bool cacheValid;
std::list<TlbEntry*> freeList;
enum FaultTypes { enum FaultTypes {
OtherFault = 0, OtherFault = 0,
PrivViolation = 0x1, PrivViolation = 0x1,
@ -93,9 +96,6 @@ class TLB : public SimObject
/** Given an entry id, read that tlb entries' tag. */ /** Given an entry id, read that tlb entries' tag. */
uint64_t TagRead(int entry); uint64_t TagRead(int entry);
/** Give an entry id, read that tlb entries' tte */
uint64_t TteRead(int entry);
/** Remove all entries from the TLB */ /** Remove all entries from the TLB */
void invalidateAll(); void invalidateAll();
@ -128,6 +128,10 @@ class TLB : public SimObject
// Checkpointing // Checkpointing
virtual void serialize(std::ostream &os); virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
/** Give an entry id, read that tlb entries' tte */
uint64_t TteRead(int entry);
}; };
class ITB : public TLB class ITB : public TLB

View file

@ -11,4 +11,4 @@ class SparcDTB(SparcTLB):
class SparcITB(SparcTLB): class SparcITB(SparcTLB):
type = 'SparcITB' type = 'SparcITB'
size = 48 size = 64