diff options
-rw-r--r-- | src/arch/alpha/tlb.cc | 38 | ||||
-rw-r--r-- | src/arch/alpha/tlb.hh | 4 | ||||
-rw-r--r-- | src/cpu/static_inst.hh | 7 | ||||
-rw-r--r-- | src/mem/bus.cc | 44 | ||||
-rw-r--r-- | src/mem/bus.hh | 101 |
5 files changed, 174 insertions, 20 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 214b2579f..205b81baf 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -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()); diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh index ea5ba5539..20f0037fd 100644 --- a/src/arch/alpha/tlb.hh +++ b/src/arch/alpha/tlb.hh @@ -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 diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index f32b61ee5..2e1ebd766 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -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. diff --git a/src/mem/bus.cc b/src/mem/bus.cc index cb359734b..9fa61a76d 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -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. diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 06ccd4ac0..f5cad0586 100644 --- a/src/mem/bus.hh +++ b/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(); } }; |