Merge with head.
--HG-- extra : convert_revision : ae7b3df573368c29a66d5b027ecad9ffb3a99104
This commit is contained in:
@@ -64,6 +64,7 @@ TLB::TLB(const string &name, int s)
|
||||
{
|
||||
table = new PTE[size];
|
||||
memset(table, 0, sizeof(PTE[size]));
|
||||
flushCache();
|
||||
}
|
||||
|
||||
TLB::~TLB()
|
||||
@@ -79,18 +80,29 @@ TLB::lookup(Addr vpn, uint8_t asn) const
|
||||
// assume not found...
|
||||
PTE *retval = NULL;
|
||||
|
||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||
if (i != lookupTable.end()) {
|
||||
while (i->first == vpn) {
|
||||
int index = i->second;
|
||||
PTE *pte = &table[index];
|
||||
assert(pte->valid);
|
||||
if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
|
||||
retval = pte;
|
||||
break;
|
||||
}
|
||||
if (PTECache[0] && vpn == PTECache[0]->tag &&
|
||||
(PTECache[0]->asma || PTECache[0]->asn == asn))
|
||||
retval = PTECache[0];
|
||||
else if (PTECache[1] && vpn == PTECache[1]->tag &&
|
||||
(PTECache[1]->asma || PTECache[1]->asn == asn))
|
||||
retval = PTECache[1];
|
||||
else if (PTECache[2] && vpn == PTECache[2]->tag &&
|
||||
(PTECache[2]->asma || PTECache[2]->asn == asn))
|
||||
retval = PTECache[2];
|
||||
else {
|
||||
PageTable::const_iterator i = lookupTable.find(vpn);
|
||||
if (i != lookupTable.end()) {
|
||||
while (i->first == vpn) {
|
||||
int index = i->second;
|
||||
PTE *pte = &table[index];
|
||||
assert(pte->valid);
|
||||
if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
|
||||
retval = pte;
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +154,7 @@ TLB::checkCacheability(RequestPtr &req)
|
||||
void
|
||||
TLB::insert(Addr addr, PTE &pte)
|
||||
{
|
||||
flushCache();
|
||||
VAddr vaddr = addr;
|
||||
if (table[nlu].valid) {
|
||||
Addr oldvpn = table[nlu].tag;
|
||||
@@ -178,6 +191,7 @@ TLB::flushAll()
|
||||
{
|
||||
DPRINTF(TLB, "flushAll\n");
|
||||
memset(table, 0, sizeof(PTE[size]));
|
||||
flushCache();
|
||||
lookupTable.clear();
|
||||
nlu = 0;
|
||||
}
|
||||
@@ -185,6 +199,7 @@ TLB::flushAll()
|
||||
void
|
||||
TLB::flushProcesses()
|
||||
{
|
||||
flushCache();
|
||||
PageTable::iterator i = lookupTable.begin();
|
||||
PageTable::iterator end = lookupTable.end();
|
||||
while (i != end) {
|
||||
@@ -208,6 +223,7 @@ TLB::flushProcesses()
|
||||
void
|
||||
TLB::flushAddr(Addr addr, uint8_t asn)
|
||||
{
|
||||
flushCache();
|
||||
VAddr vaddr = addr;
|
||||
|
||||
PageTable::iterator i = lookupTable.find(vaddr.vpn());
|
||||
|
||||
@@ -88,6 +88,10 @@ namespace AlphaISA
|
||||
// Checkpointing
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
// Most recently used page table entries
|
||||
PTE *PTECache[2];
|
||||
inline void flushCache() { memset(PTECache, 0, 2 * sizeof(PTE*)); }
|
||||
};
|
||||
|
||||
class ITB : public TLB
|
||||
|
||||
@@ -353,9 +353,7 @@ class StaticInst : public StaticInstBase
|
||||
StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
|
||||
: StaticInstBase(__opClass),
|
||||
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
|
||||
{
|
||||
memset(&recentDecodes, 0, 2 * sizeof(cacheElement));
|
||||
}
|
||||
{ }
|
||||
|
||||
public:
|
||||
|
||||
@@ -459,6 +457,9 @@ class StaticInst : public StaticInstBase
|
||||
struct cacheElement {
|
||||
Addr page_addr;
|
||||
AddrDecodePage *decodePage;
|
||||
|
||||
cacheElement()
|
||||
:decodePage(NULL) { }
|
||||
} ;
|
||||
|
||||
/// An array of recently decoded instructions.
|
||||
|
||||
@@ -84,6 +84,7 @@ Bus::deletePortRefs(Port *p)
|
||||
if (funcPort == bp)
|
||||
return;
|
||||
interfaces.erase(bp->getId());
|
||||
clearBusCache();
|
||||
delete bp;
|
||||
}
|
||||
|
||||
@@ -176,7 +177,16 @@ Bus::recvTiming(PacketPtr pkt)
|
||||
DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
|
||||
src, pkt->getDest(), pkt->getAddr(), pkt->cmdString());
|
||||
|
||||
BusPort *src_port = (src == defaultId) ? defaultPort : interfaces[src];
|
||||
BusPort *src_port;
|
||||
if (src == defaultId)
|
||||
src_port = defaultPort;
|
||||
else {
|
||||
src_port = checkBusCache(src);
|
||||
if (src_port == NULL) {
|
||||
src_port = interfaces[src];
|
||||
updateBusCache(src, src_port);
|
||||
}
|
||||
}
|
||||
|
||||
// If the bus is busy, or other devices are in line ahead of the current
|
||||
// one, put this device on the retry list.
|
||||
@@ -220,6 +230,15 @@ Bus::recvTiming(PacketPtr pkt)
|
||||
assert(dest >= 0 && dest < maxId);
|
||||
assert(dest != src); // catch infinite loops
|
||||
dest_port_id = dest;
|
||||
if (dest_port_id == defaultId)
|
||||
dest_port = defaultPort;
|
||||
else {
|
||||
dest_port = checkBusCache(dest);
|
||||
if (dest_port == NULL) {
|
||||
dest_port = interfaces[dest_port_id];
|
||||
// updateBusCache(dest_port_id, dest_port);
|
||||
}
|
||||
}
|
||||
dest_port = (dest_port_id == defaultId) ?
|
||||
defaultPort : interfaces[dest_port_id];
|
||||
}
|
||||
@@ -291,9 +310,13 @@ Bus::findPort(Addr addr)
|
||||
/* An interval tree would be a better way to do this. --ali. */
|
||||
int dest_id = -1;
|
||||
|
||||
PortIter i = portMap.find(RangeSize(addr,1));
|
||||
if (i != portMap.end())
|
||||
dest_id = i->second;
|
||||
dest_id = checkPortCache(addr);
|
||||
if (dest_id == -1) {
|
||||
PortIter i = portMap.find(RangeSize(addr,1));
|
||||
if (i != portMap.end())
|
||||
dest_id = i->second;
|
||||
updatePortCache(dest_id, i->first.start, i->first.end);
|
||||
}
|
||||
|
||||
// Check if this matches the default range
|
||||
if (dest_id == -1) {
|
||||
@@ -340,8 +363,16 @@ Bus::recvAtomic(PacketPtr pkt)
|
||||
int orig_src = pkt->getSrc();
|
||||
|
||||
int target_port_id = findPort(pkt->getAddr());
|
||||
Port *target_port = (target_port_id == defaultId) ?
|
||||
defaultPort : interfaces[target_port_id];
|
||||
BusPort *target_port;
|
||||
if (target_port_id == defaultId)
|
||||
target_port = defaultPort;
|
||||
else {
|
||||
target_port = checkBusCache(target_port_id);
|
||||
if (target_port == NULL) {
|
||||
target_port = interfaces[target_port_id];
|
||||
updateBusCache(target_port_id, target_port);
|
||||
}
|
||||
}
|
||||
|
||||
SnoopIter s_end = snoopPorts.end();
|
||||
for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
|
||||
@@ -438,6 +469,7 @@ Bus::recvStatusChange(Port::Status status, int id)
|
||||
|
||||
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
|
||||
|
||||
clearPortCache();
|
||||
if (id == defaultId) {
|
||||
defaultRange.clear();
|
||||
// Only try to update these ranges if the user set a default responder.
|
||||
|
||||
101
src/mem/bus.hh
101
src/mem/bus.hh
@@ -180,6 +180,58 @@ class Bus : public MemObject
|
||||
*/
|
||||
int findPort(Addr addr);
|
||||
|
||||
// Cache for the findPort function storing recently used ports from portMap
|
||||
struct PortCache {
|
||||
bool valid;
|
||||
int id;
|
||||
Addr start;
|
||||
Addr end;
|
||||
};
|
||||
|
||||
PortCache portCache[3];
|
||||
|
||||
// Checks the cache and returns the id of the port that has the requested
|
||||
// address within its range
|
||||
inline int checkPortCache(Addr addr) {
|
||||
if (portCache[0].valid && addr >= portCache[0].start &&
|
||||
addr < portCache[0].end) {
|
||||
return portCache[0].id;
|
||||
} else if (portCache[1].valid && addr >= portCache[1].start &&
|
||||
addr < portCache[1].end) {
|
||||
return portCache[1].id;
|
||||
} else if (portCache[2].valid && addr >= portCache[2].start &&
|
||||
addr < portCache[2].end) {
|
||||
return portCache[2].id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clears the earliest entry of the cache and inserts a new port entry
|
||||
inline void updatePortCache(short id, Addr start, Addr end) {
|
||||
portCache[2].valid = portCache[1].valid;
|
||||
portCache[2].id = portCache[1].id;
|
||||
portCache[2].start = portCache[1].start;
|
||||
portCache[2].end = portCache[1].end;
|
||||
|
||||
portCache[1].valid = portCache[0].valid;
|
||||
portCache[1].id = portCache[0].id;
|
||||
portCache[1].start = portCache[0].start;
|
||||
portCache[1].end = portCache[0].end;
|
||||
|
||||
portCache[0].valid = true;
|
||||
portCache[0].id = id;
|
||||
portCache[0].start = start;
|
||||
portCache[0].end = end;
|
||||
}
|
||||
|
||||
// Clears the cache. Needs to be called in constructor.
|
||||
inline void clearPortCache() {
|
||||
portCache[2].valid = false;
|
||||
portCache[1].valid = false;
|
||||
portCache[0].valid = false;
|
||||
}
|
||||
|
||||
/** Process address range request.
|
||||
* @param resp addresses that we can respond to
|
||||
* @param snoop addresses that we would like to snoop
|
||||
@@ -246,6 +298,53 @@ class Bus : public MemObject
|
||||
int cachedBlockSize;
|
||||
bool cachedBlockSizeValid;
|
||||
|
||||
// Cache for the peer port interfaces
|
||||
struct BusCache {
|
||||
bool valid;
|
||||
short id;
|
||||
BusPort *port;
|
||||
};
|
||||
|
||||
BusCache busCache[3];
|
||||
|
||||
// Checks the peer port interfaces cache for the port id and returns
|
||||
// a pointer to the matching port
|
||||
inline BusPort* checkBusCache(short id) {
|
||||
if (busCache[0].valid && id == busCache[0].id) {
|
||||
return busCache[0].port;
|
||||
} else if (busCache[1].valid && id == busCache[1].id) {
|
||||
return busCache[1].port;
|
||||
} else if (busCache[2].valid && id == busCache[2].id) {
|
||||
return busCache[2].port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Replaces the earliest entry in the cache with a new entry
|
||||
inline void updateBusCache(short id, BusPort *port) {
|
||||
busCache[2].valid = busCache[1].valid;
|
||||
busCache[2].id = busCache[1].id;
|
||||
busCache[2].port = busCache[1].port;
|
||||
|
||||
busCache[1].valid = busCache[0].valid;
|
||||
busCache[1].id = busCache[0].id;
|
||||
busCache[1].port = busCache[0].port;
|
||||
|
||||
busCache[0].valid = true;
|
||||
busCache[0].id = id;
|
||||
busCache[0].port = port;
|
||||
}
|
||||
|
||||
// Invalidates the cache. Needs to be called in constructor.
|
||||
inline void clearBusCache() {
|
||||
// memset(busCache, 0, 3 * sizeof(BusCache));
|
||||
busCache[2].valid = false;
|
||||
busCache[1].valid = false;
|
||||
busCache[0].valid = false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** A function used to return the port associated with this bus object. */
|
||||
@@ -270,6 +369,8 @@ class Bus : public MemObject
|
||||
fatal("Bus width must be positive\n");
|
||||
if (clock <= 0)
|
||||
fatal("Bus clock period must be positive\n");
|
||||
clearBusCache();
|
||||
clearPortCache();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user