tlb.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 633 行 · 第 1/2 页
CC
633 行
/* * Copyright (c) 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Nathan L. Binkert * Steven K. Reinhardt * Andrew L. Schultz */#include <string>#include <vector>#include "arch/alpha/pagetable.hh"#include "arch/alpha/tlb.hh"#include "arch/alpha/faults.hh"#include "base/inifile.hh"#include "base/str.hh"#include "base/trace.hh"#include "config/alpha_tlaser.hh"#include "cpu/thread_context.hh"using namespace std;using namespace EV5;namespace AlphaISA {/////////////////////////////////////////////////////////////////////////// Alpha TLB//#ifdef DEBUGbool uncacheBit39 = false;bool uncacheBit40 = false;#endif#define MODE2MASK(X) (1 << (X))TLB::TLB(const Params *p) : BaseTLB(p), size(p->size), nlu(0){ table = new TlbEntry[size]; memset(table, 0, sizeof(TlbEntry[size])); flushCache();}TLB::~TLB(){ if (table) delete [] table;}// look up an entry in the TLBTlbEntry *TLB::lookup(Addr vpn, uint8_t asn){ // assume not found... TlbEntry *retval = NULL; if (EntryCache[0]) { if (vpn == EntryCache[0]->tag && (EntryCache[0]->asma || EntryCache[0]->asn == asn)) retval = EntryCache[0]; else if (EntryCache[1]) { if (vpn == EntryCache[1]->tag && (EntryCache[1]->asma || EntryCache[1]->asn == asn)) retval = EntryCache[1]; else if (EntryCache[2] && vpn == EntryCache[2]->tag && (EntryCache[2]->asma || EntryCache[2]->asn == asn)) retval = EntryCache[2]; } } if (retval == NULL) { PageTable::const_iterator i = lookupTable.find(vpn); if (i != lookupTable.end()) { while (i->first == vpn) { int index = i->second; TlbEntry *entry = &table[index]; assert(entry->valid); if (vpn == entry->tag && (entry->asma || entry->asn == asn)) { retval = updateCache(entry); break; } ++i; } } } DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn, retval ? "hit" : "miss", retval ? retval->ppn : 0); return retval;}FaultTLB::checkCacheability(RequestPtr &req){// in Alpha, cacheability is controlled by upper-level bits of the// physical address/* * We support having the uncacheable bit in either bit 39 or bit 40. * The Turbolaser platform (and EV5) support having the bit in 39, but * Tsunami (which Linux assumes uses an EV6) generates accesses with * the bit in 40. So we must check for both, but we have debug flags * to catch a weird case where both are used, which shouldn't happen. */#if ALPHA_TLASER if (req->getPaddr() & PAddrUncachedBit39)#else if (req->getPaddr() & PAddrUncachedBit43)#endif { // IPR memory space not implemented if (PAddrIprSpace(req->getPaddr())) { return new UnimpFault("IPR memory space not implemented!"); } else { // mark request as uncacheable req->setFlags(req->getFlags() | UNCACHEABLE);#if !ALPHA_TLASER // Clear bits 42:35 of the physical address (10-2 in Tsunami manual) req->setPaddr(req->getPaddr() & PAddrUncachedMask);#endif } } return NoFault;}// insert a new TLB entryvoidTLB::insert(Addr addr, TlbEntry &entry){ flushCache(); VAddr vaddr = addr; if (table[nlu].valid) { Addr oldvpn = table[nlu].tag; PageTable::iterator i = lookupTable.find(oldvpn); if (i == lookupTable.end()) panic("TLB entry not found in lookupTable"); int index; while ((index = i->second) != nlu) { if (table[index].tag != oldvpn) panic("TLB entry not found in lookupTable"); ++i; } DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn); lookupTable.erase(i); } DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), entry.ppn); table[nlu] = entry; table[nlu].tag = vaddr.vpn(); table[nlu].valid = true; lookupTable.insert(make_pair(vaddr.vpn(), nlu)); nextnlu();}voidTLB::flushAll(){ DPRINTF(TLB, "flushAll\n"); memset(table, 0, sizeof(TlbEntry[size])); flushCache(); lookupTable.clear(); nlu = 0;}voidTLB::flushProcesses(){ flushCache(); PageTable::iterator i = lookupTable.begin(); PageTable::iterator end = lookupTable.end(); while (i != end) { int index = i->second; TlbEntry *entry = &table[index]; assert(entry->valid); // we can't increment i after we erase it, so save a copy and // increment it to get the next entry now PageTable::iterator cur = i; ++i; if (!entry->asma) { DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, entry->tag, entry->ppn); entry->valid = false; lookupTable.erase(cur); } }}voidTLB::flushAddr(Addr addr, uint8_t asn){ flushCache(); VAddr vaddr = addr; PageTable::iterator i = lookupTable.find(vaddr.vpn()); if (i == lookupTable.end()) return; while (i != lookupTable.end() && i->first == vaddr.vpn()) { int index = i->second; TlbEntry *entry = &table[index]; assert(entry->valid); if (vaddr.vpn() == entry->tag && (entry->asma || entry->asn == asn)) { DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(), entry->ppn); // invalidate this entry entry->valid = false; lookupTable.erase(i++); } else { ++i; } }}voidTLB::serialize(ostream &os){ SERIALIZE_SCALAR(size); SERIALIZE_SCALAR(nlu); for (int i = 0; i < size; i++) { nameOut(os, csprintf("%s.Entry%d", name(), i)); table[i].serialize(os); }}voidTLB::unserialize(Checkpoint *cp, const string §ion){ UNSERIALIZE_SCALAR(size); UNSERIALIZE_SCALAR(nlu); for (int i = 0; i < size; i++) { table[i].unserialize(cp, csprintf("%s.Entry%d", section, i)); if (table[i].valid) { lookupTable.insert(make_pair(table[i].tag, i)); } }}/////////////////////////////////////////////////////////////////////////// Alpha ITB//ITB::ITB(const Params *p) : TLB(p){}voidITB::regStats(){ hits .name(name() + ".hits") .desc("ITB hits"); misses .name(name() + ".misses") .desc("ITB misses"); acv .name(name() + ".acv") .desc("ITB acv"); accesses .name(name() + ".accesses") .desc("ITB accesses"); accesses = hits + misses;}FaultITB::translate(RequestPtr &req, ThreadContext *tc){ //If this is a pal pc, then set PHYSICAL if(FULL_SYSTEM && PcPAL(req->getPC())) req->setFlags(req->getFlags() | PHYSICAL);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?