summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/tlb.cc924
-rw-r--r--src/arch/mips/mmaped_ipr.hh3
-rw-r--r--src/arch/sparc/asi.cc4
-rw-r--r--src/arch/sparc/miscregfile.cc58
-rw-r--r--src/arch/sparc/miscregfile.hh2
-rw-r--r--src/arch/sparc/tlb.cc224
-rw-r--r--src/arch/sparc/tlb.hh11
-rw-r--r--src/arch/sparc/tlb_map.hh11
-rw-r--r--src/base/range_map.hh123
-rw-r--r--src/cpu/exetrace.cc6
-rw-r--r--src/dev/sparc/t1000.cc6
-rw-r--r--src/mem/bus.cc70
-rw-r--r--src/mem/bus.hh3
-rw-r--r--src/unittest/rangemaptest.cc13
-rw-r--r--src/unittest/rangemaptest2.cc78
15 files changed, 956 insertions, 580 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index af69e45c0..c21bf94f5 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -48,589 +48,589 @@ using namespace EV5;
namespace AlphaISA
{
- ///////////////////////////////////////////////////////////////////////
- //
- // Alpha TLB
- //
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha TLB
+//
#ifdef DEBUG
- bool uncacheBit39 = false;
- bool uncacheBit40 = false;
+bool uncacheBit39 = false;
+bool uncacheBit40 = false;
#endif
#define MODE2MASK(X) (1 << (X))
- TLB::TLB(const string &name, int s)
- : SimObject(name), size(s), nlu(0)
- {
- table = new PTE[size];
- memset(table, 0, sizeof(PTE[size]));
- }
+TLB::TLB(const string &name, int s)
+ : SimObject(name), size(s), nlu(0)
+{
+ table = new PTE[size];
+ memset(table, 0, sizeof(PTE[size]));
+}
- TLB::~TLB()
- {
- if (table)
- delete [] table;
- }
+TLB::~TLB()
+{
+ if (table)
+ delete [] table;
+}
- // look up an entry in the TLB
- PTE *
- 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;
- }
+// look up an entry in the TLB
+PTE *
+TLB::lookup(Addr vpn, uint8_t asn) const
+{
+ // assume not found...
+ PTE *retval = NULL;
- ++i;
+ 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;
}
- }
- DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
- retval ? "hit" : "miss", retval ? retval->ppn : 0);
- return retval;
+ ++i;
+ }
}
+ DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
+ retval ? "hit" : "miss", retval ? retval->ppn : 0);
+ return retval;
+}
- Fault
- TLB::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.
- */
+Fault
+TLB::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) {
+ if (req->getPaddr() & PAddrUncachedBit39) {
#else
- if (req->getPaddr() & PAddrUncachedBit43) {
+ 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);
+ // 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);
+ // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
+ req->setPaddr(req->getPaddr() & PAddrUncachedMask);
#endif
- }
}
- return NoFault;
}
+ return NoFault;
+}
- // insert a new TLB entry
- void
- TLB::insert(Addr addr, PTE &pte)
- {
- 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");
+// insert a new TLB entry
+void
+TLB::insert(Addr addr, PTE &pte)
+{
+ VAddr vaddr = addr;
+ if (table[nlu].valid) {
+ Addr oldvpn = table[nlu].tag;
+ PageTable::iterator i = lookupTable.find(oldvpn);
- ++i;
- }
+ if (i == lookupTable.end())
+ panic("TLB entry not found in lookupTable");
- DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
+ int index;
+ while ((index = i->second) != nlu) {
+ if (table[index].tag != oldvpn)
+ panic("TLB entry not found in lookupTable");
- lookupTable.erase(i);
+ ++i;
}
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
+ DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
- table[nlu] = pte;
- table[nlu].tag = vaddr.vpn();
- table[nlu].valid = true;
-
- lookupTable.insert(make_pair(vaddr.vpn(), nlu));
- nextnlu();
+ lookupTable.erase(i);
}
- void
- TLB::flushAll()
- {
- DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(PTE[size]));
- lookupTable.clear();
- nlu = 0;
- }
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
- void
- TLB::flushProcesses()
- {
- PageTable::iterator i = lookupTable.begin();
- PageTable::iterator end = lookupTable.end();
- while (i != end) {
- int index = i->second;
- PTE *pte = &table[index];
- assert(pte->valid);
+ table[nlu] = pte;
+ table[nlu].tag = vaddr.vpn();
+ table[nlu].valid = true;
- // 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;
+ lookupTable.insert(make_pair(vaddr.vpn(), nlu));
+ nextnlu();
+}
- if (!pte->asma) {
- DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
- pte->valid = false;
- lookupTable.erase(cur);
- }
+void
+TLB::flushAll()
+{
+ DPRINTF(TLB, "flushAll\n");
+ memset(table, 0, sizeof(PTE[size]));
+ lookupTable.clear();
+ nlu = 0;
+}
+
+void
+TLB::flushProcesses()
+{
+ PageTable::iterator i = lookupTable.begin();
+ PageTable::iterator end = lookupTable.end();
+ while (i != end) {
+ int index = i->second;
+ PTE *pte = &table[index];
+ assert(pte->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 (!pte->asma) {
+ DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
+ pte->valid = false;
+ lookupTable.erase(cur);
}
}
+}
- void
- TLB::flushAddr(Addr addr, uint8_t asn)
- {
- VAddr vaddr = addr;
+void
+TLB::flushAddr(Addr addr, uint8_t asn)
+{
+ VAddr vaddr = addr;
- PageTable::iterator i = lookupTable.find(vaddr.vpn());
- if (i == lookupTable.end())
- return;
+ PageTable::iterator i = lookupTable.find(vaddr.vpn());
+ if (i == lookupTable.end())
+ return;
- while (i->first == vaddr.vpn()) {
- int index = i->second;
- PTE *pte = &table[index];
- assert(pte->valid);
-
- if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
- DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
- pte->ppn);
+ while (i->first == vaddr.vpn()) {
+ int index = i->second;
+ PTE *pte = &table[index];
+ assert(pte->valid);
- // invalidate this entry
- pte->valid = false;
+ if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
+ DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
+ pte->ppn);
- lookupTable.erase(i);
- }
+ // invalidate this entry
+ pte->valid = false;
- ++i;
+ lookupTable.erase(i);
}
+
+ ++i;
}
+}
- void
- TLB::serialize(ostream &os)
- {
- SERIALIZE_SCALAR(size);
- SERIALIZE_SCALAR(nlu);
+void
+TLB::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(size);
+ SERIALIZE_SCALAR(nlu);
- for (int i = 0; i < size; i++) {
- nameOut(os, csprintf("%s.PTE%d", name(), i));
- table[i].serialize(os);
- }
+ for (int i = 0; i < size; i++) {
+ nameOut(os, csprintf("%s.PTE%d", name(), i));
+ table[i].serialize(os);
}
+}
- void
- TLB::unserialize(Checkpoint *cp, const string &section)
- {
- UNSERIALIZE_SCALAR(size);
- UNSERIALIZE_SCALAR(nlu);
+void
+TLB::unserialize(Checkpoint *cp, const string &section)
+{
+ UNSERIALIZE_SCALAR(size);
+ UNSERIALIZE_SCALAR(nlu);
- for (int i = 0; i < size; i++) {
- table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
- if (table[i].valid) {
- lookupTable.insert(make_pair(table[i].tag, i));
- }
+ for (int i = 0; i < size; i++) {
+ table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
+ if (table[i].valid) {
+ lookupTable.insert(make_pair(table[i].tag, i));
}
}
+}
- ///////////////////////////////////////////////////////////////////////
- //
- // Alpha ITB
- //
- ITB::ITB(const std::string &name, int size)
- : TLB(name, size)
- {}
-
-
- void
- ITB::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;
- }
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha ITB
+//
+ITB::ITB(const std::string &name, int size)
+ : TLB(name, size)
+{}
- Fault
- ITB::translate(RequestPtr &req, ThreadContext *tc) const
- {
- if (PcPAL(req->getPC())) {
- // strip off PAL PC marker (lsb is 1)
- req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
- hits++;
- return NoFault;
- }
+void
+ITB::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;
+}
- if (req->getFlags() & PHYSICAL) {
- req->setPaddr(req->getVaddr());
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->getVaddr())) {
- acv++;
- return new ItbAcvFault(req->getVaddr());
- }
+Fault
+ITB::translate(RequestPtr &req, ThreadContext *tc) const
+{
+ if (PcPAL(req->getPC())) {
+ // strip off PAL PC marker (lsb is 1)
+ req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
+ hits++;
+ return NoFault;
+ }
+
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
- // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
- // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
+
+ // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
+ // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
#if ALPHA_TLASER
- if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->getVaddr()) == 2) {
+ if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
- // only valid in kernel mode
- if (ICM_CM(tc->readMiscReg(IPR_ICM)) !=
- mode_kernel) {
- acv++;
- return new ItbAcvFault(req->getVaddr());
- }
+ // only valid in kernel mode
+ if (ICM_CM(tc->readMiscReg(IPR_ICM)) !=
+ mode_kernel) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->getPaddr() & PAddrUncachedBit40)
- req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
- else
- req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
- } else {
- // not a physical address: need to look up pte
- int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
- PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
- asn);
-
- if (!pte) {
- misses++;
- return new ItbPageFault(req->getVaddr());
- }
-
- req->setPaddr((pte->ppn << PageShift) +
- (VAddr(req->getVaddr()).offset()
- & ~3));
+ } else {
+ // not a physical address: need to look up pte
+ int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
+ PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ misses++;
+ return new ItbPageFault(req->getVaddr());
+ }
- // check permissions for this access
- if (!(pte->xre &
- (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) {
- // instruction access fault
- acv++;
- return new ItbAcvFault(req->getVaddr());
- }
+ req->setPaddr((pte->ppn << PageShift) +
+ (VAddr(req->getVaddr()).offset()
+ & ~3));
- hits++;
+ // check permissions for this access
+ if (!(pte->xre &
+ (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) {
+ // instruction access fault
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
}
+
+ hits++;
}
+ }
- // check that the physical address is ok (catch bad physical addresses)
- if (req->getPaddr() & ~PAddrImplMask)
- return genMachineCheckFault();
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
- return checkCacheability(req);
+ return checkCacheability(req);
- }
+}
- ///////////////////////////////////////////////////////////////////////
- //
- // Alpha DTB
- //
- DTB::DTB(const std::string &name, int size)
- : TLB(name, size)
- {}
-
- void
- DTB::regStats()
- {
- read_hits
- .name(name() + ".read_hits")
- .desc("DTB read hits")
- ;
-
- read_misses
- .name(name() + ".read_misses")
- .desc("DTB read misses")
- ;
-
- read_acv
- .name(name() + ".read_acv")
- .desc("DTB read access violations")
- ;
-
- read_accesses
- .name(name() + ".read_accesses")
- .desc("DTB read accesses")
- ;
-
- write_hits
- .name(name() + ".write_hits")
- .desc("DTB write hits")
- ;
-
- write_misses
- .name(name() + ".write_misses")
- .desc("DTB write misses")
- ;
-
- write_acv
- .name(name() + ".write_acv")
- .desc("DTB write access violations")
- ;
-
- write_accesses
- .name(name() + ".write_accesses")
- .desc("DTB write accesses")
- ;
-
- hits
- .name(name() + ".hits")
- .desc("DTB hits")
- ;
-
- misses
- .name(name() + ".misses")
- .desc("DTB misses")
- ;
-
- acv
- .name(name() + ".acv")
- .desc("DTB access violations")
- ;
-
- accesses
- .name(name() + ".accesses")
- .desc("DTB accesses")
- ;
-
- hits = read_hits + write_hits;
- misses = read_misses + write_misses;
- acv = read_acv + write_acv;
- accesses = read_accesses + write_accesses;
- }
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha DTB
+//
+ DTB::DTB(const std::string &name, int size)
+ : TLB(name, size)
+{}
- Fault
- DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const
- {
- Addr pc = tc->readPC();
+void
+DTB::regStats()
+{
+ read_hits
+ .name(name() + ".read_hits")
+ .desc("DTB read hits")
+ ;
+
+ read_misses
+ .name(name() + ".read_misses")
+ .desc("DTB read misses")
+ ;
+
+ read_acv
+ .name(name() + ".read_acv")
+ .desc("DTB read access violations")
+ ;
+
+ read_accesses
+ .name(name() + ".read_accesses")
+ .desc("DTB read accesses")
+ ;
+
+ write_hits
+ .name(name() + ".write_hits")
+ .desc("DTB write hits")
+ ;
+
+ write_misses
+ .name(name() + ".write_misses")
+ .desc("DTB write misses")
+ ;
+
+ write_acv
+ .name(name() + ".write_acv")
+ .desc("DTB write access violations")
+ ;
+
+ write_accesses
+ .name(name() + ".write_accesses")
+ .desc("DTB write accesses")
+ ;
+
+ hits
+ .name(name() + ".hits")
+ .desc("DTB hits")
+ ;
+
+ misses
+ .name(name() + ".misses")
+ .desc("DTB misses")
+ ;
+
+ acv
+ .name(name() + ".acv")
+ .desc("DTB access violations")
+ ;
+
+ accesses
+ .name(name() + ".accesses")
+ .desc("DTB accesses")
+ ;
+
+ hits = read_hits + write_hits;
+ misses = read_misses + write_misses;
+ acv = read_acv + write_acv;
+ accesses = read_accesses + write_accesses;
+}
- mode_type mode =
- (mode_type)DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM));
+Fault
+DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const
+{
+ Addr pc = tc->readPC();
+ mode_type mode =
+ (mode_type)DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM));
- /**
- * Check for alignment faults
- */
- if (req->getVaddr() & (req->getSize() - 1)) {
- DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
- req->getSize());
- uint64_t flags = write ? MM_STAT_WR_MASK : 0;
- return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
- }
- if (pc & 0x1) {
- mode = (req->getFlags() & ALTMODE) ?
- (mode_type)ALT_MODE_AM(
- tc->readMiscReg(IPR_ALT_MODE))
- : mode_kernel;
- }
+ /**
+ * Check for alignment faults
+ */
+ if (req->getVaddr() & (req->getSize() - 1)) {
+ DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
+ req->getSize());
+ uint64_t flags = write ? MM_STAT_WR_MASK : 0;
+ return new DtbAlignmentFault(req->getVaddr(), req->getFlags(), flags);
+ }
- if (req->getFlags() & PHYSICAL) {
- req->setPaddr(req->getVaddr());
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->getVaddr())) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
+ if (PcPAL(pc)) {
+ mode = (req->getFlags() & ALTMODE) ?
+ (mode_type)ALT_MODE_AM(
+ tc->readMiscReg(IPR_ALT_MODE))
+ : mode_kernel;
+ }
- // Check for "superpage" mapping
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ if (write) { write_acv++; } else { read_acv++; }
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_BAD_VA_MASK |
+ MM_STAT_ACV_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+
+ // Check for "superpage" mapping
#if ALPHA_TLASER
- if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->getVaddr()) == 2) {
+ if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) &&
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
#else
- if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
#endif
- // only valid in kernel mode
- if (DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)) !=
- mode_kernel) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_ACV_MASK);
- return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
- }
+ // only valid in kernel mode
+ if (DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)) !=
+ mode_kernel) {
+ if (write) { write_acv++; } else { read_acv++; }
+ uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
+ }
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->getPaddr() & PAddrUncachedBit40)
- req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
- else
- req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
#endif
+ } else {
+ if (write)
+ write_accesses++;
+ else
+ read_accesses++;
+
+ int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
+
+ // not a physical address: need to look up pte
+ PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ // page fault
+ if (write) { write_misses++; } else { read_misses++; }
+ uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_DTB_MISS_MASK;
+ return (req->getFlags() & VPTE) ?
+ (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags)) :
+ (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
+ flags));
+ }
+
+ req->setPaddr((pte->ppn << PageShift) +
+ VAddr(req->getVaddr()).offset());
+
+ if (write) {
+ if (!(pte->xwe & MODE2MASK(mode))) {
+ // declare the instruction access fault
+ write_acv++;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_ACV_MASK |
+ (pte->fonw ? MM_STAT_FONW_MASK : 0);
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+ if (pte->fonw) {
+ write_acv++;
+ uint64_t flags = MM_STAT_WR_MASK |
+ MM_STAT_FONW_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
} else {
- if (write)
- write_accesses++;
- else
- read_accesses++;
-
- int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN));
-
- // not a physical address: need to look up pte
- PTE *pte = lookup(VAddr(req->getVaddr()).vpn(),
- asn);
-
- if (!pte) {
- // page fault
- if (write) { write_misses++; } else { read_misses++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_DTB_MISS_MASK;
- return (req->getFlags() & VPTE) ?
- (Fault)(new PDtbMissFault(req->getVaddr(), req->getFlags(),
- flags)) :
- (Fault)(new NDtbMissFault(req->getVaddr(), req->getFlags(),
- flags));
+ if (!(pte->xre & MODE2MASK(mode))) {
+ read_acv++;
+ uint64_t flags = MM_STAT_ACV_MASK |
+ (pte->fonr ? MM_STAT_FONR_MASK : 0);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
}
-
- req->setPaddr((pte->ppn << PageShift) +
- VAddr(req->getVaddr()).offset());
-
- if (write) {
- if (!(pte->xwe & MODE2MASK(mode))) {
- // declare the instruction access fault
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0);
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
- if (pte->fonw) {
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_FONW_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
- } else {
- if (!(pte->xre & MODE2MASK(mode))) {
- read_acv++;
- uint64_t flags = MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0);
- return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
- }
- if (pte->fonr) {
- read_acv++;
- uint64_t flags = MM_STAT_FONR_MASK;
- return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
- }
+ if (pte->fonr) {
+ read_acv++;
+ uint64_t flags = MM_STAT_FONR_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
}
}
-
- if (write)
- write_hits++;
- else
- read_hits++;
}
- // check that the physical address is ok (catch bad physical addresses)
- if (req->getPaddr() & ~PAddrImplMask)
- return genMachineCheckFault();
-
- return checkCacheability(req);
+ if (write)
+ write_hits++;
+ else
+ read_hits++;
}
- PTE &
- TLB::index(bool advance)
- {
- PTE *pte = &table[nlu];
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
- if (advance)
- nextnlu();
+ return checkCacheability(req);
+}
- return *pte;
- }
+PTE &
+TLB::index(bool advance)
+{
+ PTE *pte = &table[nlu];
+
+ if (advance)
+ nextnlu();
- DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB)
+ return *pte;
+}
- BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
+DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB)
- Param<int> size;
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
- END_DECLARE_SIM_OBJECT_PARAMS(ITB)
+ Param<int> size;
- BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
+END_DECLARE_SIM_OBJECT_PARAMS(ITB)
- INIT_PARAM_DFLT(size, "TLB size", 48)
+BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
- END_INIT_SIM_OBJECT_PARAMS(ITB)
+ INIT_PARAM_DFLT(size, "TLB size", 48)
+END_INIT_SIM_OBJECT_PARAMS(ITB)
- CREATE_SIM_OBJECT(ITB)
- {
- return new ITB(getInstanceName(), size);
- }
- REGISTER_SIM_OBJECT("AlphaITB", ITB)
+CREATE_SIM_OBJECT(ITB)
+{
+ return new ITB(getInstanceName(), size);
+}
- BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
+REGISTER_SIM_OBJECT("AlphaITB", ITB)
- Param<int> size;
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
- END_DECLARE_SIM_OBJECT_PARAMS(DTB)
+ Param<int> size;
- BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
+END_DECLARE_SIM_OBJECT_PARAMS(DTB)
- INIT_PARAM_DFLT(size, "TLB size", 64)
+BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
- END_INIT_SIM_OBJECT_PARAMS(DTB)
+ INIT_PARAM_DFLT(size, "TLB size", 64)
+END_INIT_SIM_OBJECT_PARAMS(DTB)
- CREATE_SIM_OBJECT(DTB)
- {
- return new DTB(getInstanceName(), size);
- }
- REGISTER_SIM_OBJECT("AlphaDTB", DTB)
+CREATE_SIM_OBJECT(DTB)
+{
+ return new DTB(getInstanceName(), size);
+}
+
+REGISTER_SIM_OBJECT("AlphaDTB", DTB)
}
diff --git a/src/arch/mips/mmaped_ipr.hh b/src/arch/mips/mmaped_ipr.hh
index 041c76fdc..fa82a645c 100644
--- a/src/arch/mips/mmaped_ipr.hh
+++ b/src/arch/mips/mmaped_ipr.hh
@@ -37,8 +37,10 @@
* ISA-specific helper functions for memory mapped IPR accesses.
*/
+#include "base/misc.hh"
#include "mem/packet.hh"
+class ThreadContext;
namespace MipsISA
{
@@ -48,7 +50,6 @@ handleIprRead(ThreadContext *xc, Packet *pkt)
panic("No implementation for handleIprRead in MIPS\n");
}
-
inline Tick
handleIprWrite(ThreadContext *xc, Packet *pkt)
{
diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc
index b307ade33..a9a778ff6 100644
--- a/src/arch/sparc/asi.cc
+++ b/src/arch/sparc/asi.cc
@@ -185,6 +185,7 @@ namespace SparcISA
bool AsiIsTwin(ASI asi)
{
return
+ (asi == ASI_QUAD_LDD) ||
(asi == ASI_LDTX_AIUP) ||
(asi == ASI_LDTX_AIUS) ||
(asi == ASI_LDTX_REAL) ||
@@ -196,7 +197,8 @@ namespace SparcISA
(asi == ASI_LDTX_P) ||
(asi == ASI_LDTX_S) ||
(asi == ASI_LDTX_PL) ||
- (asi == ASI_LDTX_SL);
+ (asi == ASI_LDTX_SL) ||
+ (asi == ASI_LTX_L);
}
bool AsiIsPartialStore(ASI asi)
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
index fd20a14c1..53559c072 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -129,6 +129,26 @@ void MiscRegFile::clear()
MiscReg MiscRegFile::readReg(int miscReg)
{
switch (miscReg) {
+ case MISCREG_TLB_DATA:
+ /* Package up all the data for the tlb:
+ * 6666555555555544444444443333333333222222222211111111110000000000
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ * secContext | priContext | |tl|partid| |||||^hpriv
+ * ||||^red
+ * |||^priv
+ * ||^am
+ * |^lsuim
+ * ^lsudm
+ */
+ return bits((uint64_t)hpstate,2,2) |
+ bits((uint64_t)hpstate,5,5) << 1 |
+ bits((uint64_t)pstate,3,2) << 2 |
+ bits((uint64_t)lsuCtrlReg,3,2) << 4 |
+ bits((uint64_t)partId,7,0) << 8 |
+ bits((uint64_t)tl,2,0) << 16 |
+ (uint64_t)priContext << 32 |
+ (uint64_t)secContext << 48;
+
case MISCREG_Y:
return y;
case MISCREG_CCR:
@@ -294,16 +314,17 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
{
switch (miscReg) {
// tick and stick are aliased to each other in niagra
- case MISCREG_TICK:
+ // well store the tick data in stick and the interrupt bit in tick
case MISCREG_STICK:
+ case MISCREG_TICK:
case MISCREG_PRIVTICK:
// I'm not sure why legion ignores the lowest two bits, but we'll go
// with it
// change from curCycle() to instCount() until we're done with legion
- DPRINTFN("Instruction Count when STICK read: %#X\n",
- tc->getCpuPtr()->instCount());
- return mbits(tc->getCpuPtr()->instCount() - (tick &
- mask(63)),62,2) | mbits(tick,63,63) ;
+ DPRINTFN("Instruction Count when TICK read: %#X stick=%#X\n",
+ tc->getCpuPtr()->instCount(), stick);
+ return mbits(tc->getCpuPtr()->instCount() + (int32_t)stick,62,2) |
+ mbits(tick,63,63);
case MISCREG_FPRS:
warn("FPRS register read and FPU stuff not really implemented\n");
return fprs;
@@ -320,7 +341,6 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
case MISCREG_SOFTINT:
case MISCREG_TICK_CMPR:
case MISCREG_STICK_CMPR:
- case MISCREG_HPSTATE:
case MISCREG_HINTP:
case MISCREG_HTSTATE:
case MISCREG_HTBA:
@@ -336,9 +356,16 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
case MISCREG_QUEUE_NRES_ERROR_HEAD:
case MISCREG_QUEUE_NRES_ERROR_TAIL:
#if FULL_SYSTEM
+ case MISCREG_HPSTATE:
return readFSRegWithEffect(miscReg, tc);
#else
- panic("Accessing Fullsystem register is SE mode\n");
+ case MISCREG_HPSTATE:
+ //HPSTATE is special because because sometimes in privilege checks for instructions
+ //it will read HPSTATE to make sure the priv. level is ok
+ //So, we'll just have to tell it it isn't, instead of panicing.
+ return 0;
+
+ panic("Accessing Fullsystem register %s in SE mode\n",getMiscRegName(miscReg));
#endif
}
@@ -581,13 +608,14 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
void MiscRegFile::setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc)
{
- const uint64_t Bit64 = (1ULL << 63);
switch (miscReg) {
case MISCREG_STICK:
case MISCREG_TICK:
- // change from curCycle() to instCount() until we're done with legion
- tick = tc->getCpuPtr()->instCount() - val & ~Bit64;
- tick |= val & Bit64;
+ // stick and tick are same thing on niagra
+ // use stick for offset and tick for holding intrrupt bit
+ stick = mbits(val,62,0) - tc->getCpuPtr()->instCount();
+ tick = mbits(val,63,63);
+ DPRINTFN("Writing TICK=%#X\n", val);
break;
case MISCREG_FPRS:
//Configure the fpu based on the fprs
@@ -611,7 +639,6 @@ void MiscRegFile::setRegWithEffect(int miscReg,
case MISCREG_SOFTINT:
case MISCREG_TICK_CMPR:
case MISCREG_STICK_CMPR:
- case MISCREG_HPSTATE:
case MISCREG_HINTP:
case MISCREG_HTSTATE:
case MISCREG_HTBA:
@@ -627,10 +654,15 @@ void MiscRegFile::setRegWithEffect(int miscReg,
case MISCREG_QUEUE_NRES_ERROR_HEAD:
case MISCREG_QUEUE_NRES_ERROR_TAIL:
#if FULL_SYSTEM
+ case MISCREG_HPSTATE:
setFSRegWithEffect(miscReg, val, tc);
return;
#else
- panic("Accessing Fullsystem register is SE mode\n");
+ case MISCREG_HPSTATE:
+ //HPSTATE is special because normal trap processing saves HPSTATE when
+ //it goes into a trap, and restores it when it returns.
+ return;
+ panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val);
#endif
}
setReg(miscReg, val);
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index d09005795..c879fd357 100644
--- a/src/arch/sparc/miscregfile.hh
+++ b/src/arch/sparc/miscregfile.hh
@@ -137,6 +137,8 @@ namespace SparcISA
MISCREG_QUEUE_NRES_ERROR_HEAD,
MISCREG_QUEUE_NRES_ERROR_TAIL,
+ /* All the data for the TLB packed up in one register. */
+ MISCREG_TLB_DATA,
MISCREG_NUMMISCREGS
};
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index b0fc562ac..675287d18 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -45,7 +45,7 @@ namespace SparcISA
{
TLB::TLB(const std::string &name, int s)
- : SimObject(name), size(s)
+ : SimObject(name), size(s), usedEntries(0), cacheValid(false)
{
// To make this work you'll have to change the hypervisor and OS
if (size > 64)
@@ -79,6 +79,8 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
TlbEntry *new_entry = NULL;
int x;
+ cacheValid = false;
+
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);
@@ -194,6 +196,8 @@ TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
TlbRange tr;
MapIter i;
+ cacheValid = false;
+
// Assemble full address structure
tr.va = va;
tr.size = va + MachineBytes;
@@ -217,6 +221,7 @@ void
TLB::demapContext(int partition_id, int context_id)
{
int x;
+ cacheValid = false;
for (x = 0; x < size; x++) {
if (tlb[x].range.contextId == context_id &&
tlb[x].range.partitionId == partition_id) {
@@ -234,6 +239,7 @@ void
TLB::demapAll(int partition_id)
{
int x;
+ cacheValid = false;
for (x = 0; x < size; x++) {
if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
tlb[x].valid = false;
@@ -250,6 +256,8 @@ void
TLB::invalidateAll()
{
int x;
+ cacheValid = false;
+
for (x = 0; x < size; x++) {
tlb[x].valid = false;
}
@@ -337,7 +345,7 @@ DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a);
}
- void
+void
DTB::writeTagAccess(ThreadContext *tc, Addr va, int context)
{
TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context);
@@ -348,26 +356,47 @@ DTB::writeTagAccess(ThreadContext *tc, Addr va, int context)
Fault
ITB::translate(RequestPtr &req, ThreadContext *tc)
{
- uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
- uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
- bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
- uint64_t tl = tc->readMiscReg(MISCREG_TL);
- uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
- bool addr_mask = pstate >> 3 & 0x1;
- bool priv = pstate >> 2 & 0x1;
+ uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
+
Addr vaddr = req->getVaddr();
- int context;
- ContextType ct;
- int asi;
- bool real = false;
TlbEntry *e;
+ assert(req->getAsi() == ASI_IMPLICIT);
+
DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
vaddr, req->getSize());
- DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n",
- pstate, hpstate, lsuIm, part_id);
- assert(req->getAsi() == ASI_IMPLICIT);
+ // Be fast if we can!
+ if (cacheValid && cacheState == tlbdata) {
+ if (cacheEntry) {
+ if (cacheEntry->range.va < vaddr + sizeof(MachInst) &&
+ cacheEntry->range.va + cacheEntry->range.size >= vaddr) {
+ req->setPaddr(cacheEntry->pte.paddr() & ~(cacheEntry->pte.size()-1) |
+ vaddr & cacheEntry->pte.size()-1 );
+ return NoFault;
+ }
+ } else {
+ req->setPaddr(vaddr & PAddrImplMask);
+ return NoFault;
+ }
+ }
+
+ bool hpriv = bits(tlbdata,0,0);
+ bool red = bits(tlbdata,1,1);
+ bool priv = bits(tlbdata,2,2);
+ bool addr_mask = bits(tlbdata,3,3);
+ bool lsu_im = bits(tlbdata,4,4);
+
+ int part_id = bits(tlbdata,15,8);
+ int tl = bits(tlbdata,18,16);
+ int pri_context = bits(tlbdata,47,32);
+ int context;
+ ContextType ct;
+ int asi;
+ bool real = false;
+
+ DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n",
+ priv, hpriv, red, lsu_im, part_id);
if (tl > 0) {
asi = ASI_N;
@@ -376,16 +405,19 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
} else {
asi = ASI_P;
ct = Primary;
- context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+ context = pri_context;
}
- if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ if ( hpriv || red ) {
+ cacheValid = true;
+ cacheState = tlbdata;
+ cacheEntry = NULL;
+ req->setPaddr(vaddr & PAddrImplMask);
return NoFault;
}
- // If the asi is unaligned trap
- if (vaddr & req->getSize()-1) {
+ // If the access is unaligned trap
+ if (vaddr & 0x3) {
writeSfsr(tc, false, ct, false, OtherFault, asi);
return new MemAddressNotAligned;
}
@@ -398,8 +430,8 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
return new InstructionAccessException;
}
- if (!lsuIm) {
- e = lookup(req->getVaddr(), part_id, true);
+ if (!lsu_im) {
+ e = lookup(vaddr, part_id, true);
real = true;
context = 0;
} else {
@@ -421,9 +453,14 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
return new InstructionAccessException;
}
+ // cache translation date for next translation
+ cacheValid = true;
+ cacheState = tlbdata;
+ cacheEntry = e;
+
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
- req->getVaddr() & e->pte.size()-1 );
- DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
+ vaddr & e->pte.size()-1 );
+ DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
return NoFault;
}
@@ -433,33 +470,60 @@ Fault
DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
{
/* @todo this could really use some profiling and fixing to make it faster! */
- uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
- uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
- bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
- uint64_t tl = tc->readMiscReg(MISCREG_TL);
- uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
- bool hpriv = hpstate >> 2 & 0x1;
- bool red = hpstate >> 5 >> 0x1;
- bool addr_mask = pstate >> 3 & 0x1;
- bool priv = pstate >> 2 & 0x1;
- bool implicit = false;
- bool real = false;
+ uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
Addr vaddr = req->getVaddr();
Addr size = req->getSize();
- ContextType ct;
- int context;
ASI asi;
-
- TlbEntry *e;
-
asi = (ASI)req->getAsi();
+ bool implicit = false;
+ bool hpriv = bits(tlbdata,0,0);
+
DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
vaddr, size, asi);
- DPRINTF(TLB, "TLB: pstate: %#X hpstate: %#X lsudm: %#X part_id: %#X\n",
- pstate, hpstate, lsuDm, part_id);
+
if (asi == ASI_IMPLICIT)
implicit = true;
+ if (hpriv && implicit) {
+ req->setPaddr(vaddr & PAddrImplMask);
+ return NoFault;
+ }
+
+ // Be fast if we can!
+ if (cacheValid && cacheState == tlbdata) {
+ if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size &&
+ cacheEntry[0]->range.va + cacheEntry[0]->range.size >= vaddr) {
+ req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) |
+ vaddr & cacheEntry[0]->pte.size()-1 );
+ return NoFault;
+ }
+ if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size &&
+ cacheEntry[1]->range.va + cacheEntry[1]->range.size >= vaddr) {
+ req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) |
+ vaddr & cacheEntry[1]->pte.size()-1 );
+ return NoFault;
+ }
+ }
+
+ bool red = bits(tlbdata,1,1);
+ bool priv = bits(tlbdata,2,2);
+ bool addr_mask = bits(tlbdata,3,3);
+ bool lsu_dm = bits(tlbdata,5,5);
+
+ int part_id = bits(tlbdata,15,8);
+ int tl = bits(tlbdata,18,16);
+ int pri_context = bits(tlbdata,47,32);
+ int sec_context = bits(tlbdata,47,32);
+
+ bool real = false;
+ ContextType ct = Primary;
+ int context = 0;
+
+ TlbEntry *e;
+
+ DPRINTF(TLB, "TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n",
+ priv, hpriv, red, lsu_dm, part_id);
+
if (implicit) {
if (tl > 0) {
asi = ASI_N;
@@ -468,7 +532,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
} else {
asi = ASI_P;
ct = Primary;
- context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+ context = pri_context;
}
} else if (!hpriv && !red) {
if (tl > 0 || AsiIsNucleus(asi)) {
@@ -476,9 +540,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
context = 0;
} else if (AsiIsSecondary(asi)) {
ct = Secondary;
- context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
+ context = sec_context;
} else {
- context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+ context = pri_context;
ct = Primary; //???
}
@@ -496,7 +560,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
} else if (hpriv) {
if (asi == ASI_P) {
ct = Primary;
- context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
+ context = pri_context;
goto continueDtbFlow;
}
}
@@ -508,6 +572,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
panic("Block ASIs not supported\n");
if (AsiIsNoFault(asi))
panic("No Fault ASIs not supported\n");
+ if (write && asi == ASI_LDTX_P)
+ // block init store (like write hint64)
+ goto continueDtbFlow;
if (AsiIsTwin(asi))
panic("Twin ASIs not supported\n");
if (AsiIsPartialStore(asi))
@@ -544,17 +611,17 @@ continueDtbFlow:
}
- if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
+ if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) {
real = true;
context = 0;
};
if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
- req->setPaddr(req->getVaddr() & PAddrImplMask);
+ req->setPaddr(vaddr & PAddrImplMask);
return NoFault;
}
- e = lookup(req->getVaddr(), part_id, real, context);
+ e = lookup(vaddr, part_id, real, context);
if (e == NULL || !e->valid) {
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
@@ -587,9 +654,21 @@ continueDtbFlow:
return new DataAccessException;
}
+ // cache translation date for next translation
+ cacheValid = true;
+ cacheState = tlbdata;
+ if (cacheEntry[0] != e && cacheEntry[1] != e) {
+ cacheEntry[1] = cacheEntry[0];
+ cacheEntry[0] = e;
+ cacheAsi[1] = cacheAsi[0];
+ cacheAsi[0] = asi;
+ if (implicit)
+ cacheAsi[0] = (ASI)0;
+ }
+
req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
- req->getVaddr() & e->pte.size()-1);
- DPRINTF(TLB, "TLB: %#X -> %#X\n", req->getVaddr(), req->getPaddr());
+ vaddr & e->pte.size()-1);
+ DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
return NoFault;
/** Normal flow ends here. */
@@ -637,6 +716,8 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
{
Addr va = pkt->getAddr();
ASI asi = (ASI)pkt->req->getAsi();
+ uint64_t temp, data;
+ uint64_t tsbtemp, cnftemp;
DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
(uint32_t)pkt->req->getAsi(), pkt->getAddr());
@@ -720,6 +801,10 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
break;
case ASI_IMMU:
switch (va) {
+ case 0x0:
+ temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
+ pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
+ break;
case 0x30:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS));
break;
@@ -729,6 +814,10 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
break;
case ASI_DMMU:
switch (va) {
+ case 0x0:
+ temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
+ pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
+ break;
case 0x30:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS));
break;
@@ -739,6 +828,37 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
goto doMmuReadError;
}
break;
+ case ASI_DMMU_TSB_PS0_PTR_REG:
+ temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
+ if (bits(temp,12,0) == 0) {
+ tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0);
+ cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
+ } else {
+ tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0);
+ cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
+ }
+ data = mbits(tsbtemp,63,13);
+ data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
+ mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
+ pkt->set(data);
+ break;
+ case ASI_DMMU_TSB_PS1_PTR_REG:
+ temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
+ if (bits(temp,12,0) == 0) {
+ tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1);
+ cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
+ } else {
+ tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1);
+ cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
+ }
+ data = mbits(tsbtemp,63,13);
+ if (bits(tsbtemp,12,12))
+ data |= ULL(1) << (13+bits(tsbtemp,3,0));
+ data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
+ mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
+ pkt->set(data);
+ break;
+
default:
doMmuReadError:
panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
index 8a4ccd69f..f69b40ffb 100644
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -31,6 +31,7 @@
#ifndef __ARCH_SPARC_TLB_HH__
#define __ARCH_SPARC_TLB_HH__
+#include "arch/sparc/asi.hh"
#include "arch/sparc/tlb_map.hh"
#include "base/misc.hh"
#include "mem/request.hh"
@@ -54,6 +55,9 @@ class TLB : public SimObject
int size;
int usedEntries;
+ uint64_t cacheState;
+ bool cacheValid;
+
enum FaultTypes {
OtherFault = 0,
PrivViolation = 0x1,
@@ -131,6 +135,7 @@ class ITB : public TLB
public:
ITB(const std::string &name, int size) : TLB(name, size)
{
+ cacheEntry = NULL;
}
Fault translate(RequestPtr &req, ThreadContext *tc);
@@ -138,6 +143,7 @@ class ITB : public TLB
void writeSfsr(ThreadContext *tc, bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
void writeTagAccess(ThreadContext *tc, Addr va, int context);
+ TlbEntry *cacheEntry;
friend class DTB;
};
@@ -146,6 +152,8 @@ class DTB : public TLB
public:
DTB(const std::string &name, int size) : TLB(name, size)
{
+ cacheEntry[0] = NULL;
+ cacheEntry[1] = NULL;
}
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
@@ -157,7 +165,8 @@ class DTB : public TLB
bool se, FaultTypes ft, int asi);
void writeTagAccess(ThreadContext *tc, Addr va, int context);
-
+ TlbEntry *cacheEntry[2];
+ ASI cacheAsi[2];
};
}
diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh
index 226ef23a1..688daf5b9 100644
--- a/src/arch/sparc/tlb_map.hh
+++ b/src/arch/sparc/tlb_map.hh
@@ -53,8 +53,15 @@ class TlbMap
i = tree.upper_bound(r);
if (i == tree.begin())
- // Nothing could match, so return end()
- return tree.end();
+ if (r.real == i->first.real &&
+ r.partitionId == i->first.partitionId &&
+ i->first.va < r.va + r.size &&
+ i->first.va+i->first.size >= r.va &&
+ (r.real || r.contextId == i->first.contextId))
+ return i;
+ else
+ // Nothing could match, so return end()
+ return tree.end();
i--;
diff --git a/src/base/range_map.hh b/src/base/range_map.hh
index 17ecb9290..6d3450739 100644
--- a/src/base/range_map.hh
+++ b/src/base/range_map.hh
@@ -52,9 +52,13 @@ class range_map
i = tree.upper_bound(r);
- if (i == tree.begin())
- // Nothing could match, so return end()
- return tree.end();
+ if (i == tree.begin()) {
+ if (i->first.start <= r.end && i->first.end >= r.start)
+ return i;
+ else
+ // Nothing could match, so return end()
+ return tree.end();
+ }
i--;
@@ -126,4 +130,117 @@ class range_map
};
+template <class T,class V>
+class range_multimap
+{
+ private:
+ typedef std::multimap<Range<T>,V> RangeMap;
+ RangeMap tree;
+
+ public:
+ typedef typename RangeMap::iterator iterator;
+
+ template <class U>
+ std::pair<iterator,iterator> find(const Range<U> &r)
+ {
+ iterator i;
+ iterator j;
+
+ i = tree.lower_bound(r);
+
+ if (i == tree.begin()) {
+ if (i->first.start <= r.end && i->first.end >= r.start)
+ return std::make_pair<iterator, iterator>(i,i);
+ else
+ // Nothing could match, so return end()
+ return std::make_pair<iterator, iterator>(tree.end(), tree.end());
+ }
+ i--;
+
+ if (i->first.start <= r.end && i->first.end >= r.start) {
+ // we have at least one match
+ j = i;
+
+ i--;
+ while (i->first.start <= r.end && i->first.end >=
+ r.start) {
+ if (i == tree.begin())
+ break;
+ i--;
+ }
+ if (i == tree.begin() && i->first.start <= r.end && i->first.end >=
+ r.start)
+ return std::make_pair<iterator, iterator>(i,j);
+ i++;
+ return std::make_pair<iterator, iterator>(i,j);
+
+ }
+
+ return std::make_pair<iterator, iterator>(tree.end(), tree.end());
+ }
+
+ template <class U>
+ bool intersect(const Range<U> &r)
+ {
+ std::pair<iterator,iterator> p;
+ p = find(r);
+ if (p.first != tree.end())
+ return true;
+ return false;
+ }
+
+
+ template <class U,class W>
+ iterator insert(const Range<U> &r, const W d)
+ {
+ std::pair<iterator,iterator> p;
+ p = find(r);
+ if (p.first->first.start == r.start && p.first->first.end == r.end ||
+ p.first == tree.end())
+ return tree.insert(std::make_pair<Range<T>,V>(r, d));
+ else
+ return tree.end();
+ }
+
+ size_t erase(T k)
+ {
+ return tree.erase(k);
+ }
+
+ void erase(iterator p)
+ {
+ tree.erase(p);
+ }
+
+ void erase(iterator p, iterator q)
+ {
+ tree.erase(p,q);
+ }
+
+ void clear()
+ {
+ tree.erase(tree.begin(), tree.end());
+ }
+
+ iterator begin()
+ {
+ return tree.begin();
+ }
+
+ iterator end()
+ {
+ return tree.end();
+ }
+
+ size_t size()
+ {
+ return tree.size();
+ }
+
+ bool empty()
+ {
+ return tree.empty();
+ }
+};
+
#endif //__BASE_RANGE_MAP_HH__
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 7c4c037ce..3fe40b4c1 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -57,7 +57,9 @@
using namespace std;
using namespace TheISA;
+#if THE_ISA == SPARC_ISA && FULL_SYSTEM
static int diffcount = 0;
+#endif
namespace Trace {
SharedData *shared_data = NULL;
@@ -399,7 +401,7 @@ Trace::InstRecord::dump(ostream &outs)
diffCcr || diffTl || diffGl || diffAsi || diffPil ||
diffCwp || diffCansave || diffCanrestore ||
diffOtherwin || diffCleanwin)
- && !((staticInst->machInst & 0xE1F80000) == 0xE1F80000)) {
+ && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) {
outs << "Differences found between M5 and Legion:";
if (diffPC)
outs << " [PC]";
@@ -575,7 +577,7 @@ Trace::InstRecord::dump(ostream &outs)
thread->getDTBPtr()->dumpAll();
diffcount++;
- if (diffcount > 3)
+ if (diffcount > 2)
fatal("Differences found between Legion and M5\n");
}
diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc
index 5fc787084..4a8de77a5 100644
--- a/src/dev/sparc/t1000.cc
+++ b/src/dev/sparc/t1000.cc
@@ -62,13 +62,15 @@ T1000::intrFrequency()
void
T1000::postConsoleInt()
{
- panic("Need implementation\n");
+ warn_once("Don't know what interrupt to post for console.\n");
+ //panic("Need implementation\n");
}
void
T1000::clearConsoleInt()
{
- panic("Need implementation\n");
+ warn_once("Don't know what interrupt to clear for console.\n");
+ //panic("Need implementation\n");
}
void
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index e9a870b80..bd721dd68 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -260,19 +260,12 @@ Bus::findPort(Addr addr, int id)
{
/* An interval tree would be a better way to do this. --ali. */
int dest_id = -1;
- int i = 0;
- bool found = false;
AddrRangeIter iter;
+ range_map<Addr,int>::iterator i;
- while (i < portList.size() && !found)
- {
- if (portList[i].range == addr) {
- dest_id = portList[i].portId;
- found = true;
- DPRINTF(Bus, " found addr %#llx on device %d\n", addr, dest_id);
- }
- i++;
- }
+ i = portMap.find(RangeSize(addr,1));
+ if (i != portMap.end())
+ dest_id = i->second;
// Check if this matches the default range
if (dest_id == -1) {
@@ -463,13 +456,13 @@ Bus::recvStatusChange(Port::Status status, int id)
assert((id < interfaces.size() && id >= 0) || id == defaultId);
Port *port = interfaces[id];
- std::vector<DevMap>::iterator portIter;
+ range_map<Addr,int>::iterator portIter;
std::vector<DevMap>::iterator snoopIter;
// Clean out any previously existent ids
- for (portIter = portList.begin(); portIter != portList.end(); ) {
- if (portIter->portId == id)
- portIter = portList.erase(portIter);
+ for (portIter = portMap.begin(); portIter != portMap.end(); ) {
+ if (portIter->second == id)
+ portMap.erase(portIter++);
else
portIter++;
}
@@ -495,16 +488,14 @@ Bus::recvStatusChange(Port::Status status, int id)
}
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
- DevMap dm;
- dm.portId = id;
- dm.range = *iter;
-
DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n",
- dm.range.start, dm.range.end, id);
- portList.push_back(dm);
+ iter->start, iter->end, id);
+ if (portMap.insert(*iter, id) == portMap.end())
+ panic("Two devices with same range\n");
+
}
}
- DPRINTF(MMU, "port list has %d entries\n", portList.size());
+ DPRINTF(MMU, "port list has %d entries\n", portMap.size());
// tell all our peers that our address range has changed.
// Don't tell the device that caused this change, it already knows
@@ -519,7 +510,8 @@ Bus::recvStatusChange(Port::Status status, int id)
void
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
{
- std::vector<DevMap>::iterator portIter;
+ std::vector<DevMap>::iterator snoopIter;
+ range_map<Addr,int>::iterator portIter;
AddrRangeIter dflt_iter;
bool subset;
@@ -534,37 +526,37 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start,
dflt_iter->end);
}
- for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
+ for (portIter = portMap.begin(); portIter != portMap.end(); portIter++) {
subset = false;
for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
dflt_iter++) {
- if ((portIter->range.start < dflt_iter->start &&
- portIter->range.end >= dflt_iter->start) ||
- (portIter->range.start < dflt_iter->end &&
- portIter->range.end >= dflt_iter->end))
+ if ((portIter->first.start < dflt_iter->start &&
+ portIter->first.end >= dflt_iter->start) ||
+ (portIter->first.start < dflt_iter->end &&
+ portIter->first.end >= dflt_iter->end))
fatal("Devices can not set ranges that itersect the default set\
but are not a subset of the default set.\n");
- if (portIter->range.start >= dflt_iter->start &&
- portIter->range.end <= dflt_iter->end) {
+ if (portIter->first.start >= dflt_iter->start &&
+ portIter->first.end <= dflt_iter->end) {
subset = true;
DPRINTF(BusAddrRanges, " -- %#llx : %#llx is a SUBSET\n",
- portIter->range.start, portIter->range.end);
+ portIter->first.start, portIter->first.end);
}
}
- if (portIter->portId != id && !subset) {
- resp.push_back(portIter->range);
+ if (portIter->second != id && !subset) {
+ resp.push_back(portIter->first);
DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n",
- portIter->range.start, portIter->range.end);
+ portIter->first.start, portIter->first.end);
}
}
- for (portIter = portSnoopList.begin();
- portIter != portSnoopList.end(); portIter++)
+ for (snoopIter = portSnoopList.begin();
+ snoopIter != portSnoopList.end(); snoopIter++)
{
- if (portIter->portId != id) {
- snoop.push_back(portIter->range);
+ if (snoopIter->portId != id) {
+ snoop.push_back(snoopIter->range);
DPRINTF(BusAddrRanges, " -- Snoop: %#llx : %#llx\n",
- portIter->range.start, portIter->range.end);
+ snoopIter->range.start, snoopIter->range.end);
//@todo We need to properly insert snoop ranges
//not overlapping the ranges (multiple)
}
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index c472b6143..0ad4aad60 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -42,6 +42,7 @@
#include <inttypes.h>
#include "base/range.hh"
+#include "base/range_map.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
@@ -67,7 +68,7 @@ class Bus : public MemObject
int portId;
Range<Addr> range;
};
- std::vector<DevMap> portList;
+ range_map<Addr, int> portMap;
AddrRangeList defaultRange;
std::vector<DevMap> portSnoopList;
diff --git a/src/unittest/rangemaptest.cc b/src/unittest/rangemaptest.cc
index 6fd99c927..983a41520 100644
--- a/src/unittest/rangemaptest.cc
+++ b/src/unittest/rangemaptest.cc
@@ -41,7 +41,7 @@ int main()
range_map<Addr,int>::iterator i;
- i = r.insert(RangeIn<Addr>(0,40),5);
+ i = r.insert(RangeIn<Addr>(10,40),5);
assert(i != r.end());
i = r.insert(RangeIn<Addr>(60,90),3);
assert(i != r.end());
@@ -52,6 +52,17 @@ int main()
i = r.find(RangeIn(55,55));
assert(i == r.end());
+
+ i = r.insert(RangeIn<Addr>(0,12),1);
+ assert(i == r.end());
+
+ i = r.insert(RangeIn<Addr>(0,9),1);
+ assert(i != r.end());
+
+ i = r.find(RangeIn(20,30));
+ assert(i != r.end());
+ cout << i->first << " " << i->second << endl;
+
}
diff --git a/src/unittest/rangemaptest2.cc b/src/unittest/rangemaptest2.cc
new file mode 100644
index 000000000..b253dbe86
--- /dev/null
+++ b/src/unittest/rangemaptest2.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include <iostream>
+#include <cassert>
+#include "sim/host.hh"
+#include "base/range_map.hh"
+
+using namespace std;
+
+int main()
+{
+ range_multimap<Addr,int> r;
+
+ range_multimap<Addr,int>::iterator i;
+ std::pair<range_multimap<Addr,int>::iterator,range_multimap<Addr,int>::iterator>
+ jk;
+
+ i = r.insert(RangeIn<Addr>(10,40),5);
+ assert(i != r.end());
+ i = r.insert(RangeIn<Addr>(10,40),6);
+ assert(i != r.end());
+ i = r.insert(RangeIn<Addr>(60,90),3);
+ assert(i != r.end());
+
+ jk = r.find(RangeIn(20,30));
+ assert(jk.first != r.end());
+ cout << jk.first->first << " " << jk.first->second << endl;
+ cout << jk.second->first << " " << jk.second->second << endl;
+
+ i = r.insert(RangeIn<Addr>(0,3),5);
+ assert(i != r.end());
+
+ for( i = r.begin(); i != r.end(); i++)
+ cout << i->first << " " << i->second << endl;
+
+ jk = r.find(RangeIn(20,30));
+ assert(jk.first != r.end());
+ cout << jk.first->first << " " << jk.first->second << endl;
+ cout << jk.second->first << " " << jk.second->second << endl;
+
+
+}
+
+
+
+
+
+
+
+