summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/common/FSConfig.py17
-rw-r--r--configs/example/fs.py13
-rw-r--r--src/arch/SConscript1
-rw-r--r--src/arch/alpha/mmaped_ipr.hh61
-rw-r--r--src/arch/alpha/tlb.cc924
-rwxr-xr-xsrc/arch/isa_parser.py2
-rw-r--r--src/arch/mips/mmaped_ipr.hh62
-rw-r--r--src/arch/sparc/SConscript2
-rw-r--r--src/arch/sparc/asi.cc112
-rw-r--r--src/arch/sparc/asi.hh111
-rw-r--r--src/arch/sparc/faults.cc74
-rw-r--r--src/arch/sparc/floatregfile.hh5
-rw-r--r--src/arch/sparc/interrupts.hh41
-rw-r--r--src/arch/sparc/intregfile.cc17
-rw-r--r--src/arch/sparc/intregfile.hh10
-rw-r--r--src/arch/sparc/isa/base.isa2
-rw-r--r--src/arch/sparc/isa/decoder.isa67
-rw-r--r--src/arch/sparc/isa/formats/mem/basicmem.isa19
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa12
-rw-r--r--src/arch/sparc/isa/formats/mem/util.isa80
-rw-r--r--src/arch/sparc/isa/formats/priv.isa19
-rw-r--r--src/arch/sparc/isa/operands.isa2
-rw-r--r--src/arch/sparc/isa_traits.hh71
-rw-r--r--src/arch/sparc/miscregfile.cc962
-rw-r--r--src/arch/sparc/miscregfile.hh136
-rw-r--r--src/arch/sparc/mmaped_ipr.hh72
-rw-r--r--src/arch/sparc/pagetable.cc69
-rw-r--r--src/arch/sparc/pagetable.hh188
-rw-r--r--src/arch/sparc/process.cc3
-rw-r--r--src/arch/sparc/regfile.cc89
-rw-r--r--src/arch/sparc/regfile.hh4
-rw-r--r--src/arch/sparc/sparc_traits.hh55
-rw-r--r--src/arch/sparc/system.cc113
-rw-r--r--src/arch/sparc/system.hh36
-rw-r--r--src/arch/sparc/tlb.cc1047
-rw-r--r--src/arch/sparc/tlb.hh159
-rw-r--r--src/arch/sparc/tlb_map.hh142
-rw-r--r--src/arch/sparc/ua2005.cc232
-rw-r--r--src/arch/sparc/vtophys.hh1
-rw-r--r--src/base/bitfield.hh12
-rw-r--r--src/base/loader/aout_object.cc4
-rw-r--r--src/base/loader/aout_object.hh6
-rw-r--r--src/base/loader/ecoff_object.cc4
-rw-r--r--src/base/loader/ecoff_object.hh6
-rw-r--r--src/base/loader/elf_object.cc4
-rw-r--r--src/base/loader/elf_object.hh6
-rw-r--r--src/base/loader/object_file.hh6
-rw-r--r--src/base/loader/raw_object.cc8
-rw-r--r--src/base/loader/raw_object.hh6
-rw-r--r--src/base/range_map.hh246
-rw-r--r--src/base/traceflags.py1
-rw-r--r--src/cpu/base.cc2
-rw-r--r--src/cpu/base.hh4
-rw-r--r--src/cpu/exetrace.cc307
-rw-r--r--src/cpu/m5legion_interface.h4
-rw-r--r--src/cpu/memtest/memtest.hh2
-rw-r--r--src/cpu/o3/fetch.hh2
-rwxr-xr-xsrc/cpu/o3/isa_specific.hh5
-rw-r--r--src/cpu/o3/lsq.hh2
-rw-r--r--src/cpu/o3/sparc/cpu.cc38
-rw-r--r--src/cpu/o3/sparc/cpu.hh207
-rw-r--r--src/cpu/o3/sparc/cpu_builder.cc433
-rw-r--r--src/cpu/o3/sparc/cpu_impl.hh319
-rw-r--r--src/cpu/o3/sparc/dyn_inst.cc36
-rw-r--r--src/cpu/o3/sparc/dyn_inst.hh273
-rw-r--r--src/cpu/o3/sparc/dyn_inst_impl.hh139
-rw-r--r--src/cpu/o3/sparc/impl.hh92
-rw-r--r--src/cpu/o3/sparc/params.hh63
-rwxr-xr-xsrc/cpu/o3/sparc/thread_context.cc35
-rw-r--r--src/cpu/o3/sparc/thread_context.hh84
-rw-r--r--src/cpu/ozone/front_end.hh2
-rw-r--r--src/cpu/ozone/lw_lsq.hh2
-rw-r--r--src/cpu/simple/atomic.cc33
-rw-r--r--src/cpu/simple/atomic.hh2
-rw-r--r--src/cpu/simple/timing.hh2
-rw-r--r--src/dev/alpha/tsunami_cchip.cc2
-rw-r--r--src/dev/alpha/tsunami_io.cc2
-rw-r--r--src/dev/alpha/tsunami_pchip.cc2
-rw-r--r--src/dev/baddev.cc2
-rw-r--r--src/dev/isa_fake.cc77
-rw-r--r--src/dev/isa_fake.hh15
-rw-r--r--src/dev/sparc/SConscript1
-rw-r--r--src/dev/sparc/t1000.cc132
-rw-r--r--src/dev/sparc/t1000.hh108
-rw-r--r--src/mem/bus.cc70
-rw-r--r--src/mem/bus.hh3
-rw-r--r--src/mem/physical.cc11
-rw-r--r--src/mem/physical.hh1
-rw-r--r--src/mem/request.hh41
-rw-r--r--src/python/m5/objects/Bus.py4
-rw-r--r--src/python/m5/objects/Device.py16
-rw-r--r--src/python/m5/objects/PhysicalMemory.py1
-rw-r--r--src/python/m5/objects/System.py25
-rw-r--r--src/python/m5/objects/T1000.py82
-rw-r--r--src/python/m5/objects/Tsunami.py13
-rw-r--r--src/sim/host.hh2
-rw-r--r--src/sim/system.cc65
-rw-r--r--src/unittest/rangemaptest.cc74
-rw-r--r--src/unittest/rangemaptest2.cc78
99 files changed, 6801 insertions, 1455 deletions
diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py
index 546569f30..72742775f 100644
--- a/configs/common/FSConfig.py
+++ b/configs/common/FSConfig.py
@@ -84,17 +84,30 @@ def makeSparcSystem(mem_mode, mdesc = None):
# generic system
mdesc = SysConfig()
self.readfile = mdesc.script()
+ self.iobus = Bus(bus_id=0)
self.membus = Bus(bus_id=1)
- self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
+ self.bridge = Bridge()
+ self.t1000 = T1000()
+ self.t1000.attachIO(self.iobus)
+ self.physmem = PhysicalMemory(range = AddrRange(Addr('1MB'), size = '64MB'), zero = True)
+ self.physmem2 = PhysicalMemory(range = AddrRange(Addr('2GB'), size ='256MB'), zero = True)
+ self.bridge.side_a = self.iobus.port
+ self.bridge.side_b = self.membus.port
self.physmem.port = self.membus.port
+ self.physmem2.port = self.membus.port
self.rom.port = self.membus.port
+ self.nvram.port = self.membus.port
+ self.hypervisor_desc.port = self.membus.port
+ self.partition_desc.port = self.membus.port
self.intrctrl = IntrControl()
self.mem_mode = mem_mode
- self.kernel = binary('vmlinux')
self.reset_bin = binary('reset.bin')
self.hypervisor_bin = binary('q.bin')
self.openboot_bin = binary('openboot.bin')
+ self.nvram_bin = binary('nvram1')
+ self.hypervisor_desc_bin = binary('1up-hv.bin')
+ self.partition_desc_bin = binary('1up-md.bin')
return self
diff --git a/configs/example/fs.py b/configs/example/fs.py
index a70a60b97..d479d717e 100644
--- a/configs/example/fs.py
+++ b/configs/example/fs.py
@@ -92,7 +92,13 @@ else:
else:
bm = [SysConfig()]
-test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
+if m5.build_env['TARGET_ISA'] == "alpha":
+ test_sys = makeLinuxAlphaSystem(test_mem_mode, bm[0])
+elif m5.build_env['TARGET_ISA'] == "sparc":
+ test_sys = makeSparcSystem(test_mem_mode, bm[0])
+else:
+ m5.panic("incapable of building non-alpha or non-sparc full system!")
+
np = options.num_cpus
if options.l2cache:
@@ -113,7 +119,10 @@ for i in xrange(np):
test_sys.cpu[i].connectMemPorts(test_sys.membus)
if len(bm) == 2:
- drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
+ if m5.build_env['TARGET_ISA'] == 'alpha':
+ drive_sys = makeLinuxAlphaSystem(drive_mem_mode, bm[1])
+ elif m5.build_env['TARGET_ISA'] == 'sparc':
+ drive_sys = makeSparcSystem(drive_mem_mode, bm[1])
drive_sys.cpu = DriveCPUClass(cpu_id=0)
drive_sys.cpu.connectMemPorts(drive_sys.membus)
root = makeDualRoot(test_sys, drive_sys, options.etherdump)
diff --git a/src/arch/SConscript b/src/arch/SConscript
index bbe3c4e3a..74be5f8d1 100644
--- a/src/arch/SConscript
+++ b/src/arch/SConscript
@@ -53,6 +53,7 @@ isa_switch_hdrs = Split('''
isa_traits.hh
kernel_stats.hh
locked_mem.hh
+ mmaped_ipr.hh
process.hh
regfile.hh
remote_gdb.hh
diff --git a/src/arch/alpha/mmaped_ipr.hh b/src/arch/alpha/mmaped_ipr.hh
new file mode 100644
index 000000000..2b4ba8745
--- /dev/null
+++ b/src/arch/alpha/mmaped_ipr.hh
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_ALPHA_MMAPED_IPR_HH__
+#define __ARCH_ALPHA_MMAPED_IPR_HH__
+
+/**
+ * @file
+ *
+ * ISA-specific helper functions for memory mapped IPR accesses.
+ */
+
+#include "mem/packet.hh"
+
+
+namespace AlphaISA
+{
+inline Tick
+handleIprRead(ThreadContext *xc, Packet *pkt)
+{
+ panic("No handleIprRead implementation in Alpha\n");
+}
+
+
+inline Tick
+handleIprWrite(ThreadContext *xc, Packet *pkt)
+{
+ panic("No handleIprWrite implementation in Alpha\n");
+}
+
+
+} // namespace AlphaISA
+
+#endif
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/isa_parser.py b/src/arch/isa_parser.py
index a96622d4a..59eb18c9c 100755
--- a/src/arch/isa_parser.py
+++ b/src/arch/isa_parser.py
@@ -1307,7 +1307,7 @@ class ControlRegOperand(Operand):
bit_select = 0
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read control register as FP')
- base = 'xc->readMiscReg(%s)' % self.reg_spec
+ base = 'xc->readMiscRegWithEffect(%s)' % self.reg_spec
if self.size == self.dflt_size:
return '%s = %s;\n' % (self.base_name, base)
else:
diff --git a/src/arch/mips/mmaped_ipr.hh b/src/arch/mips/mmaped_ipr.hh
new file mode 100644
index 000000000..fa82a645c
--- /dev/null
+++ b/src/arch/mips/mmaped_ipr.hh
@@ -0,0 +1,62 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_MIPS_MMAPED_IPR_HH__
+#define __ARCH_MIPS_MMAPED_IPR_HH__
+
+/**
+ * @file
+ *
+ * ISA-specific helper functions for memory mapped IPR accesses.
+ */
+
+#include "base/misc.hh"
+#include "mem/packet.hh"
+
+class ThreadContext;
+
+namespace MipsISA
+{
+inline Tick
+handleIprRead(ThreadContext *xc, Packet *pkt)
+{
+ panic("No implementation for handleIprRead in MIPS\n");
+}
+
+inline Tick
+handleIprWrite(ThreadContext *xc, Packet *pkt)
+{
+ panic("No implementation for handleIprWrite in MIPS\n");
+}
+
+
+} // namespace MipsISA
+
+#endif
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
index 281c166c0..c2ef97bfa 100644
--- a/src/arch/sparc/SConscript
+++ b/src/arch/sparc/SConscript
@@ -56,9 +56,11 @@ base_sources = Split('''
full_system_sources = Split('''
arguments.cc
remote_gdb.cc
+ pagetable.cc
stacktrace.cc
system.cc
tlb.cc
+ ua2005.cc
vtophys.cc
''')
diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc
index 00c9e041e..a9a778ff6 100644
--- a/src/arch/sparc/asi.cc
+++ b/src/arch/sparc/asi.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
+ * Ali Saidi
*/
#include "arch/sparc/asi.hh"
@@ -37,8 +38,8 @@ namespace SparcISA
return
(asi == ASI_BLK_AIUP) ||
(asi == ASI_BLK_AIUS) ||
- (asi == ASI_BLK_AIUPL) ||
- (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_BLK_AIUP_L) ||
+ (asi == ASI_BLK_AIUS_L) ||
(asi == ASI_BLK_P) ||
(asi == ASI_BLK_S) ||
(asi == ASI_BLK_PL) ||
@@ -50,10 +51,10 @@ namespace SparcISA
return
(asi == ASI_AIUP) ||
(asi == ASI_BLK_AIUP) ||
- (asi == ASI_AIUPL) ||
- (asi == ASI_BLK_AIUPL) ||
+ (asi == ASI_AIUP_L) ||
+ (asi == ASI_BLK_AIUP_L) ||
(asi == ASI_LDTX_AIUP) ||
- (asi == ASI_LDTX_AIUPL) ||
+ (asi == ASI_LDTX_AIUP_L) ||
(asi == ASI_P) ||
(asi == ASI_PNF) ||
(asi == ASI_PL) ||
@@ -79,10 +80,10 @@ namespace SparcISA
return
(asi == ASI_AIUS) ||
(asi == ASI_BLK_AIUS) ||
- (asi == ASI_AIUSL) ||
- (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_AIUS_L) ||
+ (asi == ASI_BLK_AIUS_L) ||
(asi == ASI_LDTX_AIUS) ||
- (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_LDTX_AIUS_L) ||
(asi == ASI_S) ||
(asi == ASI_SNF) ||
(asi == ASI_SL) ||
@@ -103,7 +104,7 @@ namespace SparcISA
(asi == ASI_BLK_SL);
}
- bool AsiNucleus(ASI asi)
+ bool AsiIsNucleus(ASI asi)
{
return
(asi == ASI_N) ||
@@ -119,14 +120,14 @@ namespace SparcISA
(asi == ASI_AIUS) ||
(asi == ASI_BLK_AIUP) ||
(asi == ASI_BLK_AIUS) ||
- (asi == ASI_AIUPL) ||
- (asi == ASI_AIUSL) ||
- (asi == ASI_BLK_AIUPL) ||
- (asi == ASI_BLK_AIUSL) ||
+ (asi == ASI_AIUP_L) ||
+ (asi == ASI_AIUS_L) ||
+ (asi == ASI_BLK_AIUP_L) ||
+ (asi == ASI_BLK_AIUS_L) ||
(asi == ASI_LDTX_AIUP) ||
(asi == ASI_LDTX_AIUS) ||
- (asi == ASI_LDTX_AIUPL) ||
- (asi == ASI_LDTX_AIUSL);
+ (asi == ASI_LDTX_AIUP_L) ||
+ (asi == ASI_LDTX_AIUS_L);
}
bool AsiIsIO(ASI asi)
@@ -144,22 +145,21 @@ namespace SparcISA
(asi == ASI_REAL_L) ||
(asi == ASI_REAL_IO_L) ||
(asi == ASI_LDTX_REAL) ||
- (asi == ASI_LDTX_REAL_L) ||
- (asi == ASI_MMU_REAL);
+ (asi == ASI_LDTX_REAL_L);
}
bool AsiIsLittle(ASI asi)
{
return
(asi == ASI_NL) ||
- (asi == ASI_AIUPL) ||
- (asi == ASI_AIUSL) ||
+ (asi == ASI_AIUP_L) ||
+ (asi == ASI_AIUS_L) ||
(asi == ASI_REAL_L) ||
(asi == ASI_REAL_IO_L) ||
- (asi == ASI_BLK_AIUPL) ||
- (asi == ASI_BLK_AIUSL) ||
- (asi == ASI_LDTX_AIUPL) ||
- (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_BLK_AIUP_L) ||
+ (asi == ASI_BLK_AIUS_L) ||
+ (asi == ASI_LDTX_AIUP_L) ||
+ (asi == ASI_LDTX_AIUS_L) ||
(asi == ASI_LDTX_REAL_L) ||
(asi == ASI_LDTX_NL) ||
(asi == ASI_PL) ||
@@ -185,18 +185,20 @@ namespace SparcISA
bool AsiIsTwin(ASI asi)
{
return
+ (asi == ASI_QUAD_LDD) ||
(asi == ASI_LDTX_AIUP) ||
(asi == ASI_LDTX_AIUS) ||
(asi == ASI_LDTX_REAL) ||
(asi == ASI_LDTX_N) ||
- (asi == ASI_LDTX_AIUPL) ||
- (asi == ASI_LDTX_AIUSL) ||
+ (asi == ASI_LDTX_AIUP_L) ||
+ (asi == ASI_LDTX_AIUS_L) ||
(asi == ASI_LDTX_REAL_L) ||
(asi == ASI_LDTX_NL) ||
(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)
@@ -248,8 +250,7 @@ namespace SparcISA
bool AsiIsCmt(ASI asi)
{
return
- (asi == ASI_CMT_PER_STRAND) ||
- (asi == ASI_CMT_SHARED);
+ (asi == ASI_CMT_PER_STRAND);
}
bool AsiIsQueue(ASI asi)
@@ -257,23 +258,52 @@ namespace SparcISA
return asi == ASI_QUEUE;
}
- bool AsiIsDtlb(ASI asi)
+ bool AsiIsInterrupt(ASI asi)
{
- return
- (asi == ASI_DTLB_DATA_IN_REG) ||
- (asi == ASI_DTLB_DATA_ACCESS_REG) ||
- (asi == ASI_DTLB_TAG_READ_REG);
+ return asi == ASI_SWVR_INTR_RECEIVE ||
+ asi == ASI_SWVR_UDB_INTR_W ||
+ asi == ASI_SWVR_UDB_INTR_R ;
}
bool AsiIsMmu(ASI asi)
{
- return
- (asi == ASI_MMU_CONTEXTID) ||
- (asi == ASI_IMMU) ||
- (asi == ASI_MMU_REAL) ||
- (asi == ASI_MMU) ||
- (asi == ASI_DMMU) ||
- (asi == ASI_UMMU) ||
- (asi == ASI_DMMU_DEMAP);
+ return asi == ASI_MMU ||
+ asi == ASI_LSU_CONTROL_REG ||
+ (asi >= ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0 &&
+ asi <= ASI_IMMU_CTXT_ZERO_CONFIG) ||
+ (asi >= ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0 &&
+ asi <= ASI_IMMU_CTXT_NONZERO_CONFIG) ||
+ (asi >= ASI_IMMU &&
+ asi <= ASI_IMMU_TSB_PS1_PTR_REG) ||
+ (asi >= ASI_ITLB_DATA_IN_REG &&
+ asi <= ASI_TLB_INVALIDATE_ALL);
}
+
+ bool AsiIsUnPriv(ASI asi)
+ {
+ return asi >= 0x80;
+ }
+
+ bool AsiIsPriv(ASI asi)
+ {
+ return asi <= 0x2f;
+ }
+
+
+ bool AsiIsHPriv(ASI asi)
+ {
+ return asi >= 0x30 && asi <= 0x7f;
+ }
+
+ bool AsiIsReg(ASI asi)
+ {
+ return AsiIsMmu(asi) || AsiIsScratchPad(asi) | AsiIsSparcError(asi);
+ }
+
+ bool AsiIsSparcError(ASI asi)
+ {
+ return asi == ASI_SPARC_ERROR_EN_REG ||
+ asi == ASI_SPARC_ERROR_STATUS_REG;
+ }
+
}
diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh
index 6677b23df..166c3867e 100644
--- a/src/arch/sparc/asi.hh
+++ b/src/arch/sparc/asi.hh
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
+ * Ali Saidi
*/
#ifndef __ARCH_SPARC_ASI_HH__
@@ -34,6 +35,7 @@
namespace SparcISA
{
enum ASI {
+ ASI_IMPLICIT = 0x00,
/* Priveleged ASIs */
//0x00-0x03 implementation dependent
ASI_NUCLEUS = 0x4,
@@ -53,64 +55,110 @@ namespace SparcISA
ASI_BLOCK_AS_IF_USER_PRIMARY = ASI_BLK_AIUP,
ASI_BLK_AIUS = 0x17,
ASI_BLOCK_AS_IF_USER_SECONDARY = ASI_BLK_AIUS,
- ASI_AIUPL = 0x18,
- ASI_AS_IF_USER_PRIMARY_LITTLE = ASI_AIUPL,
- ASI_AIUSL = 0x19,
- ASI_AS_IF_USER_SECONDARY_LITTLE = ASI_AIUSL,
+ ASI_AIUP_L = 0x18,
+ ASI_AS_IF_USER_PRIMARY_LITTLE = ASI_AIUP_L,
+ ASI_AIUS_L = 0x19,
+ ASI_AS_IF_USER_SECONDARY_LITTLE = ASI_AIUS_L,
//0x1A-0x1B implementation dependent
ASI_REAL_L = 0x1C,
ASI_REAL_LITTLE = ASI_REAL_L,
ASI_REAL_IO_L = 0x1D,
ASI_REAL_IO_LITTLE = ASI_REAL_IO_L,
- ASI_BLK_AIUPL = 0x1E,
- ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE = ASI_BLK_AIUPL,
- ASI_BLK_AIUSL = 0x1F,
- ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE = ASI_BLK_AIUSL,
+ ASI_BLK_AIUP_L = 0x1E,
+ ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE = ASI_BLK_AIUP_L,
+ ASI_BLK_AIUS_L = 0x1F,
+ ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE = ASI_BLK_AIUS_L,
ASI_SCRATCHPAD = 0x20,
- ASI_MMU_CONTEXTID = 0x21,
+ ASI_MMU = 0x21,
ASI_LDTX_AIUP = 0x22,
ASI_LD_TWINX_AS_IF_USER_PRIMARY = ASI_LDTX_AIUP,
ASI_LDTX_AIUS = 0x23,
ASI_LD_TWINX_AS_IF_USER_SECONDARY = ASI_LDTX_AIUS,
- //0x24 implementation dependent
+ ASI_QUAD_LDD = 0x24,
ASI_QUEUE = 0x25,
- ASI_LDTX_REAL = 0x26,
- ASI_LD_TWINX_REAL = ASI_LDTX_REAL,
+ ASI_QUAD_LDD_REAL = 0x26,
+ ASI_LDTX_REAL = ASI_QUAD_LDD_REAL,
ASI_LDTX_N = 0x27,
ASI_LD_TWINX_NUCLEUS = ASI_LDTX_N,
+ ASI_ST_BLKINIT_NUCLEUS = ASI_LDTX_N,
+ ASI_STBI_N = ASI_LDTX_N,
//0x28-0x29 implementation dependent
- ASI_LDTX_AIUPL = 0x2A,
- ASI_LD_TWINX_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUPL,
- ASI_LDTX_AIUSL = 0x2B,
- ASI_LD_TWINX_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUSL,
- //0x2C-0x2D implementation dependent
+ ASI_LDTX_AIUP_L = 0x2A,
+ ASI_TWINX_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUP_L,
+ ASI_ST_BLKINIT_AS_IF_USER_PRIMARY_LITTLE = ASI_LDTX_AIUP_L,
+ ASI_STBI_AIUP_L = ASI_LDTX_AIUP_L,
+ ASI_LDTX_AIUS_L = 0x2B,
+ ASI_LD_TWINX_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUS_L,
+ ASI_ST_BLKINIT_AS_IF_USER_SECONDARY_LITTLE = ASI_LDTX_AIUS_L,
+ ASI_STBI_AIUS_L = ASI_LDTX_AIUS_L,
+ ASI_LTX_L = 0x2C,
+ ASI_TWINX_LITTLE = ASI_LTX_L,
+ //0x2D implementation dependent
ASI_LDTX_REAL_L = 0x2E,
ASI_LD_TWINX_REAL_LITTLE = ASI_LDTX_REAL_L,
ASI_LDTX_NL = 0x2F,
ASI_LD_TWINX_NUCLEUS_LITTLE = ASI_LDTX_NL,
- //0x30-0x40 implementation dependent
- ASI_CMT_SHARED = 0x41,
- //0x42-0x4F implementation dependent
+ //0x20 implementation dependent
+ ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0 = 0x31,
+ ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1 = 0x32,
+ ASI_DMMU_CTXT_ZERO_CONFIG = 0x33,
+ //0x34 implementation dependent
+ ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0 = 0x35,
+ ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1 = 0x36,
+ ASI_IMMU_CTXT_ZERO_CONFIG = 0x37,
+ //0x38 implementation dependent
+ ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0 = 0x39,
+ ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1 = 0x3A,
+ ASI_DMMU_CTXT_NONZERO_CONFIG = 0x3B,
+ //0x3C implementation dependent
+ ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0 = 0x3D,
+ ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1 = 0x3E,
+ ASI_IMMU_CTXT_NONZERO_CONFIG = 0x3F,
+ ASI_STREAM_MA = 0x40,
+ //0x41 implementation dependent
+ ASI_SPARC_BIST_CONTROL = 0x42,
+ ASI_INST_MASK_REG = 0x42,
+ ASI_LSU_DIAG_REG = 0x42,
+ //0x43 implementation dependent
+ ASI_STM_CTL_REG = 0x44,
+ ASI_LSU_CONTROL_REG = 0x45,
+ ASI_DCACHE_DATA = 0x46,
+ ASI_DCACHE_TAG = 0x47,
+ ASI_INTR_DISPATCH_STATUS = 0x48,
+ ASI_INTR_RECEIVE = 0x49,
+ ASI_UPA_CONFIG_REGISTER = 0x4A,
+ ASI_SPARC_ERROR_EN_REG = 0x4B,
+ ASI_SPARC_ERROR_STATUS_REG = 0x4C,
+ ASI_SPARC_ERROR_ADDRESS_REG = 0x4D,
+ ASI_ECACHE_TAG_DATA = 0x4E,
ASI_HYP_SCRATCHPAD = 0x4F,
ASI_IMMU = 0x50,
- ASI_MMU_REAL = 0x52,
+ ASI_IMMU_TSB_PS0_PTR_REG = 0x51,
+ ASI_IMMU_TSB_PS1_PTR_REG = 0x52,
//0x53 implementation dependent
- ASI_MMU = 0x54,
+ ASI_ITLB_DATA_IN_REG = 0x54,
ASI_ITLB_DATA_ACCESS_REG = 0x55,
ASI_ITLB_TAG_READ_REG = 0x56,
ASI_IMMU_DEMAP = 0x57,
ASI_DMMU = 0x58,
- ASI_UMMU = 0x58,
- //0x59-0x5B reserved
+ ASI_DMMU_TSB_PS0_PTR_REG = 0x59,
+ ASI_DMMU_TSB_PS1_PTR_REG = 0x5A,
+ ASI_DMMU_TSB_DIRECT_PTR_REG = 0x5B,
ASI_DTLB_DATA_IN_REG = 0x5C,
ASI_DTLB_DATA_ACCESS_REG = 0x5D,
ASI_DTLB_TAG_READ_REG = 0x5E,
ASI_DMMU_DEMAP = 0x5F,
- //0x60-62 implementation dependent
+ ASI_TLB_INVALIDATE_ALL = 0x60,
+ //0x61-0x62 implementation dependent
ASI_CMT_PER_STRAND = 0x63,
- //0x64-0x67 implementation dependent
- //0x68-0x7F reserved
-
+ //0x64-0x65 implementation dependent
+ ASI_ICACHE_INSTR = 0x66,
+ ASI_ICACHE_TAG = 0x67,
+ //0x68-0x71 implementation dependent
+ ASI_SWVR_INTR_RECEIVE = 0x72,
+ ASI_SWVR_UDB_INTR_W = 0x73,
+ ASI_SWVR_UDB_INTR_R = 0x74,
+ //0x74-0x7F reserved
/* Unpriveleged ASIs */
ASI_P = 0x80,
ASI_PRIMARY = ASI_P,
@@ -216,7 +264,12 @@ namespace SparcISA
bool AsiIsQueue(ASI);
bool AsiIsDtlb(ASI);
bool AsiIsMmu(ASI);
-
+ bool AsiIsUnPriv(ASI);
+ bool AsiIsPriv(ASI);
+ bool AsiIsHPriv(ASI);
+ bool AsiIsReg(ASI);
+ bool AsiIsInterrupt(ASI);
+ bool AsiIsSparcError(ASI);
};
#endif // __ARCH_SPARC_ASI_HH__
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index 4cf411d3b..64cfc832a 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -284,6 +284,11 @@ void enterREDState(ThreadContext *tc)
//HPSTATE.hpriv = 1
HPSTATE |= (1 << 2);
tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE);
+ //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+ //Legion sets it to 1.
+ MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
+ PSTATE |= (1 << 2);
+ tc->setMiscRegWithEffect(MISCREG_PSTATE, PSTATE);
}
/**
@@ -340,10 +345,12 @@ void doREDFault(ThreadContext *tc, TrapType tt)
PSTATE |= (1 << 4);
//set PSTATE.am to 0
PSTATE &= ~(1 << 3);
- //set PSTATE.priv to 0
- PSTATE &= ~(1 << 2);
+/* //set PSTATE.priv to 0
+ PSTATE &= ~(1 << 2);*/
//set PSTATE.ie to 0
- PSTATE &= ~(1 << 1);
+ //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+ //Legion sets it to 1.
+ PSTATE |= (1 << 2);
//set PSTATE.cle to 0
PSTATE &= ~(1 << 9);
//PSTATE.tle is unchanged
@@ -451,7 +458,9 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
else
{
//PSTATE.priv = 0
- PSTATE &= ~(1 << 2);
+ //PSTATE.priv is set to 1 here. The manual says it should be 0, but
+ //Legion sets it to 1.
+ PSTATE |= (1 << 2);
//PSTATE.cle = 0
PSTATE &= ~(1 << 9);
}
@@ -519,7 +528,7 @@ void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscRe
void SparcFaultBase::invoke(ThreadContext * tc)
{
- panic("Invoking a second fault!\n");
+ //panic("Invoking a second fault!\n");
FaultBase::invoke(tc);
countStat()++;
@@ -533,40 +542,35 @@ void SparcFaultBase::invoke(ThreadContext * tc)
Addr PC, NPC;
PrivilegeLevel current;
- if(!(PSTATE & (1 << 2)))
- current = User;
- else if(!(HPSTATE & (1 << 2)))
+ if(HPSTATE & (1 << 2))
+ current = Hyperprivileged;
+ else if(PSTATE & (1 << 2))
current = Privileged;
else
- current = Hyperprivileged;
+ current = User;
PrivilegeLevel level = getNextLevel(current);
- if(HPSTATE & (1 << 5) || TL == MaxTL - 1)
- {
+ if(HPSTATE & (1 << 5) || TL == MaxTL - 1) {
getREDVector(5, PC, NPC);
- enterREDState(tc);
doREDFault(tc, TT);
- }
- else if(TL == MaxTL)
- {
+ //This changes the hpstate and pstate, so we need to make sure we
+ //save the old version on the trap stack in doREDFault.
+ enterREDState(tc);
+ } else if(TL == MaxTL) {
+ panic("Should go to error state here.. crap\n");
//Do error_state somehow?
//Probably inject a WDR fault using the interrupt mechanism.
//What should the PC and NPC be set to?
- }
- else if(TL > MaxPTL && level == Privileged)
- {
+ } else if(TL > MaxPTL && level == Privileged) {
//guest_watchdog fault
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, 2);
- }
- else if(level == Hyperprivileged)
- {
+ } else if(level == Hyperprivileged ||
+ level == Privileged && trapType() >= 384) {
doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, trapType());
- }
- else
- {
+ } else {
doNormalFault(tc, trapType(), false);
getPrivVector(tc, PC, NPC, trapType(), TL+1);
}
@@ -578,9 +582,6 @@ void SparcFaultBase::invoke(ThreadContext * tc)
void PowerOnReset::invoke(ThreadContext * tc)
{
- //First, enter RED state.
- enterREDState(tc);
-
//For SPARC, when a system is first started, there is a power
//on reset Trap which sets the processor into the following state.
//Bits that aren't set aren't defined on startup.
@@ -589,15 +590,28 @@ void PowerOnReset::invoke(ThreadContext * tc)
tc->setMiscReg(MISCREG_TT, trapType());
tc->setMiscRegWithEffect(MISCREG_GL, MaxGL);
- //Turn on pef, set everything else to 0
- tc->setMiscReg(MISCREG_PSTATE, 1 << 4);
+ //Turn on pef and priv, set everything else to 0
+ tc->setMiscReg(MISCREG_PSTATE, (1 << 4) | (1 << 2));
//Turn on red and hpriv, set everything else to 0
- tc->setMiscReg(MISCREG_HPSTATE, (1 << 5) | (1 << 2));
+ MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ //HPSTATE.red = 1
+ HPSTATE |= (1 << 5);
+ //HPSTATE.hpriv = 1
+ HPSTATE |= (1 << 2);
+ //HPSTATE.ibe = 0
+ HPSTATE &= ~(1 << 10);
+ //HPSTATE.tlz = 0
+ HPSTATE &= ~(1 << 0);
+ tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
//The tick register is unreadable by nonprivileged software
tc->setMiscReg(MISCREG_TICK, 1ULL << 63);
+ //Enter RED state. We do this last so that the actual state preserved in
+ //the trap stack is the state from before this fault.
+ enterREDState(tc);
+
Addr PC, NPC;
getREDVector(trapType(), PC, NPC);
tc->setPC(PC);
diff --git a/src/arch/sparc/floatregfile.hh b/src/arch/sparc/floatregfile.hh
index 9d760c9ff..72803a5e0 100644
--- a/src/arch/sparc/floatregfile.hh
+++ b/src/arch/sparc/floatregfile.hh
@@ -38,10 +38,15 @@
#include <string>
+class Checkpoint;
+
namespace SparcISA
{
std::string getFloatRegName(RegIndex);
+ const int NumFloatArchRegs = 64;
+ const int NumFloatRegs = 64;
+
typedef float float32_t;
typedef double float64_t;
//FIXME long double refers to a 10 byte float, rather than a
diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh
index 70838d1ce..452164e46 100644
--- a/src/arch/sparc/interrupts.hh
+++ b/src/arch/sparc/interrupts.hh
@@ -32,51 +32,62 @@
#define __ARCH_SPARC_INTERRUPT_HH__
#include "arch/sparc/faults.hh"
+#include "cpu/thread_context.hh"
+
namespace SparcISA
{
class Interrupts
{
protected:
- Fault interrupts[NumInterruptLevels];
- bool requested[NumInterruptLevels];
+
public:
Interrupts()
{
- for(int x = 0; x < NumInterruptLevels; x++)
- {
- interrupts[x] = new InterruptLevelN(x);
- requested[x] = false;
- }
+
}
void post(int int_num, int index)
{
- if(int_num < 0 || int_num >= NumInterruptLevels)
- panic("int_num out of bounds\n");
- requested[int_num] = true;
}
void clear(int int_num, int index)
{
- requested[int_num] = false;
+
}
void clear_all()
{
- for(int x = 0; x < NumInterruptLevels; x++)
- requested[x] = false;
+
}
bool check_interrupts(ThreadContext * tc) const
{
- return true;
+ // so far only handle softint interrupts
+ int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
+ if (int_level)
+ return true;
+ else
+ return false;
}
Fault getInterrupt(ThreadContext * tc)
{
- return NoFault;
+ // conditioning the softint interrups
+ if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) {
+ // if running in privileged mode, then pend the interrupt
+ return NoFault;
+ } else {
+ int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
+ if ((int_level <= tc->readMiscReg(MISCREG_PIL)) ||
+ !(tc->readMiscReg(MISCREG_PSTATE) & ie)) {
+ // if PIL or no interrupt enabled, then pend the interrupt
+ return NoFault;
+ } else {
+ return new InterruptLevelN(int_level);
+ }
+ }
}
void updateIntrInfo(ThreadContext * tc)
diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc
index 358368e5f..0a8ac055f 100644
--- a/src/arch/sparc/intregfile.cc
+++ b/src/arch/sparc/intregfile.cc
@@ -31,6 +31,7 @@
#include "arch/sparc/intregfile.hh"
#include "base/trace.hh"
+#include "base/misc.hh"
#include "sim/serialize.hh"
#include <string.h>
@@ -42,7 +43,7 @@ class Checkpoint;
string SparcISA::getIntRegName(RegIndex index)
{
- static std::string intRegName[NumIntRegs] =
+ static std::string intRegName[NumIntArchRegs] =
{"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
"o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
@@ -78,30 +79,30 @@ IntRegFile::IntRegFile()
IntReg IntRegFile::readReg(int intReg)
{
IntReg val;
- if(intReg < NumRegularIntRegs)
+ if(intReg < NumIntArchRegs)
val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
- else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
+ else if((intReg -= NumIntArchRegs) < NumMicroIntRegs)
val = microRegs[intReg];
else
- panic("Tried to read non-existant integer register %d, %d\n", NumRegularIntRegs + NumMicroIntRegs + intReg, intReg);
+ panic("Tried to read non-existant integer register %d, %d\n",
+ NumIntArchRegs + NumMicroIntRegs + intReg, intReg);
DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
return val;
}
-Fault IntRegFile::setReg(int intReg, const IntReg &val)
+void IntRegFile::setReg(int intReg, const IntReg &val)
{
if(intReg)
{
DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
- if(intReg < NumRegularIntRegs)
+ if(intReg < NumIntArchRegs)
regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
- else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
+ else if((intReg -= NumIntArchRegs) < NumMicroIntRegs)
microRegs[intReg] = val;
else
panic("Tried to set non-existant integer register\n");
}
- return NoFault;
}
//This doesn't effect the actual CWP register.
diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh
index 223e3b34c..d66d0fcb7 100644
--- a/src/arch/sparc/intregfile.hh
+++ b/src/arch/sparc/intregfile.hh
@@ -32,12 +32,13 @@
#ifndef __ARCH_SPARC_INTREGFILE_HH__
#define __ARCH_SPARC_INTREGFILE_HH__
-#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
#include <string>
+class Checkpoint;
+
namespace SparcISA
{
class RegFile;
@@ -45,6 +46,9 @@ namespace SparcISA
//This function translates integer register file indices into names
std::string getIntRegName(RegIndex);
+ const int NumIntArchRegs = 32;
+ const int NumIntRegs = MaxGL * 8 + NWindows * 16 + NumMicroIntRegs;
+
class IntRegFile
{
private:
@@ -63,7 +67,7 @@ namespace SparcISA
(unsigned int)(-1) :
(1 << FrameOffsetBits) - 1;
- IntReg regGlobals[MaxGL][RegsPerFrame];
+ IntReg regGlobals[MaxGL+1][RegsPerFrame];
IntReg regSegments[2 * NWindows][RegsPerFrame];
IntReg microRegs[NumMicroIntRegs];
@@ -85,7 +89,7 @@ namespace SparcISA
IntReg readReg(int intReg);
- Fault setReg(int intReg, const IntReg &val);
+ void setReg(int intReg, const IntReg &val);
void serialize(std::ostream &os);
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index aa24c75be..4a806bfd0 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -205,7 +205,7 @@ output decoder {{
else if(reg < MaxMicroReg)
ccprintf(os, "%%u%d", reg - MaxInput);
else {
- ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
+ ccprintf(os, "%%f%d", reg - MaxMicroReg);
}
}
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index 2c8e59a1d..7a48042c2 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -307,7 +307,7 @@ decode OP default Unknown::unknown()
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
@@ -316,7 +316,7 @@ decode OP default Unknown::unknown()
int64_t resTemp, val2 = Rs2_or_imm13;
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
- {{(Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31}},
+ {{(Rs1<31:0> + val2<31:0>)<32:0>}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
@@ -327,7 +327,7 @@ decode OP default Unknown::unknown()
int32_t overflow = Rs1<1:0> || val2<1:0> ||
(Rs1<31:> == val2<31:> && val2<31:> != Rd<31:>);
if(overflow) fault = new TagOverflow;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != Rd<63:>}}
@@ -337,7 +337,7 @@ decode OP default Unknown::unknown()
Rd = resTemp = Rs1 + val2;
int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
if(overflow) fault = new TagOverflow;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
+ {{((Rs1<31:0> + val2<31:0>)<32:0>)}},
{{overflow}},
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
@@ -347,13 +347,12 @@ decode OP default Unknown::unknown()
int32_t multiplier = Rs1<31:0>;
int32_t savedLSB = Rs1<0:>;
multiplier = multiplier<31:1> |
- ((Ccr<3:3>
- ^ Ccr<1:1>) << 32);
+ ((Ccr<3:3> ^ Ccr<1:1>) << 32);
if(!Y<0:>)
multiplicand = 0;
Rd = resTemp = multiplicand + multiplier;
Y = Y<31:1> | (savedLSB << 31);}},
- {{((multiplicand & 0xFFFFFFFF + multiplier & 0xFFFFFFFF) >> 31)}},
+ {{((multiplicand<31:0> + multiplier<31:0>)<32:0>)}},
{{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}},
{{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}},
{{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}}
@@ -527,7 +526,7 @@ decode OP default Unknown::unknown()
0x00: NoPriv::wry({{Y = Rs1 ^ Rs2_or_imm13;}});
//0x01 should cause an illegal instruction exception
0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}});
- 0x03: NoPriv::wrasi({{Ccr = Rs1 ^ Rs2_or_imm13;}});
+ 0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}});
//0x04-0x05 should cause an illegal instruction exception
0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}});
//0x07-0x0E should cause an illegal instruction exception
@@ -1005,6 +1004,7 @@ decode OP default Unknown::unknown()
Asi = Tstate<31:24>;
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
+ Hpstate = Htstate;
NPC = Tnpc;
NNPC = Tnpc + 4;
Tl = Tl - 1;
@@ -1017,6 +1017,7 @@ decode OP default Unknown::unknown()
Asi = Tstate<31:24>;
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
+ Hpstate = Htstate;
NPC = Tpc;
NNPC = Tnpc;
Tl = Tl - 1;
@@ -1055,36 +1056,36 @@ decode OP default Unknown::unknown()
{{uReg0 = Rd.uw;
Rd.uw = Mem.uw;}},
{{Mem.uw = uReg0;}});
- format Load {
- 0x10: lduwa({{Rd = Mem.uw;}});
- 0x11: lduba({{Rd = Mem.ub;}});
- 0x12: lduha({{Rd = Mem.uhw;}});
+ format LoadAlt {
+ 0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
+ 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
+ 0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
0x13: ldda({{
uint64_t val = Mem.udw;
RdLow = val<31:0>;
RdHigh = val<63:32>;
- }});
+ }}, {{EXT_ASI}});
}
- format Store {
- 0x14: stwa({{Mem.uw = Rd;}});
- 0x15: stba({{Mem.ub = Rd;}});
- 0x16: stha({{Mem.uhw = Rd;}});
- 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}});
+ format StoreAlt {
+ 0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
+ 0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
+ 0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}});
+ 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
}
- format Load {
- 0x18: ldswa({{Rd = (int32_t)Mem.sw;}});
- 0x19: ldsba({{Rd = (int8_t)Mem.sb;}});
- 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}});
- 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}});
+ format LoadAlt {
+ 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
+ 0x19: ldsba({{Rd = (int8_t)Mem.sb;}}, {{EXT_ASI}});
+ 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}});
+ 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
}
- 0x1D: LoadStore::ldstuba(
+ 0x1D: LoadStoreAlt::ldstuba(
{{Rd = Mem.ub;}},
- {{Mem.ub = 0xFF}});
- 0x1E: Store::stxa({{Mem.udw = Rd}});
- 0x1F: LoadStore::swapa(
+ {{Mem.ub = 0xFF}}, {{EXT_ASI}});
+ 0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
+ 0x1F: LoadStoreAlt::swapa(
{{uReg0 = Rd.uw;
Rd.uw = Mem.uw;}},
- {{Mem.uw = uReg0;}});
+ {{Mem.uw = uReg0;}}, {{EXT_ASI}});
format Trap {
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
0x21: decode X {
@@ -1101,7 +1102,7 @@ decode OP default Unknown::unknown()
0x26: stqf({{fault = new FpDisabled;}});
0x27: Store::stdf({{Mem.udw = Frd.udw;}});
0x2D: Nop::prefetch({{ }});
- 0x30: Load::ldfa({{Frd.uw = Mem.uw;}});
+ 0x30: LoadAlt::ldfa({{Frd.uw = Mem.uw;}}, {{EXT_ASI}});
0x32: ldqfa({{fault = new FpDisabled;}});
format LoadAlt {
0x33: decode EXT_ASI {
@@ -1153,7 +1154,7 @@ decode OP default Unknown::unknown()
//ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
0x1F: FailUnimpl::ldblockf_aiusl();
//ASI_BLOCK_PRIMARY
- 0xF0: ldblockf_p({{Frd_N.udw = Mem.udw;}});
+ 0xF0: ldblockf_p({{Frd_N.udw = Mem.udw;}}, {{EXT_ASI}});
//ASI_BLOCK_SECONDARY
0xF1: FailUnimpl::ldblockf_s();
//ASI_BLOCK_PRIMARY_LITTLE
@@ -1236,7 +1237,7 @@ decode OP default Unknown::unknown()
//ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE
0x1F: FailUnimpl::stblockf_aiusl();
//ASI_BLOCK_PRIMARY
- 0xF0: stblockf_p({{Mem.udw = Frd_N.udw;}});
+ 0xF0: stblockf_p({{Mem.udw = Frd_N.udw;}}, {{EXT_ASI}});
//ASI_BLOCK_SECONDARY
0xF1: FailUnimpl::stblockf_s();
//ASI_BLOCK_PRIMARY_LITTLE
@@ -1273,7 +1274,7 @@ decode OP default Unknown::unknown()
Mem.uw = Rd.uw;
else
storeCond = false;
- Rd.uw = uReg0;}});
+ Rd.uw = uReg0;}}, {{EXT_ASI}});
0x3D: Nop::prefetcha({{ }});
0x3E: Cas::casxa(
{{uReg0 = Mem.udw;}},
@@ -1281,7 +1282,7 @@ decode OP default Unknown::unknown()
Mem.udw = Rd;
else
storeCond = false;
- Rd = uReg0;}});
+ Rd = uReg0;}}, {{EXT_ASI}});
}
}
}
diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa
index cb6c2f161..55e9fba45 100644
--- a/src/arch/sparc/isa/formats/mem/basicmem.isa
+++ b/src/arch/sparc/isa/formats/mem/basicmem.isa
@@ -52,7 +52,7 @@ def template MemDeclare {{
}};
let {{
- def doMemFormat(code, execute, faultCode, name, Name, opt_flags):
+ def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags):
addrCalcReg = 'EA = Rs1 + Rs2;'
addrCalcImm = 'EA = Rs1 + imm;'
iop = InstObjParams(name, Name, 'Mem', code,
@@ -62,25 +62,26 @@ let {{
header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
decode_block = ROrImmDecode.subst(iop)
- exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, execute,
- faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags)
+ exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm,
+ execute, faultCode, name, name + "Imm", Name, Name + "Imm",
+ asi, opt_flags)
return (header_output, decoder_output, exec_output, decode_block)
}};
-def format LoadAlt(code, *opt_flags) {{
+def format LoadAlt(code, asi, *opt_flags) {{
(header_output,
decoder_output,
exec_output,
decode_block) = doMemFormat(code, LoadExecute,
- AlternateAsiPrivFaultCheck, name, Name, opt_flags)
+ AlternateASIPrivFaultCheck, name, Name, asi, opt_flags)
}};
-def format StoreAlt(code, *opt_flags) {{
+def format StoreAlt(code, asi, *opt_flags) {{
(header_output,
decoder_output,
exec_output,
decode_block) = doMemFormat(code, StoreExecute,
- AlternateAsiPrivFaultCheck, name, Name, opt_flags)
+ AlternateASIPrivFaultCheck, name, Name, asi, opt_flags)
}};
def format Load(code, *opt_flags) {{
@@ -88,7 +89,7 @@ def format Load(code, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doMemFormat(code,
- LoadExecute, '', name, Name, opt_flags)
+ LoadExecute, '', name, Name, 0, opt_flags)
}};
def format Store(code, *opt_flags) {{
@@ -96,5 +97,5 @@ def format Store(code, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doMemFormat(code,
- StoreExecute, '', name, Name, opt_flags)
+ StoreExecute, '', name, Name, 0, opt_flags)
}};
diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa
index 8b4aca473..7a1a58d13 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -273,7 +273,7 @@ def template BlockMemMicroConstructor {{
let {{
- def doBlockMemFormat(code, faultCode, execute, name, Name, opt_flags):
+ def doBlockMemFormat(code, faultCode, execute, name, Name, asi, opt_flags):
# XXX Need to take care of pstate.hpriv as well. The lower ASIs
# are split into ones that are available in priv and hpriv, and
# those that are only available in hpriv
@@ -309,12 +309,12 @@ let {{
makeMicroName(name + "Imm", microPc),
makeMicroName(Name, microPc),
makeMicroName(Name + "Imm", microPc),
- opt_flags);
+ asi, opt_flags);
faultCode = ''
return (header_output, decoder_output, exec_output, decode_block)
}};
-def format BlockLoad(code, *opt_flags) {{
+def format BlockLoad(code, asi, *opt_flags) {{
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.
@@ -323,10 +323,10 @@ def format BlockLoad(code, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doBlockMemFormat(code, faultCode,
- LoadExecute, name, Name, opt_flags)
+ LoadExecute, name, Name, asi, opt_flags)
}};
-def format BlockStore(code, *opt_flags) {{
+def format BlockStore(code, asi, *opt_flags) {{
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.
@@ -335,5 +335,5 @@ def format BlockStore(code, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doBlockMemFormat(code, faultCode,
- StoreExecute, name, Name, opt_flags)
+ StoreExecute, name, Name, asi, opt_flags)
}};
diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa
index b9f7fde2d..3e9fd7a7d 100644
--- a/src/arch/sparc/isa/formats/mem/util.isa
+++ b/src/arch/sparc/isa/formats/mem/util.isa
@@ -76,19 +76,22 @@ output decoder {{
{
std::stringstream response;
bool load = flags[IsLoad];
- bool save = flags[IsStore];
+ bool store = flags[IsStore];
printMnemonic(response, mnemonic);
- if(save)
+ if(store)
{
printReg(response, _srcRegIdx[0]);
ccprintf(response, ", ");
}
- ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[!save ? 0 : 1]);
- ccprintf(response, " + ");
- printReg(response, _srcRegIdx[!save ? 1 : 2]);
- ccprintf(response, " ]");
+ ccprintf(response, "[");
+ if(_srcRegIdx[!store ? 0 : 1] != 0)
+ {
+ printSrcReg(response, !store ? 0 : 1);
+ ccprintf(response, " + ");
+ }
+ printSrcReg(response, !store ? 1 : 2);
+ ccprintf(response, "]");
if(load)
{
ccprintf(response, ", ");
@@ -111,12 +114,16 @@ output decoder {{
printReg(response, _srcRegIdx[0]);
ccprintf(response, ", ");
}
- ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, "[");
+ if(_srcRegIdx[!save ? 0 : 1] != 0)
+ {
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, " + ");
+ }
if(imm >= 0)
- ccprintf(response, " + 0x%x ]", imm);
+ ccprintf(response, "0x%x]", imm);
else
- ccprintf(response, " + -0x%x ]", -imm);
+ ccprintf(response, "-0x%x]", -imm);
if(load)
{
ccprintf(response, ", ");
@@ -141,7 +148,7 @@ def template LoadExecute {{
%(fault_check)s;
if(fault == NoFault)
{
- fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+ fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
}
if(fault == NoFault)
{
@@ -149,8 +156,8 @@ def template LoadExecute {{
}
if(fault == NoFault)
{
- //Write the resulting state to the execution context
- %(op_wb)s;
+ //Write the resulting state to the execution context
+ %(op_wb)s;
}
return fault;
@@ -168,7 +175,7 @@ def template LoadExecute {{
%(fault_check)s;
if(fault == NoFault)
{
- fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
+ fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
}
return fault;
}
@@ -195,7 +202,6 @@ def template StoreExecute {{
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
- uint64_t write_result = 0;
//This is to support the conditional store in cas instructions.
//It should be optomized out in all the others
bool storeCond = true;
@@ -211,12 +217,13 @@ def template StoreExecute {{
}
if(storeCond && fault == NoFault)
{
- fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ fault = xc->write((uint%(mem_acc_size)s_t)Mem,
+ EA, %(asi_val)s, 0);
}
if(fault == NoFault)
{
- //Write the resulting state to the execution context
- %(op_wb)s;
+ //Write the resulting state to the execution context
+ %(op_wb)s;
}
return fault;
@@ -226,7 +233,6 @@ def template StoreExecute {{
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
- uint64_t write_result = 0;
bool storeCond = true;
Addr EA;
%(op_decl)s;
@@ -240,11 +246,12 @@ def template StoreExecute {{
}
if(storeCond && fault == NoFault)
{
- fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
+ fault = xc->write((uint%(mem_acc_size)s_t)Mem,
+ EA, %(asi_val)s, 0);
}
if(fault == NoFault)
{
- //Write the resulting state to the execution context
+ //Write the resulting state to the execution context
%(op_wb)s;
}
return fault;
@@ -281,8 +288,9 @@ let {{
# are split into ones that are available in priv and hpriv, and
# those that are only available in hpriv
AlternateASIPrivFaultCheck = '''
- if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
- fault = new PrivilegedAction;
+ if(!bits(Pstate,2,2) && !bits(Hpstate,2,2) && !AsiIsUnPriv((ASI)EXT_ASI) ||
+ !bits(Hpstate,2,2) && AsiIsHPriv((ASI)EXT_ASI))
+ fault = new PrivilegedAction;
else if(AsiIsAsIfUser((ASI)EXT_ASI) && !bits(Pstate,2,2))
fault = new PrivilegedAction;
'''
@@ -293,7 +301,7 @@ let {{
//instruction at a certain micropc
let {{
def makeMicroName(name, microPc):
- return name + "::" + name + "_" + str(microPc)
+ return name + "::" + name + "_" + str(microPc)
}};
//This function properly generates the execute functions for one of the
@@ -302,13 +310,14 @@ let {{
//and in the other they're distributed across two. Also note that for
//execute functions, the name of the base class doesn't matter.
let {{
- def doSplitExecute(code, eaCode, execute,
- faultCode, name, Name, opt_flags):
- codeIop = InstObjParams(name, Name, '', code, opt_flags)
- eaIop = InstObjParams(name, Name, '', eaCode,
- opt_flags, {"fault_check": faultCode})
- iop = InstObjParams(name, Name, '', code, opt_flags,
- {"fault_check": faultCode, "ea_code" : eaCode})
+ def doSplitExecute(code, execute, name, Name, asi, opt_flags, microParam):
+ microParam["asi_val"] = asi;
+ codeParam = microParam.copy()
+ codeParam["ea_code"] = ''
+ codeIop = InstObjParams(name, Name, '', code, opt_flags, codeParam)
+ eaIop = InstObjParams(name, Name, '', microParam["ea_code"],
+ opt_flags, microParam)
+ iop = InstObjParams(name, Name, '', code, opt_flags, microParam)
(iop.ea_decl,
iop.ea_rd,
iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
@@ -319,12 +328,13 @@ let {{
def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
- faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
+ faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
executeCode = ''
for (eaCode, name, Name) in (
(eaRegCode, nameReg, NameReg),
(eaImmCode, nameImm, NameImm)):
- executeCode += doSplitExecute(code, eaCode,
- execute, faultCode, name, Name, opt_flags)
+ microParams = {"ea_code" : eaCode, "fault_check": faultCode}
+ executeCode += doSplitExecute(code, execute, name, Name,
+ asi, opt_flags, microParams)
return executeCode
}};
diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
index 94a68aebe..3d47ca02f 100644
--- a/src/arch/sparc/isa/formats/priv.isa
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -153,8 +153,13 @@ output decoder {{
printMnemonic(response, mnemonic);
ccprintf(response, " ");
- printSrcReg(response, 0);
- ccprintf(response, ", ");
+ //If the first reg is %g0, don't print it.
+ //This improves readability
+ if(_srcRegIdx[0] != 0)
+ {
+ printSrcReg(response, 0);
+ ccprintf(response, ", ");
+ }
printSrcReg(response, 1);
ccprintf(response, ", %%%s", regName);
@@ -169,8 +174,14 @@ output decoder {{
printMnemonic(response, mnemonic);
ccprintf(response, " ");
- printSrcReg(response, 0);
- ccprintf(response, ", 0x%x, %%%s", imm, regName);
+ //If the first reg is %g0, don't print it.
+ //This improves readability
+ if(_srcRegIdx[0] != 0)
+ {
+ printSrcReg(response, 0);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "0x%x, %%%s", imm, regName);
return response.str();
}
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 2d200f568..80ed7362c 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -61,7 +61,7 @@ def operands {{
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
- 'uReg0': ('IntReg', 'udw', 'NumRegularIntRegs+0', 'IsInteger', 6),
+ 'uReg0': ('IntReg', 'udw', 'NumIntArchRegs', 'IsInteger', 6),
'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
# Each Frd_N refers to the Nth double precision register from Frd.
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 1433ba3f8..3f0b9cad5 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -26,34 +26,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
+ * Ali Saidi
*/
#ifndef __ARCH_SPARC_ISA_TRAITS_HH__
#define __ARCH_SPARC_ISA_TRAITS_HH__
#include "arch/sparc/types.hh"
-#include "base/misc.hh"
+#include "arch/sparc/sparc_traits.hh"
#include "config/full_system.hh"
#include "sim/host.hh"
-class ThreadContext;
-class FastCPU;
-//class FullCPU;
-class Checkpoint;
-
-class StaticInst;
class StaticInstPtr;
namespace BigEndianGuest {}
-#if FULL_SYSTEM
-#include "arch/sparc/isa_fullsys_traits.hh"
-#endif
-
namespace SparcISA
{
class RegFile;
+ const int MachineBytes = 8;
+
//This makes sure the big endian versions of certain functions are used.
using namespace BigEndianGuest;
@@ -63,32 +56,12 @@ namespace SparcISA
// SPARC NOP (sethi %(hi(0), g0)
const MachInst NoopMachInst = 0x01000000;
- const int NumRegularIntRegs = 32;
- const int NumMicroIntRegs = 1;
- const int NumIntRegs =
- NumRegularIntRegs +
- NumMicroIntRegs;
- const int NumFloatRegs = 64;
- const int NumMiscRegs = 40;
-
// These enumerate all the registers for dependence tracking.
enum DependenceTags {
- // 0..31 are the integer regs 0..31
- // 32..95 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
- FP_Base_DepTag = NumIntRegs,
- Ctrl_Base_DepTag = NumIntRegs + NumMicroIntRegs + NumFloatRegs,
+ FP_Base_DepTag = 33,
+ Ctrl_Base_DepTag = 97,
};
-
- // MAXTL - maximum trap level
- const int MaxPTL = 2;
- const int MaxTL = 6;
- const int MaxGL = 3;
- const int MaxPGL = 2;
-
- // NWINDOWS - number of register windows, can be 3 to 32
- const int NWindows = 8;
-
// semantically meaningful register indices
const int ZeroReg = 0; // architecturally meaningful
// the rest of these depend on the ABI
@@ -116,23 +89,35 @@ namespace SparcISA
//Why does both the previous set of constants and this one exist?
const int PageShift = 13;
- const int PageBytes = ULL(1) << PageShift;
+ const int PageBytes = 1ULL << PageShift;
const int BranchPredAddrShiftAmt = 2;
- const int MachineBytes = 8;
- const int WordBytes = 4;
- const int HalfwordBytes = 2;
- const int ByteBytes = 1;
+ StaticInstPtr decodeInst(ExtMachInst);
+
+#if FULL_SYSTEM
+ ////////// Interrupt Stuff ///////////
+ enum InterruptLevels
+ {
+ INTLEVEL_MIN = 1,
+ INTLEVEL_MAX = 15,
- void serialize(std::ostream & os);
+ NumInterruptLevels = INTLEVEL_MAX - INTLEVEL_MIN
+ };
- void unserialize(Checkpoint *cp, const std::string &section);
+ // I don't know what it's for, so I don't
+ // know what SPARC's value should be
+ // For loading... XXX This maybe could be USegEnd?? --ali
+ const Addr LoadAddrMask = ULL(0xffffffffff);
- StaticInstPtr decodeInst(ExtMachInst);
+ /////////// TLB Stuff ////////////
+ const Addr StartVAddrHole = ULL(0x0000800000000000);
+ const Addr EndVAddrHole = ULL(0xFFFF7FFFFFFFFFFF);
+ const Addr VAddrAMask = ULL(0xFFFFFFFF);
+ const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF);
+ const Addr BytesInPageMask = ULL(0x1FFF);
- // return a no-op instruction... used for instruction fetch faults
- extern const MachInst NoopMachInst;
+#endif
}
#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
index d52e3983f..53559c072 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -37,10 +37,6 @@
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
-#if FULL_SYSTEM
-#include "arch/sparc/system.hh"
-#endif
-
using namespace SparcISA;
using namespace std;
@@ -50,24 +46,29 @@ class Checkpoint;
string SparcISA::getMiscRegName(RegIndex index)
{
static::string miscRegName[NumMiscRegs] =
- {"y", "ccr", "asi", "tick", "pc", "fprs", "pcr", "pic",
- "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
- "stick", "stick_cmpr",
- "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
- "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
- "wstate", "gl",
- "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
- "hstick_cmpr",
- "fsr"};
+ {"y", "ccr", "asi", "tick", "fprs", "pcr", "pic",
+ "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
+ "stick", "stick_cmpr",
+ "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
+ "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
+ "wstate", "gl",
+ "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
+ "hstick_cmpr",
+ "fsr"};
return miscRegName[index];
}
-void MiscRegFile::reset()
+enum RegMask
+{
+ PSTATE_MASK = (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12)
+};
+
+void MiscRegFile::clear()
{
y = 0;
ccr = 0;
asi = 0;
- tick = 0;
+ tick = ULL(1) << 63;
fprs = 0;
gsr = 0;
softint = 0;
@@ -88,129 +89,285 @@ void MiscRegFile::reset()
otherwin = 0;
wstate = 0;
gl = 0;
- hpstate = 0;
+ //In a T1, bit 11 is apparently always 1
+ hpstate = (1 << 11);
memset(htstate, 0, sizeof(htstate));
hintp = 0;
htba = 0;
hstick_cmpr = 0;
- strandStatusReg = 0;
+ //This is set this way in Legion for some reason
+ strandStatusReg = 0x50000;
fsr = 0;
- implicitInstAsi = ASI_PRIMARY;
- implicitDataAsi = ASI_PRIMARY;
+
+ priContext = 0;
+ secContext = 0;
+ partId = 0;
+ lsuCtrlReg = 0;
+
+ iTlbC0TsbPs0 = 0;
+ iTlbC0TsbPs1 = 0;
+ iTlbC0Config = 0;
+ iTlbCXTsbPs0 = 0;
+ iTlbCXTsbPs1 = 0;
+ iTlbCXConfig = 0;
+ iTlbSfsr = 0;
+ iTlbTagAccess = 0;
+
+ dTlbC0TsbPs0 = 0;
+ dTlbC0TsbPs1 = 0;
+ dTlbC0Config = 0;
+ dTlbCXTsbPs0 = 0;
+ dTlbCXTsbPs1 = 0;
+ dTlbCXConfig = 0;
+ dTlbSfsr = 0;
+ dTlbSfar = 0;
+ dTlbTagAccess = 0;
+
+ memset(scratchPad, 0, sizeof(scratchPad));
}
MiscReg MiscRegFile::readReg(int miscReg)
{
switch (miscReg) {
- case MISCREG_Y:
- return y;
- case MISCREG_CCR:
- return ccr;
- case MISCREG_ASI:
- return asi;
- case MISCREG_FPRS:
- return fprs;
- case MISCREG_TICK:
- return tick;
- case MISCREG_PCR:
- panic("PCR not implemented\n");
- case MISCREG_PIC:
- panic("PIC not implemented\n");
- case MISCREG_GSR:
- return gsr;
- case MISCREG_SOFTINT:
- return softint;
- case MISCREG_TICK_CMPR:
- return tick_cmpr;
- case MISCREG_STICK:
- return stick;
- case MISCREG_STICK_CMPR:
- return stick_cmpr;
+ 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:
+ return ccr;
+ case MISCREG_ASI:
+ return asi;
+ case MISCREG_FPRS:
+ return fprs;
+ case MISCREG_TICK:
+ return tick;
+ case MISCREG_PCR:
+ panic("PCR not implemented\n");
+ case MISCREG_PIC:
+ panic("PIC not implemented\n");
+ case MISCREG_GSR:
+ return gsr;
+ case MISCREG_SOFTINT:
+ return softint;
+ case MISCREG_TICK_CMPR:
+ return tick_cmpr;
+ case MISCREG_STICK:
+ return stick;
+ case MISCREG_STICK_CMPR:
+ return stick_cmpr;
/** Privilged Registers */
- case MISCREG_TPC:
- return tpc[tl-1];
- case MISCREG_TNPC:
- return tnpc[tl-1];
- case MISCREG_TSTATE:
- return tstate[tl-1];
- case MISCREG_TT:
- return tt[tl-1];
- case MISCREG_PRIVTICK:
- panic("Priviliged access to tick registers not implemented\n");
- case MISCREG_TBA:
- return tba;
- case MISCREG_PSTATE:
- return pstate;
- case MISCREG_TL:
- return tl;
- case MISCREG_PIL:
- return pil;
- case MISCREG_CWP:
- return cwp;
- case MISCREG_CANSAVE:
- return cansave;
- case MISCREG_CANRESTORE:
- return canrestore;
- case MISCREG_CLEANWIN:
- return cleanwin;
- case MISCREG_OTHERWIN:
- return otherwin;
- case MISCREG_WSTATE:
- return wstate;
- case MISCREG_GL:
- return gl;
+ case MISCREG_TPC:
+ return tpc[tl-1];
+ case MISCREG_TNPC:
+ return tnpc[tl-1];
+ case MISCREG_TSTATE:
+ return tstate[tl-1];
+ case MISCREG_TT:
+ return tt[tl-1];
+ case MISCREG_PRIVTICK:
+ panic("Priviliged access to tick registers not implemented\n");
+ case MISCREG_TBA:
+ return tba;
+ case MISCREG_PSTATE:
+ return pstate;
+ case MISCREG_TL:
+ return tl;
+ case MISCREG_PIL:
+ return pil;
+ case MISCREG_CWP:
+ return cwp;
+ case MISCREG_CANSAVE:
+ return cansave;
+ case MISCREG_CANRESTORE:
+ return canrestore;
+ case MISCREG_CLEANWIN:
+ return cleanwin;
+ case MISCREG_OTHERWIN:
+ return otherwin;
+ case MISCREG_WSTATE:
+ return wstate;
+ case MISCREG_GL:
+ return gl;
/** Hyper privileged registers */
- case MISCREG_HPSTATE:
- return hpstate;
- case MISCREG_HTSTATE:
- return htstate[tl-1];
- case MISCREG_HINTP:
- panic("HINTP not implemented\n");
- case MISCREG_HTBA:
- return htba;
- case MISCREG_HVER:
- return NWindows | MaxTL << 8 | MaxGL << 16;
- case MISCREG_STRAND_STS_REG:
- return strandStatusReg;
- case MISCREG_HSTICK_CMPR:
- return hstick_cmpr;
+ case MISCREG_HPSTATE:
+ return hpstate;
+ case MISCREG_HTSTATE:
+ return htstate[tl-1];
+ case MISCREG_HINTP:
+ panic("HINTP not implemented\n");
+ case MISCREG_HTBA:
+ return htba;
+ case MISCREG_HVER:
+ return NWindows | MaxTL << 8 | MaxGL << 16;
+ case MISCREG_STRAND_STS_REG:
+ return strandStatusReg;
+ case MISCREG_HSTICK_CMPR:
+ return hstick_cmpr;
/** Floating Point Status Register */
- case MISCREG_FSR:
- return fsr;
- default:
- panic("Miscellaneous register %d not implemented\n", miscReg);
+ case MISCREG_FSR:
+ return fsr;
+
+ case MISCREG_MMU_P_CONTEXT:
+ return priContext;
+ case MISCREG_MMU_S_CONTEXT:
+ return secContext;
+ case MISCREG_MMU_PART_ID:
+ return partId;
+ case MISCREG_MMU_LSU_CTRL:
+ return lsuCtrlReg;
+
+ case MISCREG_MMU_ITLB_C0_TSB_PS0:
+ return iTlbC0TsbPs0;
+ case MISCREG_MMU_ITLB_C0_TSB_PS1:
+ return iTlbC0TsbPs1;
+ case MISCREG_MMU_ITLB_C0_CONFIG:
+ return iTlbC0Config;
+ case MISCREG_MMU_ITLB_CX_TSB_PS0:
+ return iTlbCXTsbPs0;
+ case MISCREG_MMU_ITLB_CX_TSB_PS1:
+ return iTlbCXTsbPs1;
+ case MISCREG_MMU_ITLB_CX_CONFIG:
+ return iTlbCXConfig;
+ case MISCREG_MMU_ITLB_SFSR:
+ return iTlbSfsr;
+ case MISCREG_MMU_ITLB_TAG_ACCESS:
+ return iTlbTagAccess;
+
+ case MISCREG_MMU_DTLB_C0_TSB_PS0:
+ return dTlbC0TsbPs0;
+ case MISCREG_MMU_DTLB_C0_TSB_PS1:
+ return dTlbC0TsbPs1;
+ case MISCREG_MMU_DTLB_C0_CONFIG:
+ return dTlbC0Config;
+ case MISCREG_MMU_DTLB_CX_TSB_PS0:
+ return dTlbCXTsbPs0;
+ case MISCREG_MMU_DTLB_CX_TSB_PS1:
+ return dTlbCXTsbPs1;
+ case MISCREG_MMU_DTLB_CX_CONFIG:
+ return dTlbCXConfig;
+ case MISCREG_MMU_DTLB_SFSR:
+ return dTlbSfsr;
+ case MISCREG_MMU_DTLB_SFAR:
+ return dTlbSfar;
+ case MISCREG_MMU_DTLB_TAG_ACCESS:
+ return dTlbTagAccess;
+
+ case MISCREG_SCRATCHPAD_R0:
+ return scratchPad[0];
+ case MISCREG_SCRATCHPAD_R1:
+ return scratchPad[1];
+ case MISCREG_SCRATCHPAD_R2:
+ return scratchPad[2];
+ case MISCREG_SCRATCHPAD_R3:
+ return scratchPad[3];
+ case MISCREG_SCRATCHPAD_R4:
+ return scratchPad[4];
+ case MISCREG_SCRATCHPAD_R5:
+ return scratchPad[5];
+ case MISCREG_SCRATCHPAD_R6:
+ return scratchPad[6];
+ case MISCREG_SCRATCHPAD_R7:
+ return scratchPad[7];
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ return cpu_mondo_head;
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ return cpu_mondo_tail;
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ return dev_mondo_head;
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ return dev_mondo_tail;
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ return res_error_head;
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ return res_error_tail;
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ return nres_error_head;
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
+ return nres_error_tail;
+ default:
+ panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
{
switch (miscReg) {
- case MISCREG_TICK:
- case MISCREG_PRIVTICK:
- return tc->getCpuPtr()->curCycle() - (tick & mask(63)) |
- (tick & ~(mask(63))) << 63;
- case MISCREG_FPRS:
- panic("FPU not implemented\n");
- case MISCREG_PCR:
- case MISCREG_PIC:
- panic("Performance Instrumentation not impl\n");
+ // tick and stick are aliased to each other in niagra
+ // 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 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;
+ case MISCREG_PCR:
+ case MISCREG_PIC:
+ panic("Performance Instrumentation not impl\n");
/** Floating Point Status Register */
- case MISCREG_FSR:
- panic("Floating Point not implemented\n");
-//We'll include this only in FS so we don't need the SparcSystem type around
-//in SE.
+ case MISCREG_FSR:
+ warn("Reading FSR Floating Point not implemented\n");
+ break;
+ case MISCREG_SOFTINT_CLR:
+ case MISCREG_SOFTINT_SET:
+ panic("Can read from softint clr/set\n");
+ case MISCREG_SOFTINT:
+ case MISCREG_TICK_CMPR:
+ case MISCREG_STICK_CMPR:
+ case MISCREG_HINTP:
+ case MISCREG_HTSTATE:
+ case MISCREG_HTBA:
+ case MISCREG_HVER:
+ case MISCREG_STRAND_STS_REG:
+ case MISCREG_HSTICK_CMPR:
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
#if FULL_SYSTEM
- case MISCREG_STICK:
- SparcSystem *sys;
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
- return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
+ case MISCREG_HPSTATE:
+ return readFSRegWithEffect(miscReg, tc);
+#else
+ 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
- case MISCREG_HVER:
- return NWindows | MaxTL << 8 | MaxGL << 16;
+
}
return readReg(miscReg);
}
@@ -218,239 +375,294 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
void MiscRegFile::setReg(int miscReg, const MiscReg &val)
{
switch (miscReg) {
- case MISCREG_Y:
- y = val;
- break;
- case MISCREG_CCR:
- ccr = val;
- break;
- case MISCREG_ASI:
- asi = val;
- break;
- case MISCREG_FPRS:
- fprs = val;
- break;
- case MISCREG_TICK:
- tick = val;
- break;
- case MISCREG_PCR:
- panic("PCR not implemented\n");
- case MISCREG_PIC:
- panic("PIC not implemented\n");
- case MISCREG_GSR:
- gsr = val;
- break;
- case MISCREG_SOFTINT:
- softint = val;
- break;
- case MISCREG_TICK_CMPR:
- tick_cmpr = val;
- break;
- case MISCREG_STICK:
- stick = val;
- break;
- case MISCREG_STICK_CMPR:
- stick_cmpr = val;
- break;
+ case MISCREG_Y:
+ y = val;
+ break;
+ case MISCREG_CCR:
+ ccr = val;
+ break;
+ case MISCREG_ASI:
+ asi = val;
+ break;
+ case MISCREG_FPRS:
+ warn("FPU not really implemented writing %#X to FPRS\n", val);
+ fprs = val;
+ break;
+ case MISCREG_TICK:
+ tick = val;
+ break;
+ case MISCREG_PCR:
+ panic("PCR not implemented\n");
+ case MISCREG_PIC:
+ panic("PIC not implemented\n");
+ case MISCREG_GSR:
+ gsr = val;
+ break;
+ case MISCREG_SOFTINT:
+ softint |= val;
+ break;
+ case MISCREG_TICK_CMPR:
+ tick_cmpr = val;
+ break;
+ case MISCREG_STICK:
+ stick = val;
+ break;
+ case MISCREG_STICK_CMPR:
+ stick_cmpr = val;
+ break;
/** Privilged Registers */
- case MISCREG_TPC:
- tpc[tl-1] = val;
- break;
- case MISCREG_TNPC:
- tnpc[tl-1] = val;
- break;
- case MISCREG_TSTATE:
- tstate[tl-1] = val;
- break;
- case MISCREG_TT:
- tt[tl-1] = val;
- break;
- case MISCREG_PRIVTICK:
- panic("Priviliged access to tick regesiters not implemented\n");
- case MISCREG_TBA:
- // clear lower 7 bits on writes.
- tba = val & ULL(~0x7FFF);
- break;
- case MISCREG_PSTATE:
- pstate = val;
- break;
- case MISCREG_TL:
- tl = val;
- break;
- case MISCREG_PIL:
- pil = val;
- break;
- case MISCREG_CWP:
- cwp = val;
- break;
- case MISCREG_CANSAVE:
- cansave = val;
- break;
- case MISCREG_CANRESTORE:
- canrestore = val;
- break;
- case MISCREG_CLEANWIN:
- cleanwin = val;
- break;
- case MISCREG_OTHERWIN:
- otherwin = val;
- break;
- case MISCREG_WSTATE:
- wstate = val;
- break;
- case MISCREG_GL:
- gl = val;
- break;
+ case MISCREG_TPC:
+ tpc[tl-1] = val;
+ break;
+ case MISCREG_TNPC:
+ tnpc[tl-1] = val;
+ break;
+ case MISCREG_TSTATE:
+ tstate[tl-1] = val;
+ break;
+ case MISCREG_TT:
+ tt[tl-1] = val;
+ break;
+ case MISCREG_PRIVTICK:
+ panic("Priviliged access to tick regesiters not implemented\n");
+ case MISCREG_TBA:
+ // clear lower 7 bits on writes.
+ tba = val & ULL(~0x7FFF);
+ break;
+ case MISCREG_PSTATE:
+ pstate = (val & PSTATE_MASK);
+ break;
+ case MISCREG_TL:
+ tl = val;
+ break;
+ case MISCREG_PIL:
+ pil = val;
+ break;
+ case MISCREG_CWP:
+ cwp = val;
+ break;
+ case MISCREG_CANSAVE:
+ cansave = val;
+ break;
+ case MISCREG_CANRESTORE:
+ canrestore = val;
+ break;
+ case MISCREG_CLEANWIN:
+ cleanwin = val;
+ break;
+ case MISCREG_OTHERWIN:
+ otherwin = val;
+ break;
+ case MISCREG_WSTATE:
+ wstate = val;
+ break;
+ case MISCREG_GL:
+ gl = val;
+ break;
/** Hyper privileged registers */
- case MISCREG_HPSTATE:
- hpstate = val;
- break;
- case MISCREG_HTSTATE:
- htstate[tl-1] = val;
- break;
- case MISCREG_HINTP:
- panic("HINTP not implemented\n");
- case MISCREG_HTBA:
- htba = val;
- break;
- case MISCREG_STRAND_STS_REG:
- strandStatusReg = val;
- break;
- case MISCREG_HSTICK_CMPR:
- hstick_cmpr = val;
- break;
+ case MISCREG_HPSTATE:
+ hpstate = val;
+ break;
+ case MISCREG_HTSTATE:
+ htstate[tl-1] = val;
+ break;
+ case MISCREG_HINTP:
+ panic("HINTP not implemented\n");
+ case MISCREG_HTBA:
+ htba = val;
+ break;
+ case MISCREG_STRAND_STS_REG:
+ strandStatusReg = val;
+ break;
+ case MISCREG_HSTICK_CMPR:
+ hstick_cmpr = val;
+ break;
/** Floating Point Status Register */
- case MISCREG_FSR:
- fsr = val;
- break;
- default:
- panic("Miscellaneous register %d not implemented\n", miscReg);
- }
-}
+ case MISCREG_FSR:
+ fsr = val;
+ break;
-inline void MiscRegFile::setImplicitAsis()
-{
- //The spec seems to use trap level to indicate the privilege level of the
- //processor. It's unclear whether the implicit ASIs should directly depend
- //on the trap level, or if they should really be based on the privelege
- //bits
- if(tl == 0)
- {
- implicitInstAsi = implicitDataAsi =
- (pstate & (1 << 9)) ? ASI_PRIMARY_LITTLE : ASI_PRIMARY;
- }
- else if(tl <= MaxPTL)
- {
- implicitInstAsi = ASI_NUCLEUS;
- implicitDataAsi = (pstate & (1 << 9)) ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS;
- }
- else
- {
- //This is supposed to force physical addresses to match the spec.
- //It might not because of context values and partition values.
- implicitInstAsi = implicitDataAsi = ASI_REAL;
+ case MISCREG_MMU_P_CONTEXT:
+ priContext = val;
+ break;
+ case MISCREG_MMU_S_CONTEXT:
+ secContext = val;
+ break;
+ case MISCREG_MMU_PART_ID:
+ partId = val;
+ break;
+ case MISCREG_MMU_LSU_CTRL:
+ lsuCtrlReg = val;
+ break;
+
+ case MISCREG_MMU_ITLB_C0_TSB_PS0:
+ iTlbC0TsbPs0 = val;
+ break;
+ case MISCREG_MMU_ITLB_C0_TSB_PS1:
+ iTlbC0TsbPs1 = val;
+ break;
+ case MISCREG_MMU_ITLB_C0_CONFIG:
+ iTlbC0Config = val;
+ break;
+ case MISCREG_MMU_ITLB_CX_TSB_PS0:
+ iTlbCXTsbPs0 = val;
+ break;
+ case MISCREG_MMU_ITLB_CX_TSB_PS1:
+ iTlbCXTsbPs1 = val;
+ break;
+ case MISCREG_MMU_ITLB_CX_CONFIG:
+ iTlbCXConfig = val;
+ break;
+ case MISCREG_MMU_ITLB_SFSR:
+ iTlbSfsr = val;
+ break;
+ case MISCREG_MMU_ITLB_TAG_ACCESS:
+ iTlbTagAccess = val;
+ break;
+
+ case MISCREG_MMU_DTLB_C0_TSB_PS0:
+ dTlbC0TsbPs0 = val;
+ break;
+ case MISCREG_MMU_DTLB_C0_TSB_PS1:
+ dTlbC0TsbPs1 = val;
+ break;
+ case MISCREG_MMU_DTLB_C0_CONFIG:
+ dTlbC0Config = val;
+ break;
+ case MISCREG_MMU_DTLB_CX_TSB_PS0:
+ dTlbCXTsbPs0 = val;
+ break;
+ case MISCREG_MMU_DTLB_CX_TSB_PS1:
+ dTlbCXTsbPs1 = val;
+ break;
+ case MISCREG_MMU_DTLB_CX_CONFIG:
+ dTlbCXConfig = val;
+ break;
+ case MISCREG_MMU_DTLB_SFSR:
+ dTlbSfsr = val;
+ break;
+ case MISCREG_MMU_DTLB_SFAR:
+ dTlbSfar = val;
+ break;
+ case MISCREG_MMU_DTLB_TAG_ACCESS:
+ dTlbTagAccess = val;
+ break;
+
+ case MISCREG_SCRATCHPAD_R0:
+ scratchPad[0] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R1:
+ scratchPad[1] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R2:
+ scratchPad[2] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R3:
+ scratchPad[3] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R4:
+ scratchPad[4] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R5:
+ scratchPad[5] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R6:
+ scratchPad[6] = val;
+ break;
+ case MISCREG_SCRATCHPAD_R7:
+ scratchPad[7] = val;
+ break;
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ cpu_mondo_head = val;
+ break;
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ cpu_mondo_tail = val;
+ break;
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ dev_mondo_head = val;
+ break;
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ dev_mondo_tail = val;
+ break;
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ res_error_head = val;
+ break;
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ res_error_tail = val;
+ break;
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ nres_error_head = val;
+ break;
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
+ nres_error_tail = val;
+ break;
+
+ default:
+ panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
void MiscRegFile::setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc)
{
- const uint64_t Bit64 = (1ULL << 63);
-#if FULL_SYSTEM
- uint64_t time;
- SparcSystem *sys;
-#endif
switch (miscReg) {
- case MISCREG_TICK:
- tick = tc->getCpuPtr()->curCycle() - val & ~Bit64;
- tick |= val & Bit64;
- break;
- case MISCREG_FPRS:
- //Configure the fpu based on the fprs
- break;
- case MISCREG_PCR:
- //Set up performance counting based on pcr value
- break;
- case MISCREG_PSTATE:
- pstate = val;
- setImplicitAsis();
- return;
- case MISCREG_TL:
- tl = val;
- setImplicitAsis();
- return;
- case MISCREG_CWP:
- tc->changeRegFileContext(CONTEXT_CWP, val);
- break;
- case MISCREG_GL:
- tc->changeRegFileContext(CONTEXT_GLOBALS, val);
- break;
- case MISCREG_SOFTINT:
- //We need to inject interrupts, and or notify the interrupt
- //object that it needs to use a different interrupt level.
- //Any newly appropriate interrupts will happen when the cpu gets
- //around to checking for them. This might not be quite what we
- //want.
- break;
- case MISCREG_SOFTINT_CLR:
- //Do whatever this is supposed to do...
- break;
- case MISCREG_SOFTINT_SET:
- //Do whatever this is supposed to do...
- break;
-#if FULL_SYSTEM
- case MISCREG_TICK_CMPR:
- if (tickCompare == NULL)
- tickCompare = new TickCompareEvent(this, tc);
- setReg(miscReg, val);
- if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
- tickCompare->deschedule();
- time = (tick_cmpr & mask(63)) - (tick & mask(63));
- if (!(tick_cmpr & ~mask(63)) && time > 0)
- tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
- break;
-#endif
- case MISCREG_PIL:
- //We need to inject interrupts, and or notify the interrupt
- //object that it needs to use a different interrupt level.
- //Any newly appropriate interrupts will happen when the cpu gets
- //around to checking for them. This might not be quite what we
- //want.
- break;
-//We'll include this only in FS so we don't need the SparcSystem type around
-//in SE.
+ case MISCREG_STICK:
+ case MISCREG_TICK:
+ // 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
+ break;
+ case MISCREG_PCR:
+ //Set up performance counting based on pcr value
+ break;
+ case MISCREG_PSTATE:
+ pstate = val & PSTATE_MASK;
+ return;
+ case MISCREG_TL:
+ tl = val;
+ return;
+ case MISCREG_CWP:
+ tc->changeRegFileContext(CONTEXT_CWP, val);
+ break;
+ case MISCREG_GL:
+ tc->changeRegFileContext(CONTEXT_GLOBALS, val);
+ break;
+ case MISCREG_PIL:
+ case MISCREG_SOFTINT:
+ case MISCREG_TICK_CMPR:
+ case MISCREG_STICK_CMPR:
+ case MISCREG_HINTP:
+ case MISCREG_HTSTATE:
+ case MISCREG_HTBA:
+ case MISCREG_HVER:
+ case MISCREG_STRAND_STS_REG:
+ case MISCREG_HSTICK_CMPR:
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
#if FULL_SYSTEM
- case MISCREG_STICK:
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
- sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64;
- stick |= val & Bit64;
- break;
- case MISCREG_STICK_CMPR:
- if (sTickCompare == NULL)
- sTickCompare = new STickCompareEvent(this, tc);
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
- if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
- sTickCompare->deschedule();
- time = (stick_cmpr & mask(63)) - sys->sysTick;
- if (!(stick_cmpr & ~mask(63)) && time > 0)
- sTickCompare->schedule(time * Clock::Int::ns);
- break;
- case MISCREG_HSTICK_CMPR:
- if (hSTickCompare == NULL)
- hSTickCompare = new HSTickCompareEvent(this, tc);
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
- if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
- hSTickCompare->deschedule();
- int64_t time = (hstick_cmpr & mask(63)) - sys->sysTick;
- if (!(hstick_cmpr & ~mask(63)) && time > 0)
- hSTickCompare->schedule(time * Clock::Int::ns);
- break;
+ case MISCREG_HPSTATE:
+ setFSRegWithEffect(miscReg, val, tc);
+ return;
+#else
+ 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);
@@ -483,8 +695,36 @@ void MiscRegFile::serialize(std::ostream & os)
SERIALIZE_ARRAY(htstate, MaxTL);
SERIALIZE_SCALAR(htba);
SERIALIZE_SCALAR(hstick_cmpr);
- SERIALIZE_SCALAR((int)implicitInstAsi);
- SERIALIZE_SCALAR((int)implicitDataAsi);
+ SERIALIZE_SCALAR(strandStatusReg);
+ SERIALIZE_SCALAR(priContext);
+ SERIALIZE_SCALAR(secContext);
+ SERIALIZE_SCALAR(partId);
+ SERIALIZE_SCALAR(lsuCtrlReg);
+ SERIALIZE_SCALAR(iTlbC0TsbPs0);
+ SERIALIZE_SCALAR(iTlbC0TsbPs1);
+ SERIALIZE_SCALAR(iTlbC0Config);
+ SERIALIZE_SCALAR(iTlbCXTsbPs0);
+ SERIALIZE_SCALAR(iTlbCXTsbPs1);
+ SERIALIZE_SCALAR(iTlbCXConfig);
+ SERIALIZE_SCALAR(iTlbSfsr);
+ SERIALIZE_SCALAR(iTlbTagAccess);
+ SERIALIZE_SCALAR(dTlbC0TsbPs0);
+ SERIALIZE_SCALAR(dTlbC0TsbPs1);
+ SERIALIZE_SCALAR(dTlbC0Config);
+ SERIALIZE_SCALAR(dTlbCXTsbPs0);
+ SERIALIZE_SCALAR(dTlbCXTsbPs1);
+ SERIALIZE_SCALAR(dTlbSfsr);
+ SERIALIZE_SCALAR(dTlbSfar);
+ SERIALIZE_SCALAR(dTlbTagAccess);
+ SERIALIZE_ARRAY(scratchPad,8);
+ SERIALIZE_SCALAR(cpu_mondo_head);
+ SERIALIZE_SCALAR(cpu_mondo_tail);
+ SERIALIZE_SCALAR(dev_mondo_head);
+ SERIALIZE_SCALAR(dev_mondo_tail);
+ SERIALIZE_SCALAR(res_error_head);
+ SERIALIZE_SCALAR(res_error_tail);
+ SERIALIZE_SCALAR(nres_error_head);
+ SERIALIZE_SCALAR(nres_error_tail);
}
void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
@@ -514,29 +754,33 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
UNSERIALIZE_ARRAY(htstate, MaxTL);
UNSERIALIZE_SCALAR(htba);
UNSERIALIZE_SCALAR(hstick_cmpr);
- int temp;
- UNSERIALIZE_SCALAR(temp);
- implicitInstAsi = (ASI)temp;
- UNSERIALIZE_SCALAR(temp);
- implicitDataAsi = (ASI)temp;
-}
-
-#if FULL_SYSTEM
-void
-MiscRegFile::processTickCompare(ThreadContext *tc)
-{
- panic("tick compare not implemented\n");
-}
-
-void
-MiscRegFile::processSTickCompare(ThreadContext *tc)
-{
- panic("tick compare not implemented\n");
-}
-
-void
-MiscRegFile::processHSTickCompare(ThreadContext *tc)
-{
- panic("tick compare not implemented\n");
-}
-#endif
+ UNSERIALIZE_SCALAR(strandStatusReg);
+ UNSERIALIZE_SCALAR(priContext);
+ UNSERIALIZE_SCALAR(secContext);
+ UNSERIALIZE_SCALAR(partId);
+ UNSERIALIZE_SCALAR(lsuCtrlReg);
+ UNSERIALIZE_SCALAR(iTlbC0TsbPs0);
+ UNSERIALIZE_SCALAR(iTlbC0TsbPs1);
+ UNSERIALIZE_SCALAR(iTlbC0Config);
+ UNSERIALIZE_SCALAR(iTlbCXTsbPs0);
+ UNSERIALIZE_SCALAR(iTlbCXTsbPs1);
+ UNSERIALIZE_SCALAR(iTlbCXConfig);
+ UNSERIALIZE_SCALAR(iTlbSfsr);
+ UNSERIALIZE_SCALAR(iTlbTagAccess);
+ UNSERIALIZE_SCALAR(dTlbC0TsbPs0);
+ UNSERIALIZE_SCALAR(dTlbC0TsbPs1);
+ UNSERIALIZE_SCALAR(dTlbC0Config);
+ UNSERIALIZE_SCALAR(dTlbCXTsbPs0);
+ UNSERIALIZE_SCALAR(dTlbCXTsbPs1);
+ UNSERIALIZE_SCALAR(dTlbSfsr);
+ UNSERIALIZE_SCALAR(dTlbSfar);
+ UNSERIALIZE_SCALAR(dTlbTagAccess);
+ UNSERIALIZE_ARRAY(scratchPad,8);
+ UNSERIALIZE_SCALAR(cpu_mondo_head);
+ UNSERIALIZE_SCALAR(cpu_mondo_tail);
+ UNSERIALIZE_SCALAR(dev_mondo_head);
+ UNSERIALIZE_SCALAR(dev_mondo_tail);
+ UNSERIALIZE_SCALAR(res_error_head);
+ UNSERIALIZE_SCALAR(res_error_tail);
+ UNSERIALIZE_SCALAR(nres_error_head);
+ UNSERIALIZE_SCALAR(nres_error_tail);}
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index f74943256..c879fd357 100644
--- a/src/arch/sparc/miscregfile.hh
+++ b/src/arch/sparc/miscregfile.hh
@@ -32,7 +32,6 @@
#ifndef __ARCH_SPARC_MISCREGFILE_HH__
#define __ARCH_SPARC_MISCREGFILE_HH__
-#include "arch/sparc/asi.hh"
#include "arch/sparc/faults.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/types.hh"
@@ -42,14 +41,13 @@
namespace SparcISA
{
-
//These functions map register indices to names
std::string getMiscRegName(RegIndex);
enum MiscRegIndex
{
/** Ancillary State Registers */
- MISCREG_Y,
+ MISCREG_Y, /* 0 */
MISCREG_CCR,
MISCREG_ASI,
MISCREG_TICK,
@@ -59,7 +57,7 @@ namespace SparcISA
MISCREG_GSR,
MISCREG_SOFTINT_SET,
MISCREG_SOFTINT_CLR,
- MISCREG_SOFTINT,
+ MISCREG_SOFTINT, /* 10 */
MISCREG_TICK_CMPR,
MISCREG_STICK,
MISCREG_STICK_CMPR,
@@ -71,7 +69,7 @@ namespace SparcISA
MISCREG_TT,
MISCREG_PRIVTICK,
MISCREG_TBA,
- MISCREG_PSTATE,
+ MISCREG_PSTATE, /* 20 */
MISCREG_TL,
MISCREG_PIL,
MISCREG_CWP,
@@ -83,7 +81,7 @@ namespace SparcISA
MISCREG_GL,
/** Hyper privileged registers */
- MISCREG_HPSTATE,
+ MISCREG_HPSTATE, /* 30 */
MISCREG_HTSTATE,
MISCREG_HINTP,
MISCREG_HTBA,
@@ -92,9 +90,79 @@ namespace SparcISA
MISCREG_HSTICK_CMPR,
/** Floating Point Status Register */
- MISCREG_FSR
+ MISCREG_FSR,
+
+ /** MMU Internal Registers */
+ MISCREG_MMU_P_CONTEXT,
+ MISCREG_MMU_S_CONTEXT, /* 40 */
+ MISCREG_MMU_PART_ID,
+ MISCREG_MMU_LSU_CTRL,
+
+ MISCREG_MMU_ITLB_C0_TSB_PS0,
+ MISCREG_MMU_ITLB_C0_TSB_PS1,
+ MISCREG_MMU_ITLB_C0_CONFIG,
+ MISCREG_MMU_ITLB_CX_TSB_PS0,
+ MISCREG_MMU_ITLB_CX_TSB_PS1,
+ MISCREG_MMU_ITLB_CX_CONFIG,
+ MISCREG_MMU_ITLB_SFSR,
+ MISCREG_MMU_ITLB_TAG_ACCESS, /* 50 */
+
+ MISCREG_MMU_DTLB_C0_TSB_PS0,
+ MISCREG_MMU_DTLB_C0_TSB_PS1,
+ MISCREG_MMU_DTLB_C0_CONFIG,
+ MISCREG_MMU_DTLB_CX_TSB_PS0,
+ MISCREG_MMU_DTLB_CX_TSB_PS1,
+ MISCREG_MMU_DTLB_CX_CONFIG,
+ MISCREG_MMU_DTLB_SFSR,
+ MISCREG_MMU_DTLB_SFAR,
+ MISCREG_MMU_DTLB_TAG_ACCESS,
+
+ /** Scratchpad regiscers **/
+ MISCREG_SCRATCHPAD_R0, /* 60 */
+ MISCREG_SCRATCHPAD_R1,
+ MISCREG_SCRATCHPAD_R2,
+ MISCREG_SCRATCHPAD_R3,
+ MISCREG_SCRATCHPAD_R4,
+ MISCREG_SCRATCHPAD_R5,
+ MISCREG_SCRATCHPAD_R6,
+ MISCREG_SCRATCHPAD_R7,
+
+ /* CPU Queue Registers */
+ MISCREG_QUEUE_CPU_MONDO_HEAD,
+ MISCREG_QUEUE_CPU_MONDO_TAIL,
+ MISCREG_QUEUE_DEV_MONDO_HEAD, /* 70 */
+ MISCREG_QUEUE_DEV_MONDO_TAIL,
+ MISCREG_QUEUE_RES_ERROR_HEAD,
+ MISCREG_QUEUE_RES_ERROR_TAIL,
+ 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
+ };
+
+ enum HPStateFields {
+ id = 0x800, // this impl. dependent (id) field must always be '1' for T1000
+ ibe = 0x400,
+ red = 0x20,
+ hpriv = 0x4,
+ tlz = 0x1
};
+ enum PStateFields {
+ cle = 0x200,
+ tle = 0x100,
+ mm = 0xC0,
+ pef = 0x10,
+ am = 0x8,
+ priv = 0x4,
+ ie = 0x2
+ };
+
+ const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
+ const int NumMiscRegs = MISCREG_NUMMISCREGS;
+
// The control registers, broken out into fields
class MiscRegFile
{
@@ -146,12 +214,49 @@ namespace SparcISA
/** Floating point misc registers. */
uint64_t fsr; // Floating-Point State Register
- ASI implicitInstAsi;
- ASI implicitDataAsi;
+ /** MMU Internal Registers */
+ uint16_t priContext;
+ uint16_t secContext;
+ uint16_t partId;
+ uint64_t lsuCtrlReg;
+
+ uint64_t iTlbC0TsbPs0;
+ uint64_t iTlbC0TsbPs1;
+ uint64_t iTlbC0Config;
+ uint64_t iTlbCXTsbPs0;
+ uint64_t iTlbCXTsbPs1;
+ uint64_t iTlbCXConfig;
+ uint64_t iTlbSfsr;
+ uint64_t iTlbTagAccess;
+
+ uint64_t dTlbC0TsbPs0;
+ uint64_t dTlbC0TsbPs1;
+ uint64_t dTlbC0Config;
+ uint64_t dTlbCXTsbPs0;
+ uint64_t dTlbCXTsbPs1;
+ uint64_t dTlbCXConfig;
+ uint64_t dTlbSfsr;
+ uint64_t dTlbSfar;
+ uint64_t dTlbTagAccess;
+
+ uint64_t scratchPad[8];
+
+ uint64_t cpu_mondo_head;
+ uint64_t cpu_mondo_tail;
+ uint64_t dev_mondo_head;
+ uint64_t dev_mondo_tail;
+ uint64_t res_error_head;
+ uint64_t res_error_tail;
+ uint64_t nres_error_head;
+ uint64_t nres_error_tail;
// These need to check the int_dis field and if 0 then
// set appropriate bit in softint and checkinterrutps on the cpu
#if FULL_SYSTEM
+ void setFSRegWithEffect(int miscReg, const MiscReg &val,
+ ThreadContext *tc);
+ MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc);
+
/** Process a tick compare event and generate an interrupt on the cpu if
* appropriate. */
void processTickCompare(ThreadContext *tc);
@@ -172,11 +277,11 @@ namespace SparcISA
#endif
public:
- void reset();
+ void clear();
MiscRegFile()
{
- reset();
+ clear();
}
MiscReg readReg(int miscReg);
@@ -188,14 +293,14 @@ namespace SparcISA
void setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc);
- ASI getInstAsid()
+ int getInstAsid()
{
- return implicitInstAsi;
+ return priContext | (uint32_t)partId << 13;
}
- ASI getDataAsid()
+ int getDataAsid()
{
- return implicitDataAsi;
+ return priContext | (uint32_t)partId << 13;
}
void serialize(std::ostream & os);
@@ -209,7 +314,6 @@ namespace SparcISA
bool isHyperPriv() { return (hpstate & (1 << 2)); }
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
bool isNonPriv() { return !isPriv(); }
- inline void setImplicitAsis();
};
}
diff --git a/src/arch/sparc/mmaped_ipr.hh b/src/arch/sparc/mmaped_ipr.hh
new file mode 100644
index 000000000..b11c16754
--- /dev/null
+++ b/src/arch/sparc/mmaped_ipr.hh
@@ -0,0 +1,72 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_SPARC_MMAPED_IPR_HH__
+#define __ARCH_SPARC_MMAPED_IPR_HH__
+
+/**
+ * @file
+ *
+ * ISA-specific helper functions for memory mapped IPR accesses.
+ */
+
+#include "config/full_system.hh"
+#include "cpu/thread_context.hh"
+#include "mem/packet.hh"
+#include "arch/sparc/tlb.hh"
+
+
+namespace SparcISA
+{
+inline Tick
+handleIprRead(ThreadContext *xc, Packet *pkt)
+{
+#if FULL_SYSTEM
+ return xc->getDTBPtr()->doMmuRegRead(xc, pkt);
+#else
+ panic("Shouldn't have a memory mapped register in SE\n");
+#endif
+}
+
+
+inline Tick
+handleIprWrite(ThreadContext *xc, Packet *pkt)
+{
+#if FULL_SYSTEM
+ return xc->getDTBPtr()->doMmuRegWrite(xc, pkt);
+#else
+ panic("Shouldn't have a memory mapped register in SE\n");
+#endif
+}
+
+
+} // namespace SparcISA
+
+#endif
diff --git a/src/arch/sparc/pagetable.cc b/src/arch/sparc/pagetable.cc
new file mode 100644
index 000000000..22130d41c
--- /dev/null
+++ b/src/arch/sparc/pagetable.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 "arch/sparc/pagetable.hh"
+#include "sim/serialize.hh"
+
+namespace SparcISA
+{
+void
+TlbEntry::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(range.va);
+ SERIALIZE_SCALAR(range.size);
+ SERIALIZE_SCALAR(range.contextId);
+ SERIALIZE_SCALAR(range.partitionId);
+ SERIALIZE_SCALAR(range.real);
+ uint64_t entry4u = pte();
+ SERIALIZE_SCALAR(entry4u);
+ SERIALIZE_SCALAR(used);
+}
+
+
+void
+TlbEntry::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(range.va);
+ UNSERIALIZE_SCALAR(range.size);
+ UNSERIALIZE_SCALAR(range.contextId);
+ UNSERIALIZE_SCALAR(range.partitionId);
+ UNSERIALIZE_SCALAR(range.real);
+ uint64_t entry4u;
+ UNSERIALIZE_SCALAR(entry4u);
+ pte.populate(entry4u);
+ UNSERIALIZE_SCALAR(used);
+}
+
+
+int PageTableEntry::pageSizes[] = {8*1024, 64*1024, 0, 4*1024*1024, 0,
+ 256*1024*1024L};
+
+
+}
diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh
new file mode 100644
index 000000000..fc01e82da
--- /dev/null
+++ b/src/arch/sparc/pagetable.hh
@@ -0,0 +1,188 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_SPARC_PAGETABLE_HH__
+#define __ARCH_SPARC_PAGETABLE_HH__
+
+#include "arch/sparc/isa_traits.hh"
+#include "base/bitfield.hh"
+#include "base/misc.hh"
+#include "config/full_system.hh"
+
+class Checkpoint;
+
+namespace SparcISA
+{
+struct VAddr
+{
+ VAddr(Addr a) { panic("not implemented yet."); }
+};
+
+class PageTableEntry
+{
+ public:
+ enum EntryType {
+ sun4v,
+ sun4u,
+ invalid
+ };
+
+ private:
+ uint64_t entry;
+ EntryType type;
+ uint64_t entry4u;
+ bool populated;
+
+
+ public:
+ PageTableEntry() : entry(0), type(invalid), populated(false) {}
+
+ PageTableEntry(uint64_t e, EntryType t = sun4u)
+ : entry(e), type(t), populated(true)
+
+ {
+ populate(entry, type);
+ }
+
+ void populate(uint64_t e, EntryType t = sun4u)
+ {
+ entry = e;
+ type = t;
+ populated = true;
+
+ // If we get a sun4v format TTE, turn it into a sun4u
+ if (type == sun4u)
+ entry4u = entry;
+ else {
+ entry4u = 0;
+ entry4u |= mbits(entry,63,63); //valid
+ entry4u |= bits(entry,1,0) << 61; //size[1:0]
+ entry4u |= bits(entry,62,62) << 60; //nfo
+ entry4u |= bits(entry,12,12) << 59; //ie
+ entry4u |= bits(entry,2,2) << 48; //size[2]
+ entry4u |= mbits(entry,39,13); //paddr
+ entry4u |= bits(entry,61,61) << 6;; // locked
+ entry4u |= bits(entry,10,10) << 5; //cp
+ entry4u |= bits(entry,9,9) << 4; //cv
+ entry4u |= bits(entry,11,11) << 3; //e
+ entry4u |= bits(entry,8,8) << 2; //p
+ entry4u |= bits(entry,6,6) << 1; //w
+ }
+ }
+
+ void clear()
+ {
+ populated = false;
+ }
+
+ static int pageSizes[6];
+
+
+ uint64_t operator()() const { assert(populated); return entry4u; }
+ const PageTableEntry &operator=(uint64_t e) { populated = true;
+ entry4u = e; return *this; }
+
+ const PageTableEntry &operator=(const PageTableEntry &e)
+ { populated = true; entry4u = e.entry4u; return *this; }
+
+ bool valid() const { return bits(entry4u,63,63) && populated; }
+ uint8_t _size() const { assert(populated);
+ return bits(entry4u, 62,61) |
+ bits(entry4u, 48,48) << 2; }
+ Addr size() const { assert(_size() < 6); return pageSizes[_size()]; }
+ bool ie() const { return bits(entry4u, 59,59); }
+ Addr pfn() const { assert(populated); return bits(entry4u,39,13); }
+ Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);}
+ bool locked() const { assert(populated); return bits(entry4u,6,6); }
+ bool cv() const { assert(populated); return bits(entry4u,4,4); }
+ bool cp() const { assert(populated); return bits(entry4u,5,5); }
+ bool priv() const { assert(populated); return bits(entry4u,2,2); }
+ bool writable() const { assert(populated); return bits(entry4u,1,1); }
+ bool nofault() const { assert(populated); return bits(entry4u,60,60); }
+ bool sideffect() const { assert(populated); return bits(entry4u,3,3); }
+};
+
+struct TlbRange {
+ Addr va;
+ Addr size;
+ int contextId;
+ int partitionId;
+ bool real;
+
+ inline bool operator<(const TlbRange &r2) const
+ {
+ if (real && !r2.real)
+ return true;
+ if (!real && r2.real)
+ return false;
+
+ if (!real && !r2.real) {
+ if (contextId < r2.contextId)
+ return true;
+ else if (contextId > r2.contextId)
+ return false;
+ }
+
+ if (partitionId < r2.partitionId)
+ return true;
+ else if (partitionId > r2.partitionId)
+ return false;
+
+ if (va < r2.va)
+ return true;
+ return false;
+ }
+ inline bool operator==(const TlbRange &r2) const
+ {
+ return va == r2.va &&
+ size == r2.size &&
+ contextId == r2.contextId &&
+ partitionId == r2.partitionId &&
+ real == r2.real;
+ }
+};
+
+
+struct TlbEntry {
+ TlbRange range;
+ PageTableEntry pte;
+ bool used;
+ bool valid;
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+
+}; // namespace SparcISA
+
+#endif // __ARCH_SPARC_PAGE_TABLE_HH__
+
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 3efe4fc08..405e408e5 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -32,6 +32,7 @@
#include "arch/sparc/asi.hh"
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
+#include "arch/sparc/types.hh"
#include "base/loader/object_file.hh"
#include "base/loader/elf_object.hh"
#include "base/misc.hh"
@@ -77,7 +78,7 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
void
SparcLiveProcess::startup()
{
- argsInit(MachineBytes, VMPageSize);
+ argsInit(sizeof(IntReg), VMPageSize);
//From the SPARC ABI
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 65e6017da..5d8ac6a17 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -70,8 +70,9 @@ void RegFile::setNextNPC(Addr val)
void RegFile::clear()
{
- intRegFile.clear();
floatRegFile.clear();
+ intRegFile.clear();
+ miscRegFile.clear();
}
MiscReg RegFile::readMiscReg(int miscReg)
@@ -253,6 +254,92 @@ void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
// FSR
dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR));
+
+ //Strand Status Register
+ dest->setMiscReg(MISCREG_STRAND_STS_REG,
+ src->readMiscReg(MISCREG_STRAND_STS_REG));
+
+ // MMU Registers
+ dest->setMiscReg(MISCREG_MMU_P_CONTEXT,
+ src->readMiscReg(MISCREG_MMU_P_CONTEXT));
+ dest->setMiscReg(MISCREG_MMU_S_CONTEXT,
+ src->readMiscReg(MISCREG_MMU_S_CONTEXT));
+ dest->setMiscReg(MISCREG_MMU_PART_ID,
+ src->readMiscReg(MISCREG_MMU_PART_ID));
+ dest->setMiscReg(MISCREG_MMU_LSU_CTRL,
+ src->readMiscReg(MISCREG_MMU_LSU_CTRL));
+
+ dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0,
+ src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0));
+ dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1,
+ src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1));
+ dest->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG,
+ src->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG));
+ dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0,
+ src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0));
+ dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1,
+ src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1));
+ dest->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG,
+ src->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG));
+ dest->setMiscReg(MISCREG_MMU_ITLB_SFSR,
+ src->readMiscReg(MISCREG_MMU_ITLB_SFSR));
+ dest->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
+ src->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS));
+
+ dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0,
+ src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0));
+ dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1,
+ src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1));
+ dest->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG,
+ src->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG));
+ dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0,
+ src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0));
+ dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1,
+ src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1));
+ dest->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG,
+ src->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG));
+ dest->setMiscReg(MISCREG_MMU_DTLB_SFSR,
+ src->readMiscReg(MISCREG_MMU_DTLB_SFSR));
+ dest->setMiscReg(MISCREG_MMU_DTLB_SFAR,
+ src->readMiscReg(MISCREG_MMU_DTLB_SFAR));
+ dest->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
+ src->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS));
+
+ // Scratchpad Registers
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R0,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R0));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R1,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R1));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R2,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R2));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R3,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R3));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R4,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R4));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R5,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R5));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R6,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R6));
+ dest->setMiscReg(MISCREG_SCRATCHPAD_R7,
+ src->readMiscReg(MISCREG_SCRATCHPAD_R7));
+
+ // Queue Registers
+ dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD,
+ src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD));
+ dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL,
+ src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL));
+ dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD,
+ src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD));
+ dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL,
+ src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL));
+ dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD,
+ src->readMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD));
+ dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL,
+ src->readMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL));
+ dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD,
+ src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD));
+ dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL,
+ src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL));
}
void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest)
diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh
index 9f33435f6..0a09d0f66 100644
--- a/src/arch/sparc/regfile.hh
+++ b/src/arch/sparc/regfile.hh
@@ -82,12 +82,12 @@ namespace SparcISA
void setMiscRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext * tc);
- ASI instAsid()
+ int instAsid()
{
return miscRegFile.getInstAsid();
}
- ASI dataAsid()
+ int dataAsid()
{
return miscRegFile.getDataAsid();
}
diff --git a/src/arch/sparc/sparc_traits.hh b/src/arch/sparc/sparc_traits.hh
new file mode 100644
index 000000000..a3d29ea8a
--- /dev/null
+++ b/src/arch/sparc/sparc_traits.hh
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ */
+
+#ifndef __ARCH_SPARC_SPARC_TRAITS_HH__
+#define __ARCH_SPARC_SPARC_TRAITS_HH__
+
+namespace SparcISA
+{
+ // Max trap levels
+ const int MaxPTL = 2;
+ const int MaxTL = 6;
+ const int MaxGL = 3;
+ const int MaxPGL = 2;
+
+ // Number of register windows, can legally be 3 to 32
+ const int NWindows = 8;
+ const int NumMicroIntRegs = 1;
+
+// const int NumRegularIntRegs = MaxGL * 8 + NWindows * 16;
+// const int NumMicroIntRegs = 1;
+// const int NumIntRegs =
+// NumRegularIntRegs +
+// NumMicroIntRegs;
+// const int NumFloatRegs = 64;
+// const int NumMiscRegs = 40;
+}
+
+#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc
index 4e907f002..da83d86fc 100644
--- a/src/arch/sparc/system.cc
+++ b/src/arch/sparc/system.cc
@@ -42,18 +42,35 @@
using namespace BigEndianGuest;
SparcSystem::SparcSystem(Params *p)
- : System(p), sysTick(0),funcRomPort(p->name + "-fport")
-
+ : System(p), sysTick(0),funcRomPort(p->name + "-fromport"),
+ funcNvramPort(p->name + "-fnvramport"),
+ funcHypDescPort(p->name + "-fhypdescport"),
+ funcPartDescPort(p->name + "-fpartdescport")
{
resetSymtab = new SymbolTable;
hypervisorSymtab = new SymbolTable;
openbootSymtab = new SymbolTable;
+ nvramSymtab = new SymbolTable;
+ hypervisorDescSymtab = new SymbolTable;
+ partitionDescSymtab = new SymbolTable;
Port *rom_port;
rom_port = params()->rom->getPort("functional");
funcRomPort.setPeer(rom_port);
rom_port->setPeer(&funcRomPort);
+ rom_port = params()->nvram->getPort("functional");
+ funcNvramPort.setPeer(rom_port);
+ rom_port->setPeer(&funcNvramPort);
+
+ rom_port = params()->hypervisor_desc->getPort("functional");
+ funcHypDescPort.setPeer(rom_port);
+ rom_port->setPeer(&funcHypDescPort);
+
+ rom_port = params()->partition_desc->getPort("functional");
+ funcPartDescPort.setPeer(rom_port);
+ rom_port->setPeer(&funcPartDescPort);
+
/**
* Load the boot code, and hypervisor into memory.
*/
@@ -72,6 +89,23 @@ SparcSystem::SparcSystem(Params *p)
if (hypervisor == NULL)
fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
+ // Read the nvram image
+ nvram = createObjectFile(params()->nvram_bin, true);
+ if (nvram == NULL)
+ fatal("Could not load nvram image %s", params()->nvram_bin);
+
+ // Read the hypervisor description image
+ hypervisor_desc = createObjectFile(params()->hypervisor_desc_bin, true);
+ if (hypervisor_desc == NULL)
+ fatal("Could not load hypervisor description image %s",
+ params()->hypervisor_desc_bin);
+
+ // Read the partition description image
+ partition_desc = createObjectFile(params()->partition_desc_bin, true);
+ if (partition_desc == NULL)
+ fatal("Could not load partition description image %s",
+ params()->partition_desc_bin);
+
// Load reset binary into memory
reset->setTextBase(params()->reset_addr);
@@ -82,6 +116,15 @@ SparcSystem::SparcSystem(Params *p)
// Load the hypervisor binary
hypervisor->setTextBase(params()->hypervisor_addr);
hypervisor->loadSections(&funcRomPort);
+ // Load the nvram image
+ nvram->setTextBase(params()->nvram_addr);
+ nvram->loadSections(&funcNvramPort);
+ // Load the hypervisor description image
+ hypervisor_desc->setTextBase(params()->hypervisor_desc_addr);
+ hypervisor_desc->loadSections(&funcHypDescPort);
+ // Load the partition description image
+ partition_desc->setTextBase(params()->partition_desc_addr);
+ partition_desc->loadSections(&funcPartDescPort);
// load symbols
if (!reset->loadGlobalSymbols(resetSymtab))
@@ -93,6 +136,15 @@ SparcSystem::SparcSystem(Params *p)
if (!hypervisor->loadLocalSymbols(hypervisorSymtab))
panic("could not load hypervisor symbols\n");
+ if (!nvram->loadLocalSymbols(nvramSymtab))
+ panic("could not load nvram symbols\n");
+
+ if (!hypervisor_desc->loadLocalSymbols(hypervisorDescSymtab))
+ panic("could not load hypervisor description symbols\n");
+
+ if (!partition_desc->loadLocalSymbols(partitionDescSymtab))
+ panic("could not load partition description symbols\n");
+
// load symbols into debug table
if (!reset->loadGlobalSymbols(debugSymbolTable))
panic("could not load reset symbols\n");
@@ -103,6 +155,20 @@ SparcSystem::SparcSystem(Params *p)
if (!hypervisor->loadLocalSymbols(debugSymbolTable))
panic("could not load hypervisor symbols\n");
+ // Strip off the rom address so when the hypervisor is copied into memory we
+ // have symbols still
+ if (!hypervisor->loadLocalSymbols(debugSymbolTable, 0xFFFFFF))
+ panic("could not load hypervisor symbols\n");
+
+ if (!nvram->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load reset symbols\n");
+
+ if (!hypervisor_desc->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load hypervisor description symbols\n");
+
+ if (!partition_desc->loadLocalSymbols(debugSymbolTable))
+ panic("could not load partition description symbols\n");
+
// @todo any fixup code over writing data in binaries on setting break
// events on functions should happen here.
@@ -114,9 +180,15 @@ SparcSystem::~SparcSystem()
delete resetSymtab;
delete hypervisorSymtab;
delete openbootSymtab;
+ delete nvramSymtab;
+ delete hypervisorDescSymtab;
+ delete partitionDescSymtab;
delete reset;
delete openboot;
delete hypervisor;
+ delete nvram;
+ delete hypervisor_desc;
+ delete partition_desc;
}
bool
@@ -132,6 +204,9 @@ SparcSystem::serialize(std::ostream &os)
resetSymtab->serialize("reset_symtab", os);
hypervisorSymtab->serialize("hypervisor_symtab", os);
openbootSymtab->serialize("openboot_symtab", os);
+ nvramSymtab->serialize("nvram_symtab", os);
+ hypervisorDescSymtab->serialize("hypervisor_desc_symtab", os);
+ partitionDescSymtab->serialize("partition_desc_symtab", os);
}
@@ -142,6 +217,9 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
resetSymtab->unserialize("reset_symtab", cp, section);
hypervisorSymtab->unserialize("hypervisor_symtab", cp, section);
openbootSymtab->unserialize("openboot_symtab", cp, section);
+ nvramSymtab->unserialize("nvram_symtab", cp, section);
+ hypervisorDescSymtab->unserialize("hypervisor_desc_symtab", cp, section);
+ partitionDescSymtab->unserialize("partition_desc_symtab", cp, section);
}
@@ -149,16 +227,25 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
SimObjectParam<PhysicalMemory *> rom;
+ SimObjectParam<PhysicalMemory *> nvram;
+ SimObjectParam<PhysicalMemory *> hypervisor_desc;
+ SimObjectParam<PhysicalMemory *> partition_desc;
SimpleEnumParam<System::MemoryMode> mem_mode;
Param<Addr> reset_addr;
Param<Addr> hypervisor_addr;
Param<Addr> openboot_addr;
+ Param<Addr> nvram_addr;
+ Param<Addr> hypervisor_desc_addr;
+ Param<Addr> partition_desc_addr;
Param<std::string> kernel;
Param<std::string> reset_bin;
Param<std::string> hypervisor_bin;
Param<std::string> openboot_bin;
+ Param<std::string> nvram_bin;
+ Param<std::string> hypervisor_desc_bin;
+ Param<std::string> partition_desc_bin;
Param<Tick> boot_cpu_frequency;
Param<std::string> boot_osflags;
@@ -171,17 +258,30 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
INIT_PARAM(physmem, "phsyical memory"),
INIT_PARAM(rom, "ROM for boot code"),
+ INIT_PARAM(nvram, "Non-volatile RAM for the nvram"),
+ INIT_PARAM(hypervisor_desc, "ROM for the hypervisor description"),
+ INIT_PARAM(partition_desc, "ROM for the partition description"),
INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
System::MemoryModeStrings),
INIT_PARAM(reset_addr, "Address that reset should be loaded at"),
INIT_PARAM(hypervisor_addr, "Address that hypervisor should be loaded at"),
INIT_PARAM(openboot_addr, "Address that openboot should be loaded at"),
+ INIT_PARAM(nvram_addr, "Address that nvram should be loaded at"),
+ INIT_PARAM(hypervisor_desc_addr,
+ "Address that hypervisor description should be loaded at"),
+ INIT_PARAM(partition_desc_addr,
+ "Address that partition description should be loaded at"),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
INIT_PARAM(openboot_bin, "file that contains the openboot code"),
+ INIT_PARAM(nvram_bin, "file that contains the nvram image"),
+ INIT_PARAM(hypervisor_desc_bin,
+ "file that contains the hypervisor description image"),
+ INIT_PARAM(partition_desc_bin,
+ "file that contains the partition description image"),
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
"a"),
@@ -197,14 +297,23 @@ CREATE_SIM_OBJECT(SparcSystem)
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
p->rom = rom;
+ p->nvram = nvram;
+ p->hypervisor_desc = hypervisor_desc;
+ p->partition_desc = partition_desc;
p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->reset_addr = reset_addr;
p->hypervisor_addr = hypervisor_addr;
p->openboot_addr = openboot_addr;
+ p->nvram_addr = nvram_addr;
+ p->hypervisor_desc_addr = hypervisor_desc_addr;
+ p->partition_desc_addr = partition_desc_addr;
p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin;
p->openboot_bin = openboot_bin;
+ p->nvram_bin = nvram_bin;
+ p->hypervisor_desc_bin = hypervisor_desc_bin;
+ p->partition_desc_bin = partition_desc_bin;
p->boot_osflags = boot_osflags;
p->init_param = init_param;
p->readfile = readfile;
diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh
index 9cf3bb568..5d50ea067 100644
--- a/src/arch/sparc/system.hh
+++ b/src/arch/sparc/system.hh
@@ -46,12 +46,21 @@ class SparcSystem : public System
struct Params : public System::Params
{
PhysicalMemory *rom;
+ PhysicalMemory *nvram;
+ PhysicalMemory *hypervisor_desc;
+ PhysicalMemory *partition_desc;
Addr reset_addr;
Addr hypervisor_addr;
Addr openboot_addr;
+ Addr nvram_addr;
+ Addr hypervisor_desc_addr;
+ Addr partition_desc_addr;
std::string reset_bin;
std::string hypervisor_bin;
std::string openboot_bin;
+ std::string nvram_bin;
+ std::string hypervisor_desc_bin;
+ std::string partition_desc_bin;
std::string boot_osflags;
};
@@ -77,6 +86,15 @@ class SparcSystem : public System
/** openboot symbol table */
SymbolTable *openbootSymtab;
+ /** nvram symbol table? */
+ SymbolTable *nvramSymtab;
+
+ /** hypervisor desc symbol table? */
+ SymbolTable *hypervisorDescSymtab;
+
+ /** partition desc symbol table? */
+ SymbolTable *partitionDescSymtab;
+
/** Object pointer for the reset binary */
ObjectFile *reset;
@@ -86,12 +104,30 @@ class SparcSystem : public System
/** Object pointer for the openboot code */
ObjectFile *openboot;
+ /** Object pointer for the nvram image */
+ ObjectFile *nvram;
+
+ /** Object pointer for the hypervisor description image */
+ ObjectFile *hypervisor_desc;
+
+ /** Object pointer for the partition description image */
+ ObjectFile *partition_desc;
+
/** System Tick for syncronized tick across all cpus. */
Tick sysTick;
/** functional port to ROM */
FunctionalPort funcRomPort;
+ /** functional port to nvram */
+ FunctionalPort funcNvramPort;
+
+ /** functional port to hypervisor description */
+ FunctionalPort funcHypDescPort;
+
+ /** functional port to partition description */
+ FunctionalPort funcPartDescPort;
+
protected:
const Params *params() const { return (const Params *)_params; }
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 0b1a2ff5f..675287d18 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -25,55 +25,1054 @@
* (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: Nathan Binkert
- * Steve Reinhardt
- * Andrew Schultz
+ * Authors: Ali Saidi
*/
+#include "arch/sparc/asi.hh"
+#include "arch/sparc/miscregfile.hh"
#include "arch/sparc/tlb.hh"
+#include "base/bitfield.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "cpu/base.hh"
+#include "mem/packet_access.hh"
+#include "mem/request.hh"
#include "sim/builder.hh"
+/* @todo remove some of the magic constants. -- ali
+ * */
namespace SparcISA
{
- DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
- BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
+TLB::TLB(const std::string &name, int 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)
+ fatal("SPARC T1 TLB registers don't support more than 64 TLB entries.");
+
+ tlb = new TlbEntry[size];
+ memset(tlb, 0, sizeof(TlbEntry) * size);
+}
+
+void
+TLB::clearUsedBits()
+{
+ MapIter i;
+ for (i = lookupTable.begin(); i != lookupTable.end();) {
+ TlbEntry *t = i->second;
+ if (!t->pte.locked()) {
+ t->used = false;
+ usedEntries--;
+ }
+ }
+}
+
+
+void
+TLB::insert(Addr va, int partition_id, int context_id, bool real,
+ const PageTableEntry& PTE, int entry)
+{
+
+
+ MapIter i;
+ 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);
+
+ if (entry != -1) {
+ assert(entry < size && entry >= 0);
+ new_entry = &tlb[entry];
+ } else {
+ for (x = 0; x < size; x++) {
+ if (!tlb[x].valid || !tlb[x].used) {
+ new_entry = &tlb[x];
+ break;
+ }
+ }
+ }
+
+ // Update the last ently if their all locked
+ if (!new_entry)
+ new_entry = &tlb[size-1];
+
+ assert(PTE.valid());
+ new_entry->range.va = va;
+ new_entry->range.size = PTE.size();
+ new_entry->range.partitionId = partition_id;
+ new_entry->range.contextId = context_id;
+ new_entry->range.real = real;
+ new_entry->pte = PTE;
+ new_entry->used = true;;
+ new_entry->valid = true;
+ 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);
+ }
+
+ lookupTable.insert(new_entry->range, new_entry);;
+
+ // If all entries have there used bit set, clear it on them all, but the
+ // one we just inserted
+ if (usedEntries == size) {
+ clearUsedBits();
+ new_entry->used = true;
+ usedEntries++;
+ }
+
+}
+
+
+TlbEntry*
+TLB::lookup(Addr va, int partition_id, bool real, int context_id)
+{
+ MapIter i;
+ TlbRange tr;
+ TlbEntry *t;
+
+ DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n",
+ va, partition_id, context_id, real);
+ // Assemble full address structure
+ tr.va = va;
+ tr.size = va + MachineBytes;
+ tr.contextId = context_id;
+ tr.partitionId = partition_id;
+ tr.real = real;
+
+ // Try to find the entry
+ i = lookupTable.find(tr);
+ if (i == lookupTable.end()) {
+ DPRINTF(TLB, "TLB: No valid entry found\n");
+ return NULL;
+ }
+
+ // Mark the entries used bit and clear other used bits in needed
+ t = i->second;
+ DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(),
+ t->pte.size());
+ if (!t->used) {
+ t->used = true;
+ usedEntries++;
+ if (usedEntries == size) {
+ clearUsedBits();
+ t->used = true;
+ usedEntries++;
+ }
+ }
+
+ return t;
+}
+
+void
+TLB::dumpAll()
+{
+ for (int x = 0; x < size; x++) {
+ if (tlb[x].valid) {
+ DPRINTFN("%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n",
+ x, tlb[x].range.partitionId, tlb[x].range.contextId,
+ tlb[x].range.real ? 'R' : ' ', tlb[x].range.size,
+ tlb[x].range.va, tlb[x].pte.paddr(), tlb[x].pte());
+ }
+ }
+}
+
+void
+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;
+ tr.contextId = context_id;
+ tr.partitionId = partition_id;
+ tr.real = real;
+
+ // 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--;
+ }
+ lookupTable.erase(i);
+ }
+}
+
+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) {
+ tlb[x].valid = false;
+ if (tlb[x].used) {
+ tlb[x].used = false;
+ usedEntries--;
+ }
+ lookupTable.erase(tlb[x].range);
+ }
+ }
+}
+
+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;
+ if (tlb[x].used) {
+ tlb[x].used = false;
+ usedEntries--;
+ }
+ lookupTable.erase(tlb[x].range);
+ }
+ }
+}
+
+void
+TLB::invalidateAll()
+{
+ int x;
+ cacheValid = false;
+
+ for (x = 0; x < size; x++) {
+ tlb[x].valid = false;
+ }
+ usedEntries = 0;
+}
+
+uint64_t
+TLB::TteRead(int entry) {
+ assert(entry < size);
+ return tlb[entry].pte();
+}
+
+uint64_t
+TLB::TagRead(int entry) {
+ assert(entry < size);
+ uint64_t tag;
+
+ tag = tlb[entry].range.contextId | tlb[entry].range.va |
+ (uint64_t)tlb[entry].range.partitionId << 61;
+ tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
+ tag |= (uint64_t)~tlb[entry].pte._size() << 56;
+ return tag;
+}
+
+bool
+TLB::validVirtualAddress(Addr va, bool am)
+{
+ if (am)
+ return true;
+ if (va >= StartVAddrHole && va <= EndVAddrHole)
+ return false;
+ return true;
+}
+
+void
+TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
+ bool se, FaultTypes ft, int asi)
+{
+ uint64_t sfsr;
+ sfsr = tc->readMiscReg(reg);
+
+ if (sfsr & 0x1)
+ sfsr = 0x3;
+ else
+ sfsr = 1;
+
+ if (write)
+ sfsr |= 1 << 2;
+ sfsr |= ct << 4;
+ if (se)
+ sfsr |= 1 << 6;
+ sfsr |= ft << 7;
+ sfsr |= asi << 16;
+ tc->setMiscRegWithEffect(reg, sfsr);
+}
+
+void
+TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context)
+{
+ tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0));
+}
+
+void
+ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct,
+ bool se, FaultTypes ft, int asi)
+{
+ DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n",
+ (int)write, ct, ft, asi);
+ TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi);
+}
+
+void
+ITB::writeTagAccess(ThreadContext *tc, Addr va, int context)
+{
+ TLB::writeTagAccess(tc, MISCREG_MMU_ITLB_TAG_ACCESS, va, context);
+}
+
+void
+DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
+ bool se, FaultTypes ft, int asi)
+{
+ DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n",
+ a, (int)write, ct, ft, asi);
+ TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a);
+}
+
+void
+DTB::writeTagAccess(ThreadContext *tc, Addr va, int context)
+{
+ TLB::writeTagAccess(tc, MISCREG_MMU_DTLB_TAG_ACCESS, va, context);
+}
+
+
+
+Fault
+ITB::translate(RequestPtr &req, ThreadContext *tc)
+{
+ uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
+
+ Addr vaddr = req->getVaddr();
+ TlbEntry *e;
+
+ assert(req->getAsi() == ASI_IMPLICIT);
+
+ DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
+ vaddr, req->getSize());
+
+ // 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);
- Param<int> size;
+ if (tl > 0) {
+ asi = ASI_N;
+ ct = Nucleus;
+ context = 0;
+ } else {
+ asi = ASI_P;
+ ct = Primary;
+ context = pri_context;
+ }
+
+ if ( hpriv || red ) {
+ cacheValid = true;
+ cacheState = tlbdata;
+ cacheEntry = NULL;
+ req->setPaddr(vaddr & PAddrImplMask);
+ return NoFault;
+ }
+
+ // If the access is unaligned trap
+ if (vaddr & 0x3) {
+ writeSfsr(tc, false, ct, false, OtherFault, asi);
+ return new MemAddressNotAligned;
+ }
+
+ if (addr_mask)
+ vaddr = vaddr & VAddrAMask;
+
+ if (!validVirtualAddress(vaddr, addr_mask)) {
+ writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
+ return new InstructionAccessException;
+ }
+
+ if (!lsu_im) {
+ e = lookup(vaddr, part_id, true);
+ real = true;
+ context = 0;
+ } else {
+ e = lookup(vaddr, part_id, false, context);
+ }
+
+ if (e == NULL || !e->valid) {
+ tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
+ vaddr & ~BytesInPageMask | context);
+ if (real)
+ return new InstructionRealTranslationMiss;
+ else
+ return new FastInstructionAccessMMUMiss;
+ }
+
+ // were not priviledged accesing priv page
+ if (!priv && e->pte.priv()) {
+ writeSfsr(tc, false, ct, false, PrivViolation, asi);
+ return new InstructionAccessException;
+ }
+
+ // cache translation date for next translation
+ cacheValid = true;
+ cacheState = tlbdata;
+ cacheEntry = e;
+
+ req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
+ vaddr & e->pte.size()-1 );
+ DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
+ return NoFault;
+}
+
+
+
+Fault
+DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
+{
+ /* @todo this could really use some profiling and fixing to make it faster! */
+ uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
+ Addr vaddr = req->getVaddr();
+ Addr size = req->getSize();
+ ASI asi;
+ 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);
+
+ 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;
+ ct = Nucleus;
+ context = 0;
+ } else {
+ asi = ASI_P;
+ ct = Primary;
+ context = pri_context;
+ }
+ } else if (!hpriv && !red) {
+ if (tl > 0 || AsiIsNucleus(asi)) {
+ ct = Nucleus;
+ context = 0;
+ } else if (AsiIsSecondary(asi)) {
+ ct = Secondary;
+ context = sec_context;
+ } else {
+ context = pri_context;
+ ct = Primary; //???
+ }
+
+ // We need to check for priv level/asi priv
+ if (!priv && !AsiIsUnPriv(asi)) {
+ // It appears that context should be Nucleus in these cases?
+ writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
+ return new PrivilegedAction;
+ }
+ if (priv && AsiIsHPriv(asi)) {
+ writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
+ return new DataAccessException;
+ }
+
+ } else if (hpriv) {
+ if (asi == ASI_P) {
+ ct = Primary;
+ context = pri_context;
+ goto continueDtbFlow;
+ }
+ }
+
+ if (!implicit) {
+ if (AsiIsLittle(asi))
+ panic("Little Endian ASIs not supported\n");
+ if (AsiIsBlock(asi))
+ 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))
+ panic("Partial Store ASIs not supported\n");
+ if (AsiIsInterrupt(asi))
+ panic("Interrupt ASIs not supported\n");
+
+ if (AsiIsMmu(asi))
+ goto handleMmuRegAccess;
+ if (AsiIsScratchPad(asi))
+ goto handleScratchRegAccess;
+ if (AsiIsQueue(asi))
+ goto handleQueueRegAccess;
+ if (AsiIsSparcError(asi))
+ goto handleSparcErrorRegAccess;
+
+ if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
+ panic("Accessing ASI %#X. Should we?\n", asi);
+ }
+
+continueDtbFlow:
+ // If the asi is unaligned trap
+ if (vaddr & size-1) {
+ writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
+ return new MemAddressNotAligned;
+ }
+
+ if (addr_mask)
+ vaddr = vaddr & VAddrAMask;
+
+ if (!validVirtualAddress(vaddr, addr_mask)) {
+ writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
+ return new DataAccessException;
+ }
+
+
+ if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) {
+ real = true;
+ context = 0;
+ };
+
+ if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
+ req->setPaddr(vaddr & PAddrImplMask);
+ return NoFault;
+ }
+
+ e = lookup(vaddr, part_id, real, context);
- END_DECLARE_SIM_OBJECT_PARAMS(ITB)
+ if (e == NULL || !e->valid) {
+ tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
+ vaddr & ~BytesInPageMask | context);
+ DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
+ if (real)
+ return new DataRealTranslationMiss;
+ else
+ return new FastDataAccessMMUMiss;
+
+ }
- BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
- INIT_PARAM_DFLT(size, "TLB size", 48)
+ if (write && !e->pte.writable()) {
+ writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
+ return new FastDataAccessProtection;
+ }
- END_INIT_SIM_OBJECT_PARAMS(ITB)
+ if (e->pte.nofault() && !AsiIsNoFault(asi)) {
+ writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
+ return new DataAccessException;
+ }
+ if (e->pte.sideffect())
+ req->setFlags(req->getFlags() | UNCACHEABLE);
- CREATE_SIM_OBJECT(ITB)
- {
- return new ITB(getInstanceName(), size);
+
+ if (!priv && e->pte.priv()) {
+ writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
+ return new DataAccessException;
}
- REGISTER_SIM_OBJECT("SparcITB", ITB)
+ // 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;
+ }
- BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
+ req->setPaddr(e->pte.paddr() & ~(e->pte.size()-1) |
+ vaddr & e->pte.size()-1);
+ DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
+ return NoFault;
+ /** Normal flow ends here. */
- Param<int> size;
+handleScratchRegAccess:
+ if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new DataAccessException;
+ }
+ goto regAccessOk;
+
+handleQueueRegAccess:
+ if (!priv && !hpriv) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new PrivilegedAction;
+ }
+ if (priv && vaddr & 0xF || vaddr > 0x3f8 || vaddr < 0x3c0) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new DataAccessException;
+ }
+ goto regAccessOk;
+
+handleSparcErrorRegAccess:
+ if (!hpriv) {
+ if (priv) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new DataAccessException;
+ } else {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new PrivilegedAction;
+ }
+ }
+ goto regAccessOk;
- END_DECLARE_SIM_OBJECT_PARAMS(DTB)
- BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
+regAccessOk:
+handleMmuRegAccess:
+ DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
+ req->setMmapedIpr(true);
+ req->setPaddr(req->getVaddr());
+ return NoFault;
+};
- INIT_PARAM_DFLT(size, "TLB size", 64)
+Tick
+DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
+{
+ Addr va = pkt->getAddr();
+ ASI asi = (ASI)pkt->req->getAsi();
+ uint64_t temp, data;
+ uint64_t tsbtemp, cnftemp;
- END_INIT_SIM_OBJECT_PARAMS(DTB)
+ DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
+ (uint32_t)pkt->req->getAsi(), pkt->getAddr());
+ switch (asi) {
+ case ASI_LSU_CONTROL_REG:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL));
+ break;
+ case ASI_MMU:
+ switch (va) {
+ case 0x8:
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT));
+ break;
+ case 0x10:
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT));
+ break;
+ default:
+ goto doMmuReadError;
+ }
+ break;
+ case ASI_QUEUE:
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
+ (va >> 4) - 0x3c));
+ break;
+ case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0));
+ break;
+ case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1));
+ break;
+ case ASI_DMMU_CTXT_ZERO_CONFIG:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG));
+ break;
+ case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0));
+ break;
+ case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1));
+ break;
+ case ASI_IMMU_CTXT_ZERO_CONFIG:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG));
+ break;
+ case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0));
+ break;
+ case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1));
+ break;
+ case ASI_DMMU_CTXT_NONZERO_CONFIG:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
+ break;
+ case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0));
+ break;
+ case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1));
+ break;
+ case ASI_IMMU_CTXT_NONZERO_CONFIG:
+ assert(va == 0);
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
+ break;
+ case ASI_SPARC_ERROR_STATUS_REG:
+ warn("returning 0 for SPARC ERROR regsiter read\n");
+ pkt->set(0);
+ break;
+ case ASI_HYP_SCRATCHPAD:
+ case ASI_SCRATCHPAD:
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
+ 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;
+ default:
+ goto doMmuReadError;
+ }
+ 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;
+ case 0x80:
+ pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID));
+ break;
+ default:
+ 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;
- CREATE_SIM_OBJECT(DTB)
- {
- return new DTB(getInstanceName(), size);
+ default:
+doMmuReadError:
+ panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
+ (uint32_t)asi, va);
}
+ pkt->result = Packet::Success;
+ return tc->getCpuPtr()->cycles(1);
+}
+
+Tick
+DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
+{
+ uint64_t data = gtoh(pkt->get<uint64_t>());
+ Addr va = pkt->getAddr();
+ ASI asi = (ASI)pkt->req->getAsi();
+
+ Addr ta_insert;
+ Addr va_insert;
+ Addr ct_insert;
+ int part_insert;
+ int entry_insert = -1;
+ bool real_insert;
+ PageTableEntry pte;
+
+ DPRINTF(IPR, "Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
+ (uint32_t)asi, va, data);
+
+ switch (asi) {
+ case ASI_LSU_CONTROL_REG:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data);
+ break;
+ case ASI_MMU:
+ switch (va) {
+ case 0x8:
+ tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data);
+ break;
+ case 0x10:
+ tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data);
+ break;
+ default:
+ goto doMmuWriteError;
+ }
+ break;
+ case ASI_QUEUE:
+ assert(mbits(data,13,6) == data);
+ tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD +
+ (va >> 4) - 0x3c, data);
+ break;
+ case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data);
+ break;
+ case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data);
+ break;
+ case ASI_DMMU_CTXT_ZERO_CONFIG:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data);
+ break;
+ case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data);
+ break;
+ case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data);
+ break;
+ case ASI_IMMU_CTXT_ZERO_CONFIG:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data);
+ break;
+ case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data);
+ break;
+ case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data);
+ break;
+ case ASI_DMMU_CTXT_NONZERO_CONFIG:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data);
+ break;
+ case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data);
+ break;
+ case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data);
+ break;
+ case ASI_IMMU_CTXT_NONZERO_CONFIG:
+ assert(va == 0);
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data);
+ break;
+ case ASI_SPARC_ERROR_EN_REG:
+ case ASI_SPARC_ERROR_STATUS_REG:
+ warn("Ignoring write to SPARC ERROR regsiter\n");
+ break;
+ case ASI_HYP_SCRATCHPAD:
+ case ASI_SCRATCHPAD:
+ tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data);
+ break;
+ case ASI_IMMU:
+ switch (va) {
+ case 0x30:
+ tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data);
+ break;
+ default:
+ goto doMmuWriteError;
+ }
+ break;
+ case ASI_ITLB_DATA_ACCESS_REG:
+ entry_insert = bits(va, 8,3);
+ case ASI_ITLB_DATA_IN_REG:
+ assert(entry_insert != -1 || mbits(va,10,9) == va);
+ ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
+ va_insert = mbits(ta_insert, 63,13);
+ ct_insert = mbits(ta_insert, 12,0);
+ part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID);
+ real_insert = bits(va, 9,9);
+ pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v :
+ PageTableEntry::sun4u);
+ tc->getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert,
+ pte, entry_insert);
+ break;
+ case ASI_DTLB_DATA_ACCESS_REG:
+ entry_insert = bits(va, 8,3);
+ case ASI_DTLB_DATA_IN_REG:
+ assert(entry_insert != -1 || mbits(va,10,9) == va);
+ ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
+ va_insert = mbits(ta_insert, 63,13);
+ ct_insert = mbits(ta_insert, 12,0);
+ part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID);
+ real_insert = bits(va, 9,9);
+ pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v :
+ PageTableEntry::sun4u);
+ insert(va_insert, part_insert, ct_insert, real_insert, pte, entry_insert);
+ break;
+ case ASI_DMMU:
+ switch (va) {
+ case 0x30:
+ tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data);
+ break;
+ case 0x80:
+ tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data);
+ break;
+ default:
+ goto doMmuWriteError;
+ }
+ break;
+ default:
+doMmuWriteError:
+ panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
+ (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
+ }
+ pkt->result = Packet::Success;
+ return tc->getCpuPtr()->cycles(1);
+}
+
+void
+TLB::serialize(std::ostream &os)
+{
+ panic("Need to implement serialize tlb for SPARC\n");
+}
+
+void
+TLB::unserialize(Checkpoint *cp, const std::string &section)
+{
+ panic("Need to implement unserialize tlb for SPARC\n");
+}
+
+
+DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
+
+ Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(ITB)
+
+BEGIN_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("SparcITB", ITB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
+
+ Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(DTB)
+
+BEGIN_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("SparcDTB", DTB)
+REGISTER_SIM_OBJECT("SparcDTB", DTB)
}
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
index 136103f44..f69b40ffb 100644
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -31,57 +31,144 @@
#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"
#include "sim/faults.hh"
#include "sim/sim_object.hh"
class ThreadContext;
+class Packet;
namespace SparcISA
{
- const int PAddrImplBits = 40;
- const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1;
- class TLB : public SimObject
- {
- public:
- TLB(const std::string &name, int size) : SimObject(name)
- {
- }
+class TLB : public SimObject
+{
+ protected:
+ TlbMap lookupTable;;
+ typedef TlbMap::iterator MapIter;
+
+ TlbEntry *tlb;
+
+ int size;
+ int usedEntries;
+
+ uint64_t cacheState;
+ bool cacheValid;
+
+ enum FaultTypes {
+ OtherFault = 0,
+ PrivViolation = 0x1,
+ SideEffect = 0x2,
+ AtomicToIo = 0x4,
+ IllegalAsi = 0x8,
+ LoadFromNfo = 0x10,
+ VaOutOfRange = 0x20,
+ VaOutOfRangeJmp = 0x40
};
- class ITB : public TLB
- {
- public:
- ITB(const std::string &name, int size) : TLB(name, size)
- {
- }
-
- Fault translate(RequestPtr &req, ThreadContext *tc) const
- {
- //For now, always assume the address is already physical.
- //Also assume that there are 40 bits of physical address space.
- req->setPaddr(req->getVaddr() & PAddrImplMask);
- return NoFault;
- }
+ enum ContextType {
+ Primary = 0,
+ Secondary = 1,
+ Nucleus = 2
};
- class DTB : public TLB
+
+ /** lookup an entry in the TLB based on the partition id, and real bit if
+ * real is true or the partition id, and context id if real is false.
+ * @param va the virtual address not shifted (e.g. bottom 13 bits are 0)
+ * @param paritition_id partition this entry is for
+ * @param real is this a real->phys or virt->phys translation
+ * @param context_id if this is virt->phys what context
+ * @return A pointer to a tlb entry
+ */
+ TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0);
+
+ /** Insert a PTE into the TLB. */
+ void insert(Addr vpn, int partition_id, int context_id, bool real,
+ const PageTableEntry& PTE, int entry = -1);
+
+ /** Given an entry id, read that tlb entries' tag. */
+ 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 */
+ void invalidateAll();
+
+ /** Remove all non-locked entries from the tlb that match partition id. */
+ void demapAll(int partition_id);
+
+ /** Remove all entries that match a given context/partition id. */
+ void demapContext(int partition_id, int context_id);
+
+ /** Remve all entries that match a certain partition id, (contextid), and
+ * va). */
+ void demapPage(Addr va, int partition_id, bool real, int context_id);
+
+ /** Checks if the virtual address provided is a valid one. */
+ bool validVirtualAddress(Addr va, bool am);
+
+ void writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
+ bool se, FaultTypes ft, int asi);
+
+ void TLB::clearUsedBits();
+
+
+ void writeTagAccess(ThreadContext *tc, int reg, Addr va, int context);
+
+ public:
+ TLB(const std::string &name, int size);
+
+ void dumpAll();
+
+ // Checkpointing
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+class ITB : public TLB
+{
+ public:
+ ITB(const std::string &name, int size) : TLB(name, size)
{
- public:
- DTB(const std::string &name, int size) : TLB(name, size)
- {
- }
-
- Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const
- {
- //For now, always assume the address is already physical.
- //Also assume that there are 40 bits of physical address space.
- req->setPaddr(req->getVaddr() & ((1ULL << 40) - 1));
- return NoFault;
- }
- };
+ cacheEntry = NULL;
+ }
+
+ Fault translate(RequestPtr &req, ThreadContext *tc);
+ private:
+ 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;
+};
+
+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);
+ Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
+ Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
+
+ private:
+ void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
+ bool se, FaultTypes ft, int asi);
+ void writeTagAccess(ThreadContext *tc, Addr va, int context);
+
+ TlbEntry *cacheEntry[2];
+ ASI cacheAsi[2];
+};
+
}
#endif // __ARCH_SPARC_TLB_HH__
diff --git a/src/arch/sparc/tlb_map.hh b/src/arch/sparc/tlb_map.hh
new file mode 100644
index 000000000..688daf5b9
--- /dev/null
+++ b/src/arch/sparc/tlb_map.hh
@@ -0,0 +1,142 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_SPARC_TLB_MAP_HH__
+#define __ARCH_SPARC_TLB_MAP_HH__
+
+#include "arch/sparc/pagetable.hh"
+#include <map>
+
+namespace SparcISA
+{
+
+class TlbMap
+{
+ private:
+ typedef std::map<TlbRange, TlbEntry*> RangeMap;
+ RangeMap tree;
+
+ public:
+ typedef RangeMap::iterator iterator;
+
+ iterator find(const TlbRange &r)
+ {
+ iterator i;
+
+ i = tree.upper_bound(r);
+
+ if (i == tree.begin())
+ 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--;
+
+ if (r.real != i->first.real)
+ return tree.end();
+ if (!r.real && r.contextId != i->first.contextId)
+ return tree.end();
+ if (r.partitionId != i->first.partitionId)
+ return tree.end();
+ if (i->first.va <= r.va+r.size &&
+ i->first.va+i->first.size >= r.va)
+ return i;
+
+ return tree.end();
+ }
+
+ bool intersect(const TlbRange &r)
+ {
+ iterator i;
+ i = find(r);
+ if (i != tree.end())
+ return true;
+ return false;
+ }
+
+
+ iterator insert(TlbRange &r, TlbEntry *d)
+ {
+ if (intersect(r))
+ return tree.end();
+
+ return tree.insert(std::make_pair<TlbRange,TlbEntry*>(r, d)).first;
+ }
+
+ size_t erase(TlbRange 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 // __ARCH_SPARC_TLB_MAP_HH__
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
index 6493ddfd5..0db5f6acc 100644
--- a/src/arch/sparc/ua2005.cc
+++ b/src/arch/sparc/ua2005.cc
@@ -28,27 +28,27 @@
* Authors: Ali Saidi
*/
-#include "arch/sparc/regfile.hh"
+#include "arch/sparc/miscregfile.hh"
+#include "base/bitfield.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
-Fault
-SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
+using namespace SparcISA;
+
+void
+MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext *tc)
{
int64_t time;
- SparcSystem *sys;
switch (miscReg) {
/* Full system only ASRs */
case MISCREG_SOFTINT:
- if (isNonPriv())
- return new PrivilegedOpcode;
// Check if we are going to interrupt because of something
- int oldLevel = InterruptLevel(softint);
- int newLevel = InterruptLevel(val);
setReg(miscReg, val);
- if (newLevel > oldLevel)
- ; // MUST DO SOMETHING HERE TO TELL CPU TO LOOK FOR INTERRUPTS XXX
- //tc->getCpuPtr()->checkInterrupts = true;
- return NoFault;
+ tc->getCpuPtr()->checkInterrupts = true;
+ warn("Writing to softint not really supported, writing: %#x\n", val);
+ break;
case MISCREG_SOFTINT_CLR:
return setRegWithEffect(miscReg, ~val & softint, tc);
@@ -56,152 +56,131 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
return setRegWithEffect(miscReg, val | softint, tc);
case MISCREG_TICK_CMPR:
- if (isNonPriv())
- return new PrivilegedOpcode;
if (tickCompare == NULL)
tickCompare = new TickCompareEvent(this, tc);
setReg(miscReg, val);
- if (tick_cmprFields.int_dis && tickCompare.scheduled())
- tickCompare.deschedule();
- time = tick_cmprFields.tick_cmpr - tickFields.counter;
- if (!tick_cmprFields.int_dis && time > 0)
- tickCompare.schedule(time * tc->getCpuPtr()->cycles(1));
- return NoFault;
-
- case MISCREG_STICK:
- if (isNonPriv())
- return new PrivilegedOpcode;
- if (isPriv())
- return new PrivilegedAction;
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
- sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64;
- stickFields.npt = val & Bit64 ? 1 : 0;
- return NoFault;
+ if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
+ tickCompare->deschedule();
+ time = (tick_cmpr & mask(63)) - (tick & mask(63));
+ if (!(tick_cmpr & ~mask(63)) && time > 0)
+ tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
+ warn ("writing to TICK compare register %#X\n", val);
+ break;
case MISCREG_STICK_CMPR:
- if (isNonPriv())
- return new PrivilegedOpcode;
if (sTickCompare == NULL)
sTickCompare = new STickCompareEvent(this, tc);
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
setReg(miscReg, val);
- if (stick_cmprFields.int_dis && sTickCompare.scheduled())
- sTickCompare.deschedule();
- time = stick_cmprFields.tick_cmpr - sys->sysTick;
- if (!stick_cmprFields.int_dis && time > 0)
- sTickCompare.schedule(time * Clock::Int::ns);
- return NoFault;
-
- /* Fullsystem only Priv registers. */
- case MISCREG_PIL:
- if (FULL_SYSTEM) {
- setReg(miscReg, val);
- //tc->getCpuPtr()->checkInterrupts;
- // MUST DO SOMETHING HERE TO TELL CPU TO LOOK FOR INTERRUPTS XXX
- return NoFault;
- } else
- panic("PIL not implemented for syscall emulation\n");
-
- /* Hyper privileged registers */
- case MISCREG_HPSTATE:
- case MISCREG_HINTP:
+ if ((stick_cmpr & mask(63)) && sTickCompare->scheduled())
+ sTickCompare->deschedule();
+ time = (stick_cmpr & mask(63)) - (stick & mask(63));
+ if (!(stick_cmpr & ~mask(63)) && time > 0)
+ sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
+ warn ("writing to sTICK compare register value %#X\n", val);
+ break;
+
+ case MISCREG_PSTATE:
+ if (val & ie && !(pstate & ie)) {
+ tc->getCpuPtr()->checkInterrupts = true;
+ }
setReg(miscReg, val);
- return NoFault;
- case MISCREG_HTSTATE:
- if (tl == 0)
- return new IllegalInstruction;
+
+ case MISCREG_PIL:
+ if (val < pil) {
+ tc->getCpuPtr()->checkInterrupts = true;
+ }
setReg(miscReg, val);
- return NoFault;
+ break;
+
+ case MISCREG_HVER:
+ panic("Shouldn't be writing HVER\n");
case MISCREG_HTBA:
// clear lower 7 bits on writes.
setReg(miscReg, val & ULL(~0x7FFF));
- return NoFault;
+ break;
+
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
+ setReg(miscReg, val);
+ tc->getCpuPtr()->checkInterrupts = true;
+ break;
- case MISCREG_STRAND_STS_REG:
- setReg(miscReg, strandStatusReg);
- return NoFault;
case MISCREG_HSTICK_CMPR:
- if (isNonPriv())
- return new PrivilegedOpcode;
if (hSTickCompare == NULL)
hSTickCompare = new HSTickCompareEvent(this, tc);
- sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
- assert(sys != NULL);
setReg(miscReg, val);
- if (hstick_cmprFields.int_dis && hSTickCompare.scheduled())
- hSTickCompare.deschedule();
- int64_t time = hstick_cmprFields.tick_cmpr - sys->sysTick;
- if (!hstick_cmprFields.int_dis && time > 0)
- hSTickCompare.schedule(time * Clock::Int::ns);
- return NoFault;
+ if ((hstick_cmpr & mask(63)) && hSTickCompare->scheduled())
+ hSTickCompare->deschedule();
+ time = (hstick_cmpr & mask(63)) - (stick & mask(63));
+ if (!(hstick_cmpr & ~mask(63)) && time > 0)
+ hSTickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
+ warn ("writing to hsTICK compare register value %#X\n", val);
+ break;
+
+ case MISCREG_HPSTATE:
+ // T1000 spec says impl. dependent val must always be 1
+ setReg(miscReg, val | id);
+ break;
+ case MISCREG_HTSTATE:
+ case MISCREG_STRAND_STS_REG:
+ setReg(miscReg, val);
+ break;
+
default:
- return new IllegalInstruction;
+ panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
}
}
MiscReg
-MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc)
+MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
{
switch (miscReg) {
-
- /* Privileged registers. */
- case MISCREG_SOFTINT:
- if (isNonPriv()) {
- fault = new PrivilegedOpcode;
- return 0;
- }
- return readReg(miscReg);
- case MISCREG_TICK_CMPR:
- if (isNonPriv()) {
- fault = new PrivilegedOpcode;
- return 0;
- }
- return readReg(miscReg);
+ /* Privileged registers. */
+ case MISCREG_QUEUE_CPU_MONDO_HEAD:
+ case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ case MISCREG_QUEUE_DEV_MONDO_HEAD:
+ case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ case MISCREG_QUEUE_RES_ERROR_HEAD:
+ case MISCREG_QUEUE_RES_ERROR_TAIL:
+ case MISCREG_QUEUE_NRES_ERROR_HEAD:
+ case MISCREG_QUEUE_NRES_ERROR_TAIL:
+ case MISCREG_SOFTINT:
+ case MISCREG_TICK_CMPR:
+ case MISCREG_STICK_CMPR:
+ case MISCREG_PIL:
+ case MISCREG_HPSTATE:
+ case MISCREG_HINTP:
+ case MISCREG_HTSTATE:
+ case MISCREG_STRAND_STS_REG:
+ case MISCREG_HSTICK_CMPR:
+ return readReg(miscReg) ;
+
+ case MISCREG_HTBA:
+ return readReg(miscReg) & ULL(~0x7FFF);
+ case MISCREG_HVER:
+ return NWindows | MaxTL << 8 | MaxGL << 16;
+
+ default:
+ panic("Invalid read to FS misc register\n");
+ }
+}
+/*
+ In Niagra STICK==TICK so this isn't needed
case MISCREG_STICK:
SparcSystem *sys;
- if (stickFields.npt && !isNonPriv()) {
- fault = new PrivilegedAction;
- return 0;
- }
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
assert(sys != NULL);
- return curTick/Clock::Int::ns - sys->sysTick | stickFields.npt << 63;
- case MISCREG_STICK_CMPR:
- if (isNonPriv()) {
- fault = new PrivilegedOpcode;
- return 0;
- }
- return readReg(miscReg);
+ return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
+*/
- /* Hyper privileged registers */
- case MISCREG_HPSTATE:
- case MISCREG_HINTP:
- return readReg(miscReg);
- case MISCREG_HTSTATE:
- if (tl == 0) {
- fault = new IllegalInstruction;
- return 0;
- }
- return readReg(miscReg);
-
- case MISCREG_HTBA:
- return readReg(miscReg) & ULL(~0x7FFF);
- case MISCREG_HVER:
- return NWindows | MaxTL << 8 | MaxGL << 16;
- case MISCREG_STRAND_STS_REG:
- return strandStatusReg;
- case MISCREG_HSTICK_CMPR:
- return hstick_cmpr;
-
- default:
- fault = new IllegalInstruction;
- return 0;
- }
-}
void
MiscRegFile::processTickCompare(ThreadContext *tc)
@@ -221,4 +200,3 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc)
panic("tick compare not implemented\n");
}
-}; // namespace SparcISA
diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh
index bf2b757d6..66679a565 100644
--- a/src/arch/sparc/vtophys.hh
+++ b/src/arch/sparc/vtophys.hh
@@ -33,6 +33,7 @@
#define __ARCH_SPARC_VTOPHYS_H__
#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/pagetable.hh"
class ThreadContext;
class FunctionalPort;
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
index 177279678..1fc0bad5d 100644
--- a/src/base/bitfield.hh
+++ b/src/base/bitfield.hh
@@ -58,6 +58,18 @@ bits(T val, int first, int last)
}
/**
+ * Mask off the given bits in place like bits() but without shifting.
+ * msb = 63, lsb = 0
+ */
+template <class T>
+inline
+T
+mbits(T val, int first, int last)
+{
+ return val & (mask(first+1) & ~mask(last));
+}
+
+/**
* Sign-extend an N-bit value to 64 bits.
*/
template <int N>
diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc
index 6691bd4ae..8fbad8030 100644
--- a/src/base/loader/aout_object.cc
+++ b/src/base/loader/aout_object.cc
@@ -82,14 +82,14 @@ AoutObject::AoutObject(const string &_filename, int _fd,
bool
-AoutObject::loadGlobalSymbols(SymbolTable *symtab)
+AoutObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
// a.out symbols not supported yet
return false;
}
bool
-AoutObject::loadLocalSymbols(SymbolTable *symtab)
+AoutObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
// a.out symbols not supported yet
return false;
diff --git a/src/base/loader/aout_object.hh b/src/base/loader/aout_object.hh
index d180d69f3..7bac5be65 100644
--- a/src/base/loader/aout_object.hh
+++ b/src/base/loader/aout_object.hh
@@ -48,8 +48,10 @@ class AoutObject : public ObjectFile
public:
virtual ~AoutObject() {}
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
+ virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc
index 134f2d98d..a5a0ad9a4 100644
--- a/src/base/loader/ecoff_object.cc
+++ b/src/base/loader/ecoff_object.cc
@@ -86,7 +86,7 @@ EcoffObject::EcoffObject(const string &_filename, int _fd,
bool
-EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
+EcoffObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
if (!symtab)
return false;
@@ -115,7 +115,7 @@ EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
}
bool
-EcoffObject::loadLocalSymbols(SymbolTable *symtab)
+EcoffObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
if (!symtab)
return false;
diff --git a/src/base/loader/ecoff_object.hh b/src/base/loader/ecoff_object.hh
index 05c604b2b..ca6fa2dd0 100644
--- a/src/base/loader/ecoff_object.hh
+++ b/src/base/loader/ecoff_object.hh
@@ -52,8 +52,10 @@ class EcoffObject : public ObjectFile
public:
virtual ~EcoffObject() {}
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
+ virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index 2ca0d4f4a..7339507f6 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -330,13 +330,13 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
}
bool
-ElfObject::loadGlobalSymbols(SymbolTable *symtab)
+ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
return loadSomeSymbols(symtab, STB_GLOBAL);
}
bool
-ElfObject::loadLocalSymbols(SymbolTable *symtab)
+ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
return loadSomeSymbols(symtab, STB_LOCAL);
}
diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh
index 9755426b4..fb728b3c5 100644
--- a/src/base/loader/elf_object.hh
+++ b/src/base/loader/elf_object.hh
@@ -53,8 +53,10 @@ class ElfObject : public ObjectFile
public:
virtual ~ElfObject() {}
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
+ virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 64085185d..6e98332c5 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -78,8 +78,10 @@ class ObjectFile
virtual bool loadSections(Port *memPort, Addr addrMask =
std::numeric_limits<Addr>::max());
- virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
- virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
+ virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max()) = 0;
+ virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max()) = 0;
Arch getArch() const { return arch; }
OpSys getOpSys() const { return opSys; }
diff --git a/src/base/loader/raw_object.cc b/src/base/loader/raw_object.cc
index 1faf33426..2a52b0d6e 100644
--- a/src/base/loader/raw_object.cc
+++ b/src/base/loader/raw_object.cc
@@ -61,21 +61,21 @@ RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
}
bool
-RawObject::loadGlobalSymbols(SymbolTable *symtab)
+RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size());
- symtab->insert(text.baseAddr, filename.substr(fnameStart,
+ symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start");
return true;
}
bool
-RawObject::loadLocalSymbols(SymbolTable *symtab)
+RawObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size());
- symtab->insert(text.baseAddr, filename.substr(fnameStart,
+ symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start");
return true;
}
diff --git a/src/base/loader/raw_object.hh b/src/base/loader/raw_object.hh
index c7fff4e66..9014a2d30 100644
--- a/src/base/loader/raw_object.hh
+++ b/src/base/loader/raw_object.hh
@@ -41,8 +41,10 @@ class RawObject: public ObjectFile
public:
virtual ~RawObject() {}
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
+ virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
+ std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd, size_t len,
uint8_t *data);
diff --git a/src/base/range_map.hh b/src/base/range_map.hh
new file mode 100644
index 000000000..6d3450739
--- /dev/null
+++ b/src/base/range_map.hh
@@ -0,0 +1,246 @@
+/*
+ * 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
+ */
+
+#ifndef __BASE_RANGE_MAP_HH__
+#define __BASE_RANGE_MAP_HH__
+
+#include "base/range.hh"
+
+#include <map>
+
+template <class T,class V>
+class range_map
+{
+ private:
+ typedef std::map<Range<T>,V> RangeMap;
+ RangeMap tree;
+
+ public:
+ typedef typename RangeMap::iterator iterator;
+
+ template <class U>
+ const iterator find(const Range<U> &r)
+ {
+ iterator i;
+
+ i = tree.upper_bound(r);
+
+ 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--;
+
+ if (i->first.start <= r.end && i->first.end >= r.start)
+ return i;
+
+ return tree.end();
+ }
+
+ template <class U>
+ bool intersect(const Range<U> &r)
+ {
+ iterator i;
+ i = find(r);
+ if (i != tree.end())
+ return true;
+ return false;
+ }
+
+
+ template <class U,class W>
+ iterator insert(const Range<U> &r, const W d)
+ {
+ if (intersect(r))
+ return tree.end();
+
+ return tree.insert(std::make_pair<Range<T>,V>(r, d)).first;
+ }
+
+ 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();
+ }
+};
+
+
+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/base/traceflags.py b/src/base/traceflags.py
index 92735aa5f..c06399f81 100644
--- a/src/base/traceflags.py
+++ b/src/base/traceflags.py
@@ -109,6 +109,7 @@ baseFlags = [
'IIC',
'IICMore',
'IPI',
+ 'IPR',
'IQ',
'ISP',
'IdeCtrl',
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 7cbbb0b96..31604ad58 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -96,7 +96,7 @@ CPUProgressEvent::description()
#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
- : MemObject(p->name), clock(p->clock), checkInterrupts(true),
+ : MemObject(p->name), clock(p->clock), instCnt(0), checkInterrupts(true),
params(p), number_of_threads(p->numberOfThreads), system(p->system),
phase(p->phase)
#else
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 1d9b6a93b..8c6b079da 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -70,12 +70,16 @@ class BaseCPU : public MemObject
protected:
// CPU's clock period in terms of the number of ticks of curTime.
Tick clock;
+ // @todo remove me after debugging with legion done
+ Tick instCnt;
public:
// Tick currentTick;
inline Tick frequency() const { return Clock::Frequency / clock; }
inline Tick cycles(int numCycles) const { return clock * numCycles; }
inline Tick curCycle() const { return curTick / clock; }
+ // @todo remove me after debugging with legion done
+ Tick instCount() { return instCnt; }
/** The next cycle the CPU should be scheduled, given a cache
* access or quiesce event returning on this cycle. This function
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 113f0fe74..3fe40b4c1 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -57,6 +57,10 @@
using namespace std;
using namespace TheISA;
+#if THE_ISA == SPARC_ISA && FULL_SYSTEM
+static int diffcount = 0;
+#endif
+
namespace Trace {
SharedData *shared_data = NULL;
}
@@ -66,6 +70,56 @@ SharedData *shared_data = NULL;
// Methods for the InstRecord object
//
+#if THE_ISA == SPARC_ISA
+
+inline char * genCenteredLabel(int length, char * buffer, char * label)
+{
+ int labelLength = strlen(label);
+ assert(labelLength <= length);
+ int leftPad = (length - labelLength) / 2;
+ int rightPad = length - leftPad - labelLength;
+ char format[64];
+ sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
+ sprintf(buffer, format, "", label, "");
+ return buffer;
+}
+
+inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
+{
+ ccprintf(os, " %16s | %#018x %s %#-018x \n",
+ title, a, (a == b) ? "|" : "X", b);
+}
+
+inline void printColumnLabels(ostream & os)
+{
+ static char * regLabel = genCenteredLabel(16, new char[17], "Register");
+ static char * m5Label = genCenteredLabel(18, new char[18], "M5");
+ static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
+ ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel);
+ ccprintf(os, "--------------------+-----------------------+-----------------------\n");
+}
+
+inline void printSectionHeader(ostream & os, char * name)
+{
+ char sectionString[70];
+ genCenteredLabel(69, sectionString, name);
+ ccprintf(os, "====================================================================\n");
+ ccprintf(os, "%69s\n", sectionString);
+ ccprintf(os, "====================================================================\n");
+}
+
+inline void printLevelHeader(ostream & os, int level)
+{
+ char sectionString[70];
+ char levelName[70];
+ sprintf(levelName, "Trap stack level %d", level);
+ genCenteredLabel(69, sectionString, levelName);
+ ccprintf(os, "====================================================================\n");
+ ccprintf(os, "%69s\n", sectionString);
+ ccprintf(os, "====================================================================\n");
+}
+
+#endif
void
Trace::InstRecord::dump(ostream &outs)
@@ -229,40 +283,172 @@ Trace::InstRecord::dump(ostream &outs)
//
outs << endl;
}
-#if THE_ISA == SPARC_ISA
+#if THE_ISA == SPARC_ISA && FULL_SYSTEM
// Compare
if (flags[LEGION_LOCKSTEP])
{
bool compared = false;
bool diffPC = false;
+ bool diffCC = false;
bool diffInst = false;
bool diffRegs = false;
+ bool diffTpc = false;
+ bool diffTnpc = false;
+ bool diffTstate = false;
+ bool diffTt = false;
+ bool diffTba = false;
+ bool diffHpstate = false;
+ bool diffHtstate = false;
+ bool diffHtba = false;
+ bool diffPstate = false;
+ bool diffY = false;
+ bool diffCcr = false;
+ bool diffTl = false;
+ bool diffGl = false;
+ bool diffAsi = false;
+ bool diffPil = false;
+ bool diffCwp = false;
+ bool diffCansave = false;
+ bool diffCanrestore = false;
+ bool diffOtherwin = false;
+ bool diffCleanwin = false;
Addr m5Pc, lgnPc;
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
while (!compared) {
- m5Pc = PC & TheISA::PAddrImplMask;
- lgnPc = shared_data->pc & TheISA::PAddrImplMask;
if (shared_data->flags == OWN_M5) {
+ m5Pc = PC & TheISA::PAddrImplMask;
+ lgnPc = shared_data->pc & TheISA::PAddrImplMask;
if (lgnPc != m5Pc)
diffPC = true;
- if (shared_data->instruction != staticInst->machInst)
+
+ if (shared_data->cycle_count !=
+ thread->getCpuPtr()->instCount())
+ diffCC = true;
+
+ if (shared_data->instruction !=
+ (SparcISA::MachInst)staticInst->machInst) {
diffInst = true;
- for (int i = 0; i < TheISA::NumRegularIntRegs; i++) {
+ }
+ for (int i = 0; i < TheISA::NumIntArchRegs; i++) {
if (thread->readIntReg(i) != shared_data->intregs[i]) {
diffRegs = true;
}
}
-
- if (diffPC || diffInst || diffRegs ) {
+ uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
+ if (oldTl != shared_data->tl)
+ diffTl = true;
+ for (int i = 1; i <= MaxTL; i++) {
+ thread->setMiscReg(MISCREG_TL, i);
+ if (thread->readMiscReg(MISCREG_TPC) !=
+ shared_data->tpc[i-1])
+ diffTpc = true;
+ if (thread->readMiscReg(MISCREG_TNPC) !=
+ shared_data->tnpc[i-1])
+ diffTnpc = true;
+ if (thread->readMiscReg(MISCREG_TSTATE) !=
+ shared_data->tstate[i-1])
+ diffTstate = true;
+ if (thread->readMiscReg(MISCREG_TT) !=
+ shared_data->tt[i-1])
+ diffTt = true;
+ if (thread->readMiscReg(MISCREG_HTSTATE) !=
+ shared_data->htstate[i-1])
+ diffHtstate = true;
+ }
+ thread->setMiscReg(MISCREG_TL, oldTl);
+
+ if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
+ diffTba = true;
+ //When the hpstate register is read by an instruction,
+ //legion has bit 11 set. When it's in storage, it doesn't.
+ //Since we don't directly support seperate interpretations
+ //of the registers like that, the bit is always set to 1 and
+ //we just don't compare it. It's not supposed to matter
+ //anyway.
+ if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
+ diffHpstate = true;
+ if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
+ diffHtba = true;
+ if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
+ diffPstate = true;
+ if(shared_data->y != thread->readMiscReg(MISCREG_Y))
+ diffY = true;
+ if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
+ diffCcr = true;
+ if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
+ diffGl = true;
+ if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
+ diffAsi = true;
+ if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
+ diffPil = true;
+ if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
+ diffCwp = true;
+ if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
+ diffCansave = true;
+ if(shared_data->canrestore !=
+ thread->readMiscReg(MISCREG_CANRESTORE))
+ diffCanrestore = true;
+ if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
+ diffOtherwin = true;
+ if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
+ diffCleanwin = true;
+
+ if ((diffPC || diffCC || diffInst || diffRegs || diffTpc ||
+ diffTnpc || diffTstate || diffTt || diffHpstate ||
+ diffHtstate || diffHtba || diffPstate || diffY ||
+ diffCcr || diffTl || diffGl || diffAsi || diffPil ||
+ diffCwp || diffCansave || diffCanrestore ||
+ diffOtherwin || diffCleanwin)
+ && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) {
outs << "Differences found between M5 and Legion:";
if (diffPC)
outs << " [PC]";
+ if (diffCC)
+ outs << " [CC]";
if (diffInst)
outs << " [Instruction]";
if (diffRegs)
outs << " [IntRegs]";
+ if (diffTpc)
+ outs << " [Tpc]";
+ if (diffTnpc)
+ outs << " [Tnpc]";
+ if (diffTstate)
+ outs << " [Tstate]";
+ if (diffTt)
+ outs << " [Tt]";
+ if (diffHpstate)
+ outs << " [Hpstate]";
+ if (diffHtstate)
+ outs << " [Htstate]";
+ if (diffHtba)
+ outs << " [Htba]";
+ if (diffPstate)
+ outs << " [Pstate]";
+ if (diffY)
+ outs << " [Y]";
+ if (diffCcr)
+ outs << " [Ccr]";
+ if (diffTl)
+ outs << " [Tl]";
+ if (diffGl)
+ outs << " [Gl]";
+ if (diffAsi)
+ outs << " [Asi]";
+ if (diffPil)
+ outs << " [Pil]";
+ if (diffCwp)
+ outs << " [Cwp]";
+ if (diffCansave)
+ outs << " [Cansave]";
+ if (diffCanrestore)
+ outs << " [Canrestore]";
+ if (diffOtherwin)
+ outs << " [Otherwin]";
+ if (diffCleanwin)
+ outs << " [Cleanwin]";
outs << endl << endl;
outs << right << setfill(' ') << setw(15)
@@ -272,38 +458,127 @@ Trace::InstRecord::dump(ostream &outs)
<< "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
<< lgnPc << endl << endl;
+ outs << right << setfill(' ') << setw(15)
+ << "M5 CC: " << "0x"<< setw(16) << setfill('0')
+ << hex << thread->getCpuPtr()->instCount() << endl;
+ outs << setfill(' ') << setw(15)
+ << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
+ << shared_data->cycle_count << endl << endl;
+
outs << setfill(' ') << setw(15)
<< "M5 Inst: " << "0x"<< setw(8)
<< setfill('0') << hex << staticInst->machInst
<< staticInst->disassemble(m5Pc, debugSymbolTable)
<< endl;
- StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread));
+ StaticInstPtr legionInst =
+ StaticInst::decode(makeExtMI(shared_data->instruction,
+ thread));
outs << setfill(' ') << setw(15)
<< " Legion Inst: "
<< "0x" << setw(8) << setfill('0') << hex
<< shared_data->instruction
<< legionInst->disassemble(lgnPc, debugSymbolTable)
- << endl;
-
+ << endl << endl;
+
+ printSectionHeader(outs, "General State");
+ printColumnLabels(outs);
+ printRegPair(outs, "HPstate",
+ thread->readMiscReg(MISCREG_HPSTATE),
+ shared_data->hpstate | (1 << 11));
+ printRegPair(outs, "Htba",
+ thread->readMiscReg(MISCREG_HTBA),
+ shared_data->htba);
+ printRegPair(outs, "Pstate",
+ thread->readMiscReg(MISCREG_PSTATE),
+ shared_data->pstate);
+ printRegPair(outs, "Y",
+ thread->readMiscReg(MISCREG_Y),
+ shared_data->y);
+ printRegPair(outs, "Ccr",
+ thread->readMiscReg(MISCREG_CCR),
+ shared_data->ccr);
+ printRegPair(outs, "Tl",
+ thread->readMiscReg(MISCREG_TL),
+ shared_data->tl);
+ printRegPair(outs, "Gl",
+ thread->readMiscReg(MISCREG_GL),
+ shared_data->gl);
+ printRegPair(outs, "Asi",
+ thread->readMiscReg(MISCREG_ASI),
+ shared_data->asi);
+ printRegPair(outs, "Pil",
+ thread->readMiscReg(MISCREG_PIL),
+ shared_data->pil);
+ printRegPair(outs, "Cwp",
+ thread->readMiscReg(MISCREG_CWP),
+ shared_data->cwp);
+ printRegPair(outs, "Cansave",
+ thread->readMiscReg(MISCREG_CANSAVE),
+ shared_data->cansave);
+ printRegPair(outs, "Canrestore",
+ thread->readMiscReg(MISCREG_CANRESTORE),
+ shared_data->canrestore);
+ printRegPair(outs, "Otherwin",
+ thread->readMiscReg(MISCREG_OTHERWIN),
+ shared_data->otherwin);
+ printRegPair(outs, "Cleanwin",
+ thread->readMiscReg(MISCREG_CLEANWIN),
+ shared_data->cleanwin);
+ outs << endl;
+ for (int i = 1; i <= MaxTL; i++) {
+ printLevelHeader(outs, i);
+ printColumnLabels(outs);
+ thread->setMiscReg(MISCREG_TL, i);
+ printRegPair(outs, "Tpc",
+ thread->readMiscReg(MISCREG_TPC),
+ shared_data->tpc[i-1]);
+ printRegPair(outs, "Tnpc",
+ thread->readMiscReg(MISCREG_TNPC),
+ shared_data->tnpc[i-1]);
+ printRegPair(outs, "Tstate",
+ thread->readMiscReg(MISCREG_TSTATE),
+ shared_data->tstate[i-1]);
+ printRegPair(outs, "Tt",
+ thread->readMiscReg(MISCREG_TT),
+ shared_data->tt[i-1]);
+ printRegPair(outs, "Htstate",
+ thread->readMiscReg(MISCREG_HTSTATE),
+ shared_data->htstate[i-1]);
+ }
+ thread->setMiscReg(MISCREG_TL, oldTl);
outs << endl;
+ printSectionHeader(outs, "General Purpose Registers");
static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
for(int y = 0; y < 4; y++)
{
for(int x = 0; x < 8; x++)
{
- outs << regtypes[y] << x << " " ;
- outs << "0x" << hex << setw(16) << thread->readIntReg(y*8+x);
- if (thread->readIntReg(y*8 + x) != shared_data->intregs[y*8+x])
+ char label[8];
+ sprintf(label, "%s%d", regtypes[y], x);
+ printRegPair(outs, label,
+ thread->readIntReg(y*8+x),
+ shared_data->intregs[y*8+x]);
+ /*outs << regtypes[y] << x << " " ;
+ outs << "0x" << hex << setw(16)
+ << thread->readIntReg(y*8+x);
+ if (thread->readIntReg(y*8 + x)
+ != shared_data->intregs[y*8+x])
outs << " X ";
else
outs << " | ";
- outs << "0x" << setw(16) << hex << shared_data->intregs[y*8+x]
- << endl;
+ outs << "0x" << setw(16) << hex
+ << shared_data->intregs[y*8+x]
+ << endl;*/
}
}
- fatal("Differences found between Legion and M5\n");
+ thread->getITBPtr()->dumpAll();
+ thread->getDTBPtr()->dumpAll();
+
+ diffcount++;
+ if (diffcount > 2)
+ fatal("Differences found between Legion and M5\n");
}
compared = true;
diff --git a/src/cpu/m5legion_interface.h b/src/cpu/m5legion_interface.h
index 373fbeb11..bfb88485a 100644
--- a/src/cpu/m5legion_interface.h
+++ b/src/cpu/m5legion_interface.h
@@ -30,7 +30,7 @@
#include <unistd.h>
-#define VERSION 0xA1000005
+#define VERSION 0xA1000006
#define OWN_M5 0x000000AA
#define OWN_LEGION 0x00000055
@@ -42,6 +42,8 @@ typedef struct {
uint64_t pc;
uint64_t new_pc;
+ uint64_t cycle_count;
+ uint64_t new_cycle_count;
uint32_t instruction;
uint32_t new_instruction;
uint64_t intregs[32];
diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh
index 7bf34d827..264309fd7 100644
--- a/src/cpu/memtest/memtest.hh
+++ b/src/cpu/memtest/memtest.hh
@@ -116,7 +116,7 @@ class MemTest : public MemObject
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
};
CpuPort cachePort;
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 04016347a..e880e14e4 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -98,7 +98,7 @@ class DefaultFetch
/** Returns the address ranges of this device. */
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
/** Timing version of receive. Handles setting fetch to the
* proper status to start fetching. */
diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh
index 4937589e3..72a8d4021 100755
--- a/src/cpu/o3/isa_specific.hh
+++ b/src/cpu/o3/isa_specific.hh
@@ -40,6 +40,11 @@
#include "cpu/o3/mips/impl.hh"
#include "cpu/o3/mips/params.hh"
#include "cpu/o3/mips/dyn_inst.hh"
+#elif THE_ISA == SPARC_ISA
+ #include "cpu/o3/sparc/cpu.hh"
+ #include "cpu/o3/sparc/impl.hh"
+ #include "cpu/o3/sparc/params.hh"
+ #include "cpu/o3/sparc/dyn_inst.hh"
#else
#error "ISA-specific header files O3CPU not defined ISA"
#endif
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index 7559a36d5..e68085cfd 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -313,7 +313,7 @@ class LSQ {
/** Returns the address ranges of this device. */
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
/** Timing version of receive. Handles writing back and
* completing the load or store that has returned from
diff --git a/src/cpu/o3/sparc/cpu.cc b/src/cpu/o3/sparc/cpu.cc
new file mode 100644
index 000000000..1546a2b88
--- /dev/null
+++ b/src/cpu/o3/sparc/cpu.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2004-2005 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: Gabe Black
+ */
+
+#include "cpu/o3/sparc/impl.hh"
+#include "cpu/o3/sparc/cpu_impl.hh"
+#include "cpu/o3/sparc/dyn_inst.hh"
+
+// Force instantiation of SparcO3CPU for all the implementations that are
+// needed. Consider merging this and sparc_dyn_inst.cc, and maybe all
+// classes that depend on a certain impl, into one file (sparc_impl.cc?).
+template class SparcO3CPU<SparcSimpleImpl>;
diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh
new file mode 100644
index 000000000..c4df79832
--- /dev/null
+++ b/src/cpu/o3/sparc/cpu.hh
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2004-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: Kevin Lim
+ */
+
+#ifndef __CPU_O3_SPARC_CPU_HH__
+#define __CPU_O3_SPARC_CPU_HH__
+
+#include "arch/sparc/regfile.hh"
+#include "arch/sparc/types.hh"
+#include "cpu/thread_context.hh"
+#include "cpu/o3/cpu.hh"
+#include "sim/byteswap.hh"
+
+namespace TheISA
+{
+ class ITB;
+ class DTB;
+}
+
+class EndQuiesceEvent;
+namespace Kernel {
+ class Statistics;
+};
+
+class TranslatingPort;
+
+/**
+ * SparcO3CPU class. Derives from the FullO3CPU class, and
+ * implements all ISA and implementation specific functions of the
+ * CPU. This is the CPU class that is used for the SimObjects, and is
+ * what is given to the DynInsts. Most of its state exists in the
+ * FullO3CPU; the state is has is mainly for ISA specific
+ * functionality.
+ */
+template <class Impl>
+class SparcO3CPU : public FullO3CPU<Impl>
+{
+ protected:
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
+ typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MiscRegFile MiscRegFile;
+
+ public:
+ typedef O3ThreadState<Impl> ImplState;
+ typedef O3ThreadState<Impl> Thread;
+ typedef typename Impl::Params Params;
+
+ /** Constructs an AlphaO3CPU with the given parameters. */
+ SparcO3CPU(Params *params);
+
+#if FULL_SYSTEM
+ /** ITB pointer. */
+ SparcISA::ITB *itb;
+ /** DTB pointer. */
+ SparcISA::DTB *dtb;
+#endif
+
+ /** Registers statistics. */
+ void regStats();
+
+#if FULL_SYSTEM
+ /** Translates instruction requestion. */
+ Fault translateInstReq(RequestPtr &req, Thread *thread)
+ {
+ return itb->translate(req, thread->getTC());
+ }
+
+ /** Translates data read request. */
+ Fault translateDataReadReq(RequestPtr &req, Thread *thread)
+ {
+ return dtb->translate(req, thread->getTC(), false);
+ }
+
+ /** Translates data write request. */
+ Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
+ {
+ return dtb->translate(req, thread->getTC(), true);
+ }
+
+#else
+ /** Translates instruction requestion in syscall emulation mode. */
+ Fault translateInstReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+ /** Translates data read request in syscall emulation mode. */
+ Fault translateDataReadReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+ /** Translates data write request in syscall emulation mode. */
+ Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+#endif
+ /** Reads a miscellaneous register. */
+ MiscReg readMiscReg(int misc_reg, unsigned tid);
+
+ /** Reads a misc. register, including any side effects the read
+ * might have as defined by the architecture.
+ */
+ MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid);
+
+ /** Sets a miscellaneous register. */
+ void setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
+
+ /** Sets a misc. register, including any side effects the write
+ * might have as defined by the architecture.
+ */
+ void setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
+
+ /** Initiates a squash of all in-flight instructions for a given
+ * thread. The source of the squash is an external update of
+ * state through the TC.
+ */
+ void squashFromTC(unsigned tid);
+
+#if FULL_SYSTEM
+ /** Posts an interrupt. */
+ void post_interrupt(int int_num, int index);
+ /** HW return from error interrupt. */
+ Fault hwrei(unsigned tid);
+
+ bool simPalCheck(int palFunc, unsigned tid);
+
+ /** Returns the Fault for any valid interrupt. */
+ Fault getInterrupts();
+
+ /** Processes any an interrupt fault. */
+ void processInterrupts(Fault interrupt);
+
+ /** Halts the CPU. */
+ void halt() { panic("Halt not implemented!\n"); }
+#endif
+
+ /** Traps to handle given fault. */
+ void trap(Fault fault, unsigned tid);
+
+#if !FULL_SYSTEM
+ /** Executes a syscall.
+ * @todo: Determine if this needs to be virtual.
+ */
+ void syscall(int64_t callnum, int tid);
+ /** Gets a syscall argument. */
+ IntReg getSyscallArg(int i, int tid);
+
+ /** Used to shift args for indirect syscall. */
+ void setSyscallArg(int i, IntReg val, int tid);
+
+ /** Sets the return value of a syscall. */
+ void setSyscallReturn(SyscallReturn return_value, int tid);
+#endif
+
+ /** CPU read function, forwards read to LSQ. */
+ template <class T>
+ Fault read(RequestPtr &req, T &data, int load_idx)
+ {
+ return this->iew.ldstQueue.read(req, data, load_idx);
+ }
+
+ /** CPU write function, forwards write to LSQ. */
+ template <class T>
+ Fault write(RequestPtr &req, T &data, int store_idx)
+ {
+ return this->iew.ldstQueue.write(req, data, store_idx);
+ }
+
+ Addr lockAddr;
+
+ /** Temporary fix for the lock flag, works in the UP case. */
+ bool lockFlag;
+};
+
+#endif // __CPU_O3_ALPHA_CPU_HH__
diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc
new file mode 100644
index 000000000..81f419ee0
--- /dev/null
+++ b/src/cpu/o3/sparc/cpu_builder.cc
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#include <string>
+
+#include "cpu/base.hh"
+#include "cpu/o3/sparc/cpu.hh"
+#include "cpu/o3/sparc/impl.hh"
+#include "cpu/o3/sparc/params.hh"
+#include "cpu/o3/fu_pool.hh"
+#include "sim/builder.hh"
+
+class DerivO3CPU : public SparcO3CPU<SparcSimpleImpl>
+{
+ public:
+ DerivO3CPU(SparcSimpleParams *p)
+ : SparcO3CPU<SparcSimpleImpl>(p)
+ { }
+};
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+ Param<int> clock;
+ Param<int> phase;
+ Param<int> numThreads;
+ Param<int> activity;
+
+#if FULL_SYSTEM
+ SimObjectParam<System *> system;
+ Param<int> cpu_id;
+ SimObjectParam<AlphaISA::ITB *> itb;
+ SimObjectParam<AlphaISA::DTB *> dtb;
+ Param<Tick> profile;
+
+ Param<bool> do_quiesce;
+ Param<bool> do_checkpoint_insts;
+ Param<bool> do_statistics_insts;
+#else
+ SimObjectVectorParam<Process *> workload;
+#endif // FULL_SYSTEM
+
+ SimObjectParam<BaseCPU *> checker;
+
+ Param<Counter> max_insts_any_thread;
+ Param<Counter> max_insts_all_threads;
+ Param<Counter> max_loads_any_thread;
+ Param<Counter> max_loads_all_threads;
+ Param<Tick> progress_interval;
+
+ Param<unsigned> cachePorts;
+
+ Param<unsigned> decodeToFetchDelay;
+ Param<unsigned> renameToFetchDelay;
+ Param<unsigned> iewToFetchDelay;
+ Param<unsigned> commitToFetchDelay;
+ Param<unsigned> fetchWidth;
+
+ Param<unsigned> renameToDecodeDelay;
+ Param<unsigned> iewToDecodeDelay;
+ Param<unsigned> commitToDecodeDelay;
+ Param<unsigned> fetchToDecodeDelay;
+ Param<unsigned> decodeWidth;
+
+ Param<unsigned> iewToRenameDelay;
+ Param<unsigned> commitToRenameDelay;
+ Param<unsigned> decodeToRenameDelay;
+ Param<unsigned> renameWidth;
+
+ Param<unsigned> commitToIEWDelay;
+ Param<unsigned> renameToIEWDelay;
+ Param<unsigned> issueToExecuteDelay;
+ Param<unsigned> dispatchWidth;
+ Param<unsigned> issueWidth;
+ Param<unsigned> wbWidth;
+ Param<unsigned> wbDepth;
+ SimObjectParam<FUPool *> fuPool;
+
+ Param<unsigned> iewToCommitDelay;
+ Param<unsigned> renameToROBDelay;
+ Param<unsigned> commitWidth;
+ Param<unsigned> squashWidth;
+ Param<Tick> trapLatency;
+
+ Param<unsigned> backComSize;
+ Param<unsigned> forwardComSize;
+
+ Param<std::string> predType;
+ Param<unsigned> localPredictorSize;
+ Param<unsigned> localCtrBits;
+ Param<unsigned> localHistoryTableSize;
+ Param<unsigned> localHistoryBits;
+ Param<unsigned> globalPredictorSize;
+ Param<unsigned> globalCtrBits;
+ Param<unsigned> globalHistoryBits;
+ Param<unsigned> choicePredictorSize;
+ Param<unsigned> choiceCtrBits;
+
+ Param<unsigned> BTBEntries;
+ Param<unsigned> BTBTagSize;
+
+ Param<unsigned> RASSize;
+
+ Param<unsigned> LQEntries;
+ Param<unsigned> SQEntries;
+ Param<unsigned> LFSTSize;
+ Param<unsigned> SSITSize;
+
+ Param<unsigned> numPhysIntRegs;
+ Param<unsigned> numPhysFloatRegs;
+ Param<unsigned> numIQEntries;
+ Param<unsigned> numROBEntries;
+
+ Param<unsigned> smtNumFetchingThreads;
+ Param<std::string> smtFetchPolicy;
+ Param<std::string> smtLSQPolicy;
+ Param<unsigned> smtLSQThreshold;
+ Param<std::string> smtIQPolicy;
+ Param<unsigned> smtIQThreshold;
+ Param<std::string> smtROBPolicy;
+ Param<unsigned> smtROBThreshold;
+ Param<std::string> smtCommitPolicy;
+
+ Param<unsigned> instShiftAmt;
+
+ Param<bool> defer_registration;
+
+ Param<bool> function_trace;
+ Param<Tick> function_trace_start;
+
+END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+ INIT_PARAM(clock, "clock speed"),
+ INIT_PARAM_DFLT(phase, "clock phase", 0),
+ INIT_PARAM(numThreads, "number of HW thread contexts"),
+ INIT_PARAM_DFLT(activity, "Initial activity count", 0),
+
+#if FULL_SYSTEM
+ INIT_PARAM(system, "System object"),
+ INIT_PARAM(cpu_id, "processor ID"),
+ INIT_PARAM(itb, "Instruction translation buffer"),
+ INIT_PARAM(dtb, "Data translation buffer"),
+ INIT_PARAM(profile, ""),
+
+ INIT_PARAM(do_quiesce, ""),
+ INIT_PARAM(do_checkpoint_insts, ""),
+ INIT_PARAM(do_statistics_insts, ""),
+#else
+ INIT_PARAM(workload, "Processes to run"),
+#endif // FULL_SYSTEM
+
+ INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
+
+ INIT_PARAM_DFLT(max_insts_any_thread,
+ "Terminate when any thread reaches this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_insts_all_threads,
+ "Terminate when all threads have reached"
+ "this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_any_thread,
+ "Terminate when any thread reaches this load count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_all_threads,
+ "Terminate when all threads have reached this load"
+ "count",
+ 0),
+ INIT_PARAM_DFLT(progress_interval, "Progress interval", 0),
+
+ INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
+
+ INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
+ INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
+ INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
+ "delay"),
+ INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
+ INIT_PARAM(fetchWidth, "Fetch width"),
+ INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
+ INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
+ "delay"),
+ INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
+ INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
+ INIT_PARAM(decodeWidth, "Decode width"),
+
+ INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
+ "delay"),
+ INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
+ INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
+ INIT_PARAM(renameWidth, "Rename width"),
+
+ INIT_PARAM(commitToIEWDelay, "Commit to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(renameToIEWDelay, "Rename to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
+ "to the IEW stage)"),
+ INIT_PARAM(dispatchWidth, "Dispatch width"),
+ INIT_PARAM(issueWidth, "Issue width"),
+ INIT_PARAM(wbWidth, "Writeback width"),
+ INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"),
+ INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
+
+ INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
+ "delay"),
+ INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
+ INIT_PARAM(commitWidth, "Commit width"),
+ INIT_PARAM(squashWidth, "Squash width"),
+ INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
+
+ INIT_PARAM(backComSize, "Time buffer size for backwards communication"),
+ INIT_PARAM(forwardComSize, "Time buffer size for forward communication"),
+
+ INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
+ INIT_PARAM(localPredictorSize, "Size of local predictor"),
+ INIT_PARAM(localCtrBits, "Bits per counter"),
+ INIT_PARAM(localHistoryTableSize, "Size of local history table"),
+ INIT_PARAM(localHistoryBits, "Bits for the local history"),
+ INIT_PARAM(globalPredictorSize, "Size of global predictor"),
+ INIT_PARAM(globalCtrBits, "Bits per counter"),
+ INIT_PARAM(globalHistoryBits, "Bits of history"),
+ INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
+ INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
+
+ INIT_PARAM(BTBEntries, "Number of BTB entries"),
+ INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
+
+ INIT_PARAM(RASSize, "RAS size"),
+
+ INIT_PARAM(LQEntries, "Number of load queue entries"),
+ INIT_PARAM(SQEntries, "Number of store queue entries"),
+ INIT_PARAM(LFSTSize, "Last fetched store table size"),
+ INIT_PARAM(SSITSize, "Store set ID table size"),
+
+ INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
+ INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
+ "registers"),
+ INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
+ INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
+
+ INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
+ INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
+ INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
+ INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
+ INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
+ INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
+
+ INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace")
+
+END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+CREATE_SIM_OBJECT(DerivO3CPU)
+{
+ DerivO3CPU *cpu;
+
+#if FULL_SYSTEM
+ // Full-system only supports a single thread for the moment.
+ int actual_num_threads = 1;
+#else
+ // In non-full-system mode, we infer the number of threads from
+ // the workload if it's not explicitly specified.
+ int actual_num_threads =
+ (numThreads.isValid() && numThreads >= workload.size()) ?
+ numThreads : workload.size();
+
+ if (workload.size() == 0) {
+ fatal("Must specify at least one workload!");
+ }
+#endif
+
+ SparcSimpleParams *params = new SparcSimpleParams;
+
+ params->clock = clock;
+
+ params->name = getInstanceName();
+ params->numberOfThreads = actual_num_threads;
+ params->activity = activity;
+
+#if FULL_SYSTEM
+ params->system = system;
+ params->cpu_id = cpu_id;
+ params->itb = itb;
+ params->dtb = dtb;
+ params->profile = profile;
+
+ params->do_quiesce = do_quiesce;
+ params->do_checkpoint_insts = do_checkpoint_insts;
+ params->do_statistics_insts = do_statistics_insts;
+#else
+ params->workload = workload;
+#endif // FULL_SYSTEM
+
+ params->checker = checker;
+
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+ params->progress_interval = progress_interval;
+
+ //
+ // Caches
+ //
+ params->cachePorts = cachePorts;
+
+ params->decodeToFetchDelay = decodeToFetchDelay;
+ params->renameToFetchDelay = renameToFetchDelay;
+ params->iewToFetchDelay = iewToFetchDelay;
+ params->commitToFetchDelay = commitToFetchDelay;
+ params->fetchWidth = fetchWidth;
+
+ params->renameToDecodeDelay = renameToDecodeDelay;
+ params->iewToDecodeDelay = iewToDecodeDelay;
+ params->commitToDecodeDelay = commitToDecodeDelay;
+ params->fetchToDecodeDelay = fetchToDecodeDelay;
+ params->decodeWidth = decodeWidth;
+
+ params->iewToRenameDelay = iewToRenameDelay;
+ params->commitToRenameDelay = commitToRenameDelay;
+ params->decodeToRenameDelay = decodeToRenameDelay;
+ params->renameWidth = renameWidth;
+
+ params->commitToIEWDelay = commitToIEWDelay;
+ params->renameToIEWDelay = renameToIEWDelay;
+ params->issueToExecuteDelay = issueToExecuteDelay;
+ params->dispatchWidth = dispatchWidth;
+ params->issueWidth = issueWidth;
+ params->wbWidth = wbWidth;
+ params->wbDepth = wbDepth;
+ params->fuPool = fuPool;
+
+ params->iewToCommitDelay = iewToCommitDelay;
+ params->renameToROBDelay = renameToROBDelay;
+ params->commitWidth = commitWidth;
+ params->squashWidth = squashWidth;
+ params->trapLatency = trapLatency;
+
+ params->backComSize = backComSize;
+ params->forwardComSize = forwardComSize;
+
+ params->predType = predType;
+ params->localPredictorSize = localPredictorSize;
+ params->localCtrBits = localCtrBits;
+ params->localHistoryTableSize = localHistoryTableSize;
+ params->localHistoryBits = localHistoryBits;
+ params->globalPredictorSize = globalPredictorSize;
+ params->globalCtrBits = globalCtrBits;
+ params->globalHistoryBits = globalHistoryBits;
+ params->choicePredictorSize = choicePredictorSize;
+ params->choiceCtrBits = choiceCtrBits;
+
+ params->BTBEntries = BTBEntries;
+ params->BTBTagSize = BTBTagSize;
+
+ params->RASSize = RASSize;
+
+ params->LQEntries = LQEntries;
+ params->SQEntries = SQEntries;
+
+ params->SSITSize = SSITSize;
+ params->LFSTSize = LFSTSize;
+
+ params->numPhysIntRegs = numPhysIntRegs;
+ params->numPhysFloatRegs = numPhysFloatRegs;
+ params->numIQEntries = numIQEntries;
+ params->numROBEntries = numROBEntries;
+
+ params->smtNumFetchingThreads = smtNumFetchingThreads;
+
+ // Default smtFetchPolicy to "RoundRobin", if necessary.
+ std::string round_robin_policy = "RoundRobin";
+ std::string single_thread = "SingleThread";
+
+ if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0)
+ params->smtFetchPolicy = round_robin_policy;
+ else
+ params->smtFetchPolicy = smtFetchPolicy;
+
+ params->smtIQPolicy = smtIQPolicy;
+ params->smtLSQPolicy = smtLSQPolicy;
+ params->smtLSQThreshold = smtLSQThreshold;
+ params->smtROBPolicy = smtROBPolicy;
+ params->smtROBThreshold = smtROBThreshold;
+ params->smtCommitPolicy = smtCommitPolicy;
+
+ params->instShiftAmt = 2;
+
+ params->deferRegistration = defer_registration;
+
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+
+ cpu = new DerivO3CPU(params);
+
+ return cpu;
+}
+
+REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU)
+
diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh
new file mode 100644
index 000000000..536a620bf
--- /dev/null
+++ b/src/cpu/o3/sparc/cpu_impl.hh
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#include "config/use_checker.hh"
+
+#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/miscregfile.hh"
+#include "base/cprintf.hh"
+#include "base/statistics.hh"
+#include "base/timebuf.hh"
+#include "cpu/checker/thread_context.hh"
+#include "sim/sim_events.hh"
+#include "sim/stats.hh"
+
+#include "cpu/o3/sparc/cpu.hh"
+#include "cpu/o3/sparc/params.hh"
+#include "cpu/o3/sparc/thread_context.hh"
+#include "cpu/o3/comm.hh"
+#include "cpu/o3/thread_state.hh"
+
+#if FULL_SYSTEM
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/kernel_stats.hh"
+#include "cpu/quiesce_event.hh"
+#include "sim/sim_exit.hh"
+#include "sim/system.hh"
+#endif
+
+template <class Impl>
+SparcO3CPU<Impl>::SparcO3CPU(Params *params)
+#if FULL_SYSTEM
+ : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
+#else
+ : FullO3CPU<Impl>(params)
+#endif
+{
+ DPRINTF(O3CPU, "Creating SparcO3CPU object.\n");
+
+ // Setup any thread state.
+ this->thread.resize(this->numThreads);
+
+ for (int i = 0; i < this->numThreads; ++i) {
+#if FULL_SYSTEM
+ // SMT is not supported in FS mode yet.
+ assert(this->numThreads == 1);
+ this->thread[i] = new Thread(this, 0);
+ this->thread[i]->setStatus(ThreadContext::Suspended);
+#else
+ if (i < params->workload.size()) {
+ DPRINTF(O3CPU, "Workload[%i] process is %#x",
+ i, this->thread[i]);
+ this->thread[i] = new Thread(this, i, params->workload[i], i);
+
+ this->thread[i]->setStatus(ThreadContext::Suspended);
+
+ //usedTids[i] = true;
+ //threadMap[i] = i;
+ } else {
+ //Allocate Empty thread so M5 can use later
+ //when scheduling threads to CPU
+ Process* dummy_proc = NULL;
+
+ this->thread[i] = new Thread(this, i, dummy_proc, i);
+ //usedTids[i] = false;
+ }
+#endif // !FULL_SYSTEM
+
+ ThreadContext *tc;
+
+ // Setup the TC that will serve as the interface to the threads/CPU.
+ SparcTC<Impl> *sparc_tc = new SparcTC<Impl>;
+
+ tc = sparc_tc;
+
+ // If we're using a checker, then the TC should be the
+ // CheckerThreadContext.
+#if USE_CHECKER
+ if (params->checker) {
+ tc = new CheckerThreadContext<SparcTC<Impl> >(
+ sparc_tc, this->checker);
+ }
+#endif
+
+ sparc_tc->cpu = this;
+ sparc_tc->thread = this->thread[i];
+
+#if FULL_SYSTEM
+ // Setup quiesce event.
+ this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
+#endif
+ // Give the thread the TC.
+ this->thread[i]->tc = tc;
+
+ // Add the TC to the CPU's list of TC's.
+ this->threadContexts.push_back(tc);
+ }
+
+ for (int i=0; i < this->numThreads; i++) {
+ this->thread[i]->setFuncExeInst(0);
+ }
+
+ // Sets CPU pointers. These must be set at this level because the CPU
+ // pointers are defined to be the highest level of CPU class.
+ this->fetch.setCPU(this);
+ this->decode.setCPU(this);
+ this->rename.setCPU(this);
+ this->iew.setCPU(this);
+ this->commit.setCPU(this);
+
+ this->rob.setCPU(this);
+ this->regFile.setCPU(this);
+
+ lockAddr = 0;
+ lockFlag = false;
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::regStats()
+{
+ // Register stats for everything that has stats.
+ this->fullCPURegStats();
+ this->fetch.regStats();
+ this->decode.regStats();
+ this->rename.regStats();
+ this->iew.regStats();
+ this->commit.regStats();
+}
+
+
+template <class Impl>
+TheISA::MiscReg
+SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
+{
+ return this->regFile.readMiscReg(misc_reg, tid);
+}
+
+template <class Impl>
+TheISA::MiscReg
+SparcO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid)
+{
+ return this->regFile.readMiscRegWithEffect(misc_reg, tid);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
+{
+ this->regFile.setMiscReg(misc_reg, val, tid);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
+ unsigned tid)
+{
+ this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::squashFromTC(unsigned tid)
+{
+ this->thread[tid]->inSyscall = true;
+ this->commit.generateTCEvent(tid);
+}
+
+#if FULL_SYSTEM
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::post_interrupt(int int_num, int index)
+{
+ BaseCPU::post_interrupt(int_num, index);
+
+ if (this->thread[0]->status() == ThreadContext::Suspended) {
+ DPRINTF(IPI,"Suspended Processor awoke\n");
+ this->threadContexts[0]->activate();
+ }
+}
+
+template <class Impl>
+Fault
+SparcO3CPU<Impl>::hwrei(unsigned tid)
+{
+ panic("This doesn't make sense for SPARC\n");
+ return NoFault;
+}
+
+template <class Impl>
+bool
+SparcO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
+{
+ panic("This doesn't make sense for SPARC\n");
+ return true;
+}
+
+template <class Impl>
+Fault
+SparcO3CPU<Impl>::getInterrupts()
+{
+ // Check if there are any outstanding interrupts
+ return this->interrupts.getInterrupt(this->threadContexts[0]);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::processInterrupts(Fault interrupt)
+{
+ // Check for interrupts here. For now can copy the code that
+ // exists within isa_fullsys_traits.hh. Also assume that thread 0
+ // is the one that handles the interrupts.
+ // @todo: Possibly consolidate the interrupt checking code.
+ // @todo: Allow other threads to handle interrupts.
+
+ assert(interrupt != NoFault);
+ this->interrupts.updateIntrInfo(this->threadContexts[0]);
+
+ DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
+ this->checkInterrupts = false;
+ this->trap(interrupt, 0);
+}
+
+#endif // FULL_SYSTEM
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::trap(Fault fault, unsigned tid)
+{
+ // Pass the thread's TC into the invoke method.
+ fault->invoke(this->threadContexts[tid]);
+}
+
+#if !FULL_SYSTEM
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::syscall(int64_t callnum, int tid)
+{
+ DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
+
+ DPRINTF(Activity,"Activity: syscall() called.\n");
+
+ // Temporarily increase this by one to account for the syscall
+ // instruction.
+ ++(this->thread[tid]->funcExeInst);
+
+ // Execute the actual syscall.
+ this->thread[tid]->syscall(callnum);
+
+ // Decrease funcExeInst by one as the normal commit will handle
+ // incrementing it.
+ --(this->thread[tid]->funcExeInst);
+}
+
+template <class Impl>
+TheISA::IntReg
+SparcO3CPU<Impl>::getSyscallArg(int i, int tid)
+{
+ return this->readArchIntReg(SparcISA::ArgumentReg0 + i, tid);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
+{
+ this->setArchIntReg(SparcISA::ArgumentReg0 + i, val, tid);
+}
+
+template <class Impl>
+void
+SparcO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
+{
+ // check for error condition. SPARC syscall convention is to
+ // indicate success/failure in reg the carry bit of the ccr
+ // and put the return value itself in the standard return value reg ().
+ if (return_value.successful()) {
+ // no error, clear XCC.C
+ this->setMiscReg(SparcISA::MISCREG_CCR,
+ this->readMiscReg(SparcISA::MISCREG_CCR, tid) & 0xEE, tid);
+ this->setArchIntReg(SparcISA::ReturnValueReg,
+ return_value.value(), tid);
+ } else {
+ // got an error, set XCC.C
+ this->setMiscReg(SparcISA::MISCREG_CCR,
+ this->readMiscReg(SparcISA::MISCREG_CCR, tid) | 0x11, tid);
+ this->setArchIntReg(SparcISA::ReturnValueReg,
+ return_value.value(), tid);
+ }
+}
+#endif
diff --git a/src/cpu/o3/sparc/dyn_inst.cc b/src/cpu/o3/sparc/dyn_inst.cc
new file mode 100644
index 000000000..984b58f4b
--- /dev/null
+++ b/src/cpu/o3/sparc/dyn_inst.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2004-2005 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: Gabe Black
+ */
+
+#include "cpu/o3/sparc/dyn_inst_impl.hh"
+#include "cpu/o3/sparc/impl.hh"
+
+// Force instantiation of SparcDynInst for all the implementations that
+// are needed.
+template class SparcDynInst<SparcSimpleImpl>;
diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh
new file mode 100644
index 000000000..f8d6bb63f
--- /dev/null
+++ b/src/cpu/o3/sparc/dyn_inst.hh
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#ifndef __CPU_O3_SPARC_DYN_INST_HH__
+#define __CPU_O3_SPARC_DYN_INST_HH__
+
+#include "arch/sparc/isa_traits.hh"
+#include "cpu/base_dyn_inst.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/o3/sparc/cpu.hh"
+#include "cpu/o3/sparc/impl.hh"
+
+class Packet;
+
+/**
+ * Mostly implementation & ISA specific SparcDynInst. As with most
+ * other classes in the new CPU model, it is templated on the Impl to
+ * allow for passing in of all types, such as the CPU type and the ISA
+ * type. The SparcDynInst serves as the primary interface to the CPU
+ * for instructions that are executing.
+ */
+template <class Impl>
+class SparcDynInst : public BaseDynInst<Impl>
+{
+ public:
+ /** Typedef for the CPU. */
+ typedef typename Impl::O3CPU O3CPU;
+
+ public:
+ /** BaseDynInst constructor given a binary instruction. */
+ SparcDynInst(TheISA::ExtMachInst inst, Addr PC,
+ Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu);
+
+ /** BaseDynInst constructor given a static inst pointer. */
+ SparcDynInst(StaticInstPtr &_staticInst);
+
+ /** Executes the instruction.*/
+ Fault execute();
+
+ /** Initiates the access. Only valid for memory operations. */
+ Fault initiateAcc();
+
+ /** Completes the access. Only valid for memory operations. */
+ Fault completeAcc(PacketPtr pkt);
+
+ private:
+ /** Initializes variables. */
+ void initVars();
+
+ public:
+ /** Reads a miscellaneous register. */
+ TheISA::MiscReg readMiscReg(int misc_reg)
+ {
+ return this->cpu->readMiscReg(misc_reg, this->threadNumber);
+ }
+
+ /** Reads a misc. register, including any side-effects the read
+ * might have as defined by the architecture.
+ */
+ TheISA::MiscReg readMiscRegWithEffect(int misc_reg)
+ {
+ return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber);
+ }
+
+ /** Sets a misc. register. */
+ void setMiscReg(int misc_reg, const TheISA::MiscReg &val)
+ {
+ this->instResult.integer = val;
+ return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
+ }
+
+ /** Sets a misc. register, including any side-effects the write
+ * might have as defined by the architecture.
+ */
+ void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val)
+ {
+ return this->cpu->setMiscRegWithEffect(misc_reg, val,
+ this->threadNumber);
+ }
+
+#if FULL_SYSTEM
+ /** Calls hardware return from error interrupt. */
+ Fault hwrei();
+ /** Traps to handle specified fault. */
+ void trap(Fault fault);
+ bool simPalCheck(int palFunc);
+#else
+ /** Calls a syscall. */
+ void syscall(int64_t callnum);
+#endif
+
+ private:
+ /** Physical register index of the destination registers of this
+ * instruction.
+ */
+ PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs];
+
+ /** Physical register index of the source registers of this
+ * instruction.
+ */
+ PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs];
+
+ /** Physical register index of the previous producers of the
+ * architected destinations.
+ */
+ PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs];
+
+ public:
+
+ // The register accessor methods provide the index of the
+ // instruction's operand (e.g., 0 or 1), not the architectural
+ // register index, to simplify the implementation of register
+ // renaming. We find the architectural register index by indexing
+ // into the instruction's own operand index table. Note that a
+ // raw pointer to the StaticInst is provided instead of a
+ // ref-counted StaticInstPtr to redice overhead. This is fine as
+ // long as these methods don't copy the pointer into any long-term
+ // storage (which is pretty hard to imagine they would have reason
+ // to do).
+
+ uint64_t readIntReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readIntReg(_srcRegIdx[idx]);
+ }
+
+ TheISA::FloatReg readFloatReg(const StaticInst *si, int idx, int width)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx], width);
+ }
+
+ TheISA::FloatReg readFloatReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx]);
+ }
+
+ TheISA::FloatRegBits readFloatRegBits(const StaticInst *si,
+ int idx, int width)
+ {
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx], width);
+ }
+
+ TheISA::FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx]);
+ }
+
+ /** @todo: Make results into arrays so they can handle multiple dest
+ * registers.
+ */
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
+ {
+ this->cpu->setIntReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setIntReg(si, idx, val);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx,
+ TheISA::FloatReg val, int width)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val, width);
+ BaseDynInst<Impl>::setFloatReg(si, idx, val, width);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, TheISA::FloatReg val)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatReg(si, idx, val);
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx,
+ TheISA::FloatRegBits val, int width)
+ {
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val, width);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
+ }
+
+ void setFloatRegBits(const StaticInst *si,
+ int idx, TheISA::FloatRegBits val)
+ {
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
+ }
+
+ /** Returns the physical register index of the i'th destination
+ * register.
+ */
+ PhysRegIndex renamedDestRegIdx(int idx) const
+ {
+ return _destRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the i'th source register. */
+ PhysRegIndex renamedSrcRegIdx(int idx) const
+ {
+ return _srcRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the previous physical register
+ * that remapped to the same logical register index.
+ */
+ PhysRegIndex prevDestRegIdx(int idx) const
+ {
+ return _prevDestRegIdx[idx];
+ }
+
+ /** Renames a destination register to a physical register. Also records
+ * the previous physical register that the logical register mapped to.
+ */
+ void renameDestReg(int idx,
+ PhysRegIndex renamed_dest,
+ PhysRegIndex previous_rename)
+ {
+ _destRegIdx[idx] = renamed_dest;
+ _prevDestRegIdx[idx] = previous_rename;
+ }
+
+ /** Renames a source logical register to the physical register which
+ * has/will produce that logical register's result.
+ * @todo: add in whether or not the source register is ready.
+ */
+ void renameSrcReg(int idx, PhysRegIndex renamed_src)
+ {
+ _srcRegIdx[idx] = renamed_src;
+ }
+
+ public:
+ /** Calculates EA part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault calcEA()
+ {
+ return this->staticInst->eaCompInst()->execute(this, this->traceData);
+ }
+
+ /** Does the memory access part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault memAccess()
+ {
+ return this->staticInst->memAccInst()->execute(this, this->traceData);
+ }
+};
+
+#endif // __CPU_O3_SPARC_DYN_INST_HH__
+
diff --git a/src/cpu/o3/sparc/dyn_inst_impl.hh b/src/cpu/o3/sparc/dyn_inst_impl.hh
new file mode 100644
index 000000000..210daace2
--- /dev/null
+++ b/src/cpu/o3/sparc/dyn_inst_impl.hh
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#include "cpu/o3/sparc/dyn_inst.hh"
+
+template <class Impl>
+SparcDynInst<Impl>::SparcDynInst(TheISA::ExtMachInst inst, Addr PC,
+ Addr Pred_PC, InstSeqNum seq_num, O3CPU *cpu)
+ : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
+{
+ initVars();
+}
+
+template <class Impl>
+SparcDynInst<Impl>::SparcDynInst(StaticInstPtr &_staticInst)
+ : BaseDynInst<Impl>(_staticInst)
+{
+ initVars();
+}
+
+template <class Impl>
+void
+SparcDynInst<Impl>::initVars()
+{
+ // Make sure to have the renamed register entries set to the same
+ // as the normal register entries. It will allow the IQ to work
+ // without any modifications.
+ for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
+ _destRegIdx[i] = this->staticInst->destRegIdx(i);
+ }
+
+ for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
+ _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
+ this->_readySrcRegIdx[i] = 0;
+ }
+}
+
+template <class Impl>
+Fault
+SparcDynInst<Impl>::execute()
+{
+ // @todo: Pretty convoluted way to avoid squashing from happening
+ // when using the TC during an instruction's execution
+ // (specifically for instructions that have side-effects that use
+ // the TC). Fix this.
+ bool in_syscall = this->thread->inSyscall;
+ this->thread->inSyscall = true;
+
+ this->fault = this->staticInst->execute(this, this->traceData);
+
+ this->thread->inSyscall = in_syscall;
+
+ return this->fault;
+}
+
+template <class Impl>
+Fault
+SparcDynInst<Impl>::initiateAcc()
+{
+ // @todo: Pretty convoluted way to avoid squashing from happening
+ // when using the TC during an instruction's execution
+ // (specifically for instructions that have side-effects that use
+ // the TC). Fix this.
+ bool in_syscall = this->thread->inSyscall;
+ this->thread->inSyscall = true;
+
+ this->fault = this->staticInst->initiateAcc(this, this->traceData);
+
+ this->thread->inSyscall = in_syscall;
+
+ return this->fault;
+}
+
+template <class Impl>
+Fault
+SparcDynInst<Impl>::completeAcc(PacketPtr pkt)
+{
+ this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
+
+ return this->fault;
+}
+
+#if FULL_SYSTEM
+template <class Impl>
+Fault
+SparcDynInst<Impl>::hwrei()
+{
+ return NoFault;
+}
+
+template <class Impl>
+void
+SparcDynInst<Impl>::trap(Fault fault)
+{
+ this->cpu->trap(fault, this->threadNumber);
+}
+
+template <class Impl>
+bool
+SparcDynInst<Impl>::simPalCheck(int palFunc)
+{
+ return this->cpu->simPalCheck(palFunc, this->threadNumber);
+}
+#else
+template <class Impl>
+void
+SparcDynInst<Impl>::syscall(int64_t callnum)
+{
+ this->cpu->syscall(callnum, this->threadNumber);
+}
+#endif
+
diff --git a/src/cpu/o3/sparc/impl.hh b/src/cpu/o3/sparc/impl.hh
new file mode 100644
index 000000000..0a970c2f0
--- /dev/null
+++ b/src/cpu/o3/sparc/impl.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2004-2005 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: Gabe Black
+ */
+
+#ifndef __CPU_O3_SPARC_IMPL_HH__
+#define __CPU_O3_SPARC_IMPL_HH__
+
+#include "arch/sparc/isa_traits.hh"
+
+#include "cpu/o3/sparc/params.hh"
+#include "cpu/o3/cpu_policy.hh"
+
+
+// Forward declarations.
+template <class Impl>
+class SparcDynInst;
+
+template <class Impl>
+class SparcO3CPU;
+
+/** Implementation specific struct that defines several key types to the
+ * CPU, the stages within the CPU, the time buffers, and the DynInst.
+ * The struct defines the ISA, the CPU policy, the specific DynInst, the
+ * specific O3CPU, and all of the structs from the time buffers to do
+ * communication.
+ * This is one of the key things that must be defined for each hardware
+ * specific CPU implementation.
+ */
+struct SparcSimpleImpl
+{
+ /** The type of MachInst. */
+ typedef TheISA::MachInst MachInst;
+
+ /** The CPU policy to be used, which defines all of the CPU stages. */
+ typedef SimpleCPUPolicy<SparcSimpleImpl> CPUPol;
+
+ /** The DynInst type to be used. */
+ typedef SparcDynInst<SparcSimpleImpl> DynInst;
+
+ /** The refcounted DynInst pointer to be used. In most cases this is
+ * what should be used, and not DynInst *.
+ */
+ typedef RefCountingPtr<DynInst> DynInstPtr;
+
+ /** The O3CPU type to be used. */
+ typedef SparcO3CPU<SparcSimpleImpl> O3CPU;
+
+ /** Same typedef, but for CPUType. BaseDynInst may not always use
+ * an O3 CPU, so it's clearer to call it CPUType instead in that
+ * case.
+ */
+ typedef O3CPU CPUType;
+
+ /** The Params to be passed to each stage. */
+ typedef SparcSimpleParams Params;
+
+ enum {
+ MaxWidth = 8,
+ MaxThreads = 4
+ };
+};
+
+/** The O3Impl to be used. */
+typedef SparcSimpleImpl O3CPUImpl;
+
+#endif // __CPU_O3_SPARC_IMPL_HH__
diff --git a/src/cpu/o3/sparc/params.hh b/src/cpu/o3/sparc/params.hh
new file mode 100644
index 000000000..d399d64c4
--- /dev/null
+++ b/src/cpu/o3/sparc/params.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#ifndef __CPU_O3_SPARC_PARAMS_HH__
+#define __CPU_O3_SPARC_PARAMS_HH__
+
+#include "cpu/o3/cpu.hh"
+#include "cpu/o3/params.hh"
+
+//Forward declarations
+namespace SparcISA
+{
+ class DTB;
+ class ITB;
+}
+class MemObject;
+class Process;
+class System;
+
+/**
+ * This file defines the parameters that will be used for the AlphaO3CPU.
+ * This must be defined externally so that the Impl can have a params class
+ * defined that it can pass to all of the individual stages.
+ */
+
+class SparcSimpleParams : public O3Params
+{
+ public:
+
+#if FULL_SYSTEM
+ SparcISA::ITB *itb;
+ SparcISA::DTB *dtb;
+#endif
+};
+
+#endif // __CPU_O3_SPARC_PARAMS_HH__
diff --git a/src/cpu/o3/sparc/thread_context.cc b/src/cpu/o3/sparc/thread_context.cc
new file mode 100755
index 000000000..d85aff502
--- /dev/null
+++ b/src/cpu/o3/sparc/thread_context.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#include "cpu/o3/thread_context.hh"
+#include "cpu/o3/thread_context_impl.hh"
+
+template class O3ThreadContext<SparcSimpleImpl>;
+
diff --git a/src/cpu/o3/sparc/thread_context.hh b/src/cpu/o3/sparc/thread_context.hh
new file mode 100644
index 000000000..69d1e2d04
--- /dev/null
+++ b/src/cpu/o3/sparc/thread_context.hh
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2004-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: Gabe Black
+ */
+
+#include "arch/sparc/types.hh"
+#include "cpu/o3/thread_context.hh"
+
+template <class Impl>
+class SparcTC : public O3ThreadContext<Impl>
+{
+ public:
+#if FULL_SYSTEM
+ /** Returns a pointer to the ITB. */
+ virtual SparcISA::ITB *getITBPtr() { return this->cpu->itb; }
+
+ /** Returns a pointer to the DTB. */
+ virtual SparcISA::DTB *getDTBPtr() { return this->cpu->dtb; }
+
+ /** Returns pointer to the quiesce event. */
+ virtual EndQuiesceEvent *getQuiesceEvent()
+ {
+ return this->thread->quiesceEvent;
+ }
+#endif
+
+ virtual uint64_t readNextNPC()
+ {
+ return this->cpu->readNextNPC(this->thread->readTid());
+ }
+
+ virtual void setNextNPC(uint64_t val)
+ {
+ this->cpu->setNextNPC(val, this->thread->readTid());
+ }
+
+ virtual void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
+ {
+ panic("This doesn't make sense!\n");
+ }
+
+
+ /** This function exits the thread context in the CPU and returns
+ * 1 if the CPU has no more active threads (meaning it's OK to exit);
+ * Used in syscall-emulation mode when a thread executes the 'exit'
+ * syscall.
+ */
+ virtual int exit()
+ {
+ this->deallocate();
+
+ // If there are still threads executing in the system
+ if (this->cpu->numActiveThreads())
+ return 0; // don't exit simulation
+ else
+ return 1; // exit simulation
+ }
+};
diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh
index e09e4de9c..0acf99ead 100644
--- a/src/cpu/ozone/front_end.hh
+++ b/src/cpu/ozone/front_end.hh
@@ -92,7 +92,7 @@ class FrontEnd
/** Returns the address ranges of this device. */
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
/** Timing version of receive. Handles setting fetch to the
* proper status to start fetching. */
diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh
index 7e6849668..c981b8e63 100644
--- a/src/cpu/ozone/lw_lsq.hh
+++ b/src/cpu/ozone/lw_lsq.hh
@@ -258,7 +258,7 @@ class OzoneLWLSQ {
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
virtual bool recvTiming(PacketPtr pkt);
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 8cfe2ee83..8db864153 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -29,6 +29,7 @@
*/
#include "arch/locked_mem.hh"
+#include "arch/mmaped_ipr.hh"
#include "arch/utility.hh"
#include "cpu/exetrace.hh"
#include "cpu/simple/atomic.hh"
@@ -289,10 +290,16 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
if (fault == NoFault) {
pkt->reinitFromRequest();
- dcache_latency = dcachePort.sendAtomic(pkt);
+ if (req->isMmapedIpr())
+ dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt);
+ else
+ dcache_latency = dcachePort.sendAtomic(pkt);
dcache_access = true;
-
- assert(pkt->result == Packet::Success);
+#if !defined(NDEBUG)
+ if (pkt->result != Packet::Success)
+ panic("Unable to find responder for address pa = %#X va = %#X\n",
+ pkt->req->getPaddr(), pkt->req->getVaddr());
+#endif
data = pkt->get<T>();
if (req->isLocked()) {
@@ -376,14 +383,22 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
}
if (do_access) {
- data = htog(data);
pkt->reinitFromRequest();
pkt->dataStatic(&data);
- dcache_latency = dcachePort.sendAtomic(pkt);
+ if (req->isMmapedIpr()) {
+ dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt);
+ } else {
+ data = htog(data);
+ dcache_latency = dcachePort.sendAtomic(pkt);
+ }
dcache_access = true;
- assert(pkt->result == Packet::Success);
+#if !defined(NDEBUG)
+ if (pkt->result != Packet::Success)
+ panic("Unable to find responder for address pa = %#X va = %#X\n",
+ pkt->req->getPaddr(), pkt->req->getVaddr());
+#endif
}
if (req->isLocked()) {
@@ -476,9 +491,15 @@ AtomicSimpleCPU::tick()
dcache_access = false; // assume no dcache access
preExecute();
+
fault = curStaticInst->execute(this, traceData);
postExecute();
+ // @todo remove me after debugging with legion done
+ if (curStaticInst && (!curStaticInst->isMicroOp() ||
+ curStaticInst->isLastMicroOp()))
+ instCnt++;
+
if (simulate_stalls) {
Tick icache_stall = icache_latency - cycles(1);
Tick dcache_stall =
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index 0df6fe079..42c7bf23a 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -106,7 +106,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
};
CpuPort icachePort;
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index fe5d03666..abcb224bf 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -94,7 +94,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
+ { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); }
struct TickEvent : public Event
{
diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc
index 924e1d462..eb51d4e49 100644
--- a/src/dev/alpha/tsunami_cchip.cc
+++ b/src/dev/alpha/tsunami_cchip.cc
@@ -57,7 +57,7 @@ using namespace TheISA;
TsunamiCChip::TsunamiCChip(Params *p)
: BasicPioDevice(p), tsunami(p->tsunami)
{
- pioSize = 0xfffffff;
+ pioSize = 0x10000000;
drir = 0;
ipint = 0;
diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc
index def214a95..8430856ef 100644
--- a/src/dev/alpha/tsunami_io.cc
+++ b/src/dev/alpha/tsunami_io.cc
@@ -430,7 +430,7 @@ TsunamiIO::TsunamiIO(Params *p)
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
rtc(p->name + ".rtc", p->tsunami, p->frequency)
{
- pioSize = 0xff;
+ pioSize = 0x100;
// set the back pointer from tsunami to myself
tsunami->io = this;
diff --git a/src/dev/alpha/tsunami_pchip.cc b/src/dev/alpha/tsunami_pchip.cc
index 94a7f96e5..f30199337 100644
--- a/src/dev/alpha/tsunami_pchip.cc
+++ b/src/dev/alpha/tsunami_pchip.cc
@@ -53,7 +53,7 @@ using namespace TheISA;
TsunamiPChip::TsunamiPChip(Params *p)
: BasicPioDevice(p)
{
- pioSize = 0xfff;
+ pioSize = 0x1000;
for (int i = 0; i < 4; i++) {
wsba[i] = 0;
diff --git a/src/dev/baddev.cc b/src/dev/baddev.cc
index 1bab93492..6a7060455 100644
--- a/src/dev/baddev.cc
+++ b/src/dev/baddev.cc
@@ -49,7 +49,7 @@ using namespace TheISA;
BadDevice::BadDevice(Params *p)
: BasicPioDevice(p), devname(p->device_name)
{
- pioSize = 0xf;
+ pioSize = 0x10;
}
Tick
diff --git a/src/dev/isa_fake.cc b/src/dev/isa_fake.cc
index 40909c6a1..c36ddeb83 100644
--- a/src/dev/isa_fake.cc
+++ b/src/dev/isa_fake.cc
@@ -47,7 +47,10 @@ IsaFake::IsaFake(Params *p)
if (!params()->retBadAddr)
pioSize = p->pio_size;
- memset(&retData, p->retData, sizeof(retData));
+ retData8 = params()->retData8;
+ retData16 = params()->retData16;
+ retData32 = params()->retData32;
+ retData64 = params()->retData64;
}
Tick
@@ -55,6 +58,9 @@ IsaFake::read(PacketPtr pkt)
{
assert(pkt->result == Packet::Unknown);
+ if (params()->warnAccess != "")
+ warn("Device %s accessed by read to address %#x size=%d\n",
+ name(), pkt->getAddr(), pkt->getSize());
if (params()->retBadAddr) {
DPRINTF(Tsunami, "read to bad address va=%#x size=%d\n",
pkt->getAddr(), pkt->getSize());
@@ -65,16 +71,16 @@ IsaFake::read(PacketPtr pkt)
pkt->getAddr(), pkt->getSize());
switch (pkt->getSize()) {
case sizeof(uint64_t):
- pkt->set(retData);
+ pkt->set(retData64);
break;
case sizeof(uint32_t):
- pkt->set((uint32_t)retData);
+ pkt->set(retData32);
break;
case sizeof(uint16_t):
- pkt->set((uint16_t)retData);
+ pkt->set(retData16);
break;
case sizeof(uint8_t):
- pkt->set((uint8_t)retData);
+ pkt->set(retData8);
break;
default:
panic("invalid access size!\n");
@@ -87,6 +93,27 @@ IsaFake::read(PacketPtr pkt)
Tick
IsaFake::write(PacketPtr pkt)
{
+ if (params()->warnAccess != "") {
+ uint64_t data;
+ switch (pkt->getSize()) {
+ case sizeof(uint64_t):
+ data = pkt->get<uint64_t>();
+ break;
+ case sizeof(uint32_t):
+ data = pkt->get<uint32_t>();
+ break;
+ case sizeof(uint16_t):
+ data = pkt->get<uint16_t>();
+ break;
+ case sizeof(uint8_t):
+ data = pkt->get<uint8_t>();
+ break;
+ default:
+ panic("invalid access size!\n");
+ }
+ warn("Device %s accessed by write to address %#x size=%d data=%#x\n",
+ name(), pkt->getAddr(), pkt->getSize(), data);
+ }
if (params()->retBadAddr) {
DPRINTF(Tsunami, "write to bad address va=%#x size=%d \n",
pkt->getAddr(), pkt->getSize());
@@ -94,6 +121,25 @@ IsaFake::write(PacketPtr pkt)
} else {
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
pkt->getAddr(), pkt->getSize());
+
+ if (params()->updateData) {
+ switch (pkt->getSize()) {
+ case sizeof(uint64_t):
+ retData64 = pkt->get<uint64_t>();
+ break;
+ case sizeof(uint32_t):
+ retData32 = pkt->get<uint32_t>();
+ break;
+ case sizeof(uint16_t):
+ retData16 = pkt->get<uint16_t>();
+ break;
+ case sizeof(uint8_t):
+ retData8 = pkt->get<uint8_t>();
+ break;
+ default:
+ panic("invalid access size!\n");
+ }
+ }
pkt->result = Packet::Success;
}
return pioDelay;
@@ -105,7 +151,12 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
Param<Tick> pio_latency;
Param<Addr> pio_size;
Param<bool> ret_bad_addr;
- Param<uint8_t> ret_data;
+ Param<bool> update_data;
+ Param<std::string> warn_access;
+ Param<uint8_t> ret_data8;
+ Param<uint16_t> ret_data16;
+ Param<uint32_t> ret_data32;
+ Param<uint64_t> ret_data64;
SimObjectParam<Platform *> platform;
SimObjectParam<System *> system;
@@ -117,7 +168,12 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake)
INIT_PARAM(pio_latency, "Programmed IO latency"),
INIT_PARAM(pio_size, "Size of address range"),
INIT_PARAM(ret_bad_addr, "Return pkt status BadAddr"),
- INIT_PARAM(ret_data, "Data to return if not bad addr"),
+ INIT_PARAM(update_data, "Update returned data"),
+ INIT_PARAM(warn_access, "Warn if this device is touched"),
+ INIT_PARAM(ret_data8, "Data to return if not bad addr"),
+ INIT_PARAM(ret_data16, "Data to return if not bad addr"),
+ INIT_PARAM(ret_data32, "Data to return if not bad addr"),
+ INIT_PARAM(ret_data64, "Data to return if not bad addr"),
INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object")
@@ -131,7 +187,12 @@ CREATE_SIM_OBJECT(IsaFake)
p->pio_delay = pio_latency;
p->pio_size = pio_size;
p->retBadAddr = ret_bad_addr;
- p->retData = ret_data;
+ p->updateData = update_data;
+ p->warnAccess = warn_access;
+ p->retData8= ret_data8;
+ p->retData16 = ret_data16;
+ p->retData32 = ret_data32;
+ p->retData64 = ret_data64;
p->platform = platform;
p->system = system;
return new IsaFake(p);
diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh
index fee41e325..dc2ad48e8 100644
--- a/src/dev/isa_fake.hh
+++ b/src/dev/isa_fake.hh
@@ -40,6 +40,8 @@
#include "dev/alpha/tsunami.hh"
#include "mem/packet.hh"
+#include <string>
+
/**
* IsaFake is a device that returns, BadAddr, 1 or 0 on all reads and
* rites. It is meant to be placed at an address range
@@ -54,11 +56,20 @@ class IsaFake : public BasicPioDevice
{
Addr pio_size;
bool retBadAddr;
- uint8_t retData;
+ bool updateData;
+ uint8_t retData8;
+ uint16_t retData16;
+ uint32_t retData32;
+ uint64_t retData64;
+ std::string warnAccess;
};
protected:
const Params *params() const { return (const Params*)_params; }
- uint64_t retData;
+ uint8_t retData8;
+ uint16_t retData16;
+ uint32_t retData32;
+ uint64_t retData64;
+
public:
/**
diff --git a/src/dev/sparc/SConscript b/src/dev/sparc/SConscript
index 701e533a8..c37294f0c 100644
--- a/src/dev/sparc/SConscript
+++ b/src/dev/sparc/SConscript
@@ -37,6 +37,7 @@ Import('env')
sources = []
sources += Split('''
+ t1000.cc
''')
# Convert file names to SCons File objects. This takes care of the
diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc
new file mode 100644
index 000000000..4a8de77a5
--- /dev/null
+++ b/src/dev/sparc/t1000.cc
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2004-2005 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
+ */
+
+/** @file
+ * Implementation of T1000 platform.
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "cpu/intr_control.hh"
+#include "dev/simconsole.hh"
+#include "dev/sparc/t1000.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
+
+T1000::T1000(const string &name, System *s, IntrControl *ic)
+ : Platform(name, ic), system(s)
+{
+ // set the back pointer from the system to myself
+ system->platform = this;
+}
+
+Tick
+T1000::intrFrequency()
+{
+ panic("Need implementation\n");
+}
+
+void
+T1000::postConsoleInt()
+{
+ warn_once("Don't know what interrupt to post for console.\n");
+ //panic("Need implementation\n");
+}
+
+void
+T1000::clearConsoleInt()
+{
+ warn_once("Don't know what interrupt to clear for console.\n");
+ //panic("Need implementation\n");
+}
+
+void
+T1000::postPciInt(int line)
+{
+ panic("Need implementation\n");
+}
+
+void
+T1000::clearPciInt(int line)
+{
+ panic("Need implementation\n");
+}
+
+Addr
+T1000::pciToDma(Addr pciAddr) const
+{
+ panic("Need implementation\n");
+}
+
+
+Addr
+T1000::calcConfigAddr(int bus, int dev, int func)
+{
+ panic("Need implementation\n");
+}
+
+void
+T1000::serialize(std::ostream &os)
+{
+ panic("Need implementation\n");
+}
+
+void
+T1000::unserialize(Checkpoint *cp, const std::string &section)
+{
+ panic("Need implementation\n");
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(T1000)
+
+ SimObjectParam<System *> system;
+ SimObjectParam<IntrControl *> intrctrl;
+
+END_DECLARE_SIM_OBJECT_PARAMS(T1000)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(T1000)
+
+ INIT_PARAM(system, "system"),
+ INIT_PARAM(intrctrl, "interrupt controller")
+
+END_INIT_SIM_OBJECT_PARAMS(T1000)
+
+CREATE_SIM_OBJECT(T1000)
+{
+ return new T1000(getInstanceName(), system, intrctrl);
+}
+
+REGISTER_SIM_OBJECT("T1000", T1000)
diff --git a/src/dev/sparc/t1000.hh b/src/dev/sparc/t1000.hh
new file mode 100644
index 000000000..2955763a9
--- /dev/null
+++ b/src/dev/sparc/t1000.hh
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2004-2005 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
+ */
+
+/**
+ * @file
+ * Declaration of top level class for the T1000 platform chips. This class just
+ * retains pointers to all its children so the children can communicate.
+ */
+
+#ifndef __DEV_T1000_HH__
+#define __DEV_T1000_HH__
+
+#include "dev/platform.hh"
+
+class IdeController;
+class System;
+
+class T1000 : public Platform
+{
+ public:
+ /** Pointer to the system */
+ System *system;
+
+ public:
+ /**
+ * Constructor for the Tsunami Class.
+ * @param name name of the object
+ * @param s system the object belongs to
+ * @param intctrl pointer to the interrupt controller
+ */
+ T1000(const std::string &name, System *s, IntrControl *intctrl);
+
+ /**
+ * Return the interrupting frequency to AlphaAccess
+ * @return frequency of RTC interrupts
+ */
+ virtual Tick intrFrequency();
+
+ /**
+ * Cause the cpu to post a serial interrupt to the CPU.
+ */
+ virtual void postConsoleInt();
+
+ /**
+ * Clear a posted CPU interrupt
+ */
+ virtual void clearConsoleInt();
+
+ /**
+ * Cause the chipset to post a cpi interrupt to the CPU.
+ */
+ virtual void postPciInt(int line);
+
+ /**
+ * Clear a posted PCI->CPU interrupt
+ */
+ virtual void clearPciInt(int line);
+
+
+ virtual Addr pciToDma(Addr pciAddr) const;
+
+ /**
+ * Calculate the configuration address given a bus/dev/func.
+ */
+ virtual Addr calcConfigAddr(int bus, int dev, int func);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __DEV_T1000_HH__
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/mem/physical.cc b/src/mem/physical.cc
index 94f60ad80..6610e547d 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -65,6 +65,10 @@ PhysicalMemory::PhysicalMemory(Params *p)
fatal("Could not mmap!\n");
}
+ //If requested, initialize all the memory to 0
+ if(params()->zero)
+ memset(pmemAddr, 0, params()->addrRange.size());
+
pagePtr = 0;
}
@@ -191,7 +195,7 @@ PhysicalMemory::checkLockedAddrList(Request *req)
void
PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
{
- assert(pkt->getAddr() + pkt->getSize() > params()->addrRange.start &&
+ assert(pkt->getAddr() >= params()->addrRange.start &&
pkt->getAddr() + pkt->getSize() <= params()->addrRange.start +
params()->addrRange.size());
@@ -432,6 +436,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
Param<string> file;
Param<Range<Addr> > range;
Param<Tick> latency;
+ Param<bool> zero;
END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
@@ -439,7 +444,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
INIT_PARAM_DFLT(file, "memory mapped file", ""),
INIT_PARAM(range, "Device Address Range"),
- INIT_PARAM(latency, "Memory access latency")
+ INIT_PARAM(latency, "Memory access latency"),
+ INIT_PARAM(zero, "Zero initialize memory")
END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
@@ -449,6 +455,7 @@ CREATE_SIM_OBJECT(PhysicalMemory)
p->name = getInstanceName();
p->addrRange = range;
p->latency = latency;
+ p->zero = zero;
return new PhysicalMemory(p);
}
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 045e61612..af88bcaa0 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -154,6 +154,7 @@ class PhysicalMemory : public MemObject
std::string name;
Range<Addr> addrRange;
Tick latency;
+ bool zero;
};
protected:
diff --git a/src/mem/request.hh b/src/mem/request.hh
index e54984fcd..de0512e1c 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -49,26 +49,28 @@ class Request;
typedef Request* RequestPtr;
+/** ASI information for this request if it exsits. */
+const uint32_t ASI_BITS = 0x000FF;
/** The request is a Load locked/store conditional. */
-const unsigned LOCKED = 0x001;
+const uint32_t LOCKED = 0x00100;
/** The virtual address is also the physical address. */
-const unsigned PHYSICAL = 0x002;
+const uint32_t PHYSICAL = 0x00200;
/** The request is an ALPHA VPTE pal access (hw_ld). */
-const unsigned VPTE = 0x004;
+const uint32_t VPTE = 0x00400;
/** Use the alternate mode bits in ALPHA. */
-const unsigned ALTMODE = 0x008;
+const uint32_t ALTMODE = 0x00800;
/** The request is to an uncacheable address. */
-const unsigned UNCACHEABLE = 0x010;
+const uint32_t UNCACHEABLE = 0x01000;
/** The request should not cause a page fault. */
-const unsigned NO_FAULT = 0x020;
+const uint32_t NO_FAULT = 0x02000;
/** The request should be prefetched into the exclusive state. */
-const unsigned PF_EXCLUSIVE = 0x100;
+const uint32_t PF_EXCLUSIVE = 0x10000;
/** The request should be marked as LRU. */
-const unsigned EVICT_NEXT = 0x200;
+const uint32_t EVICT_NEXT = 0x20000;
/** The request should ignore unaligned access faults */
-const unsigned NO_ALIGN_FAULT = 0x400;
+const uint32_t NO_ALIGN_FAULT = 0x40000;
/** The request was an instruction read. */
-const unsigned INST_READ = 0x800;
+const uint32_t INST_READ = 0x80000;
class Request
{
@@ -95,6 +97,10 @@ class Request
/** The address space ID. */
int asid;
+
+ /** This request is to a memory mapped register. */
+ bool mmapedIpr;
+
/** The virtual address of the request. */
Addr vaddr;
@@ -164,6 +170,7 @@ class Request
validAsidVaddr = false;
validPC = false;
validScResult = false;
+ mmapedIpr = false;
}
/**
@@ -181,6 +188,7 @@ class Request
validAsidVaddr = true;
validPC = true;
validScResult = false;
+ mmapedIpr = false;
}
/** Set just the physical address. This should only be used to
@@ -215,6 +223,19 @@ class Request
/** Accessor function for asid.*/
int getAsid() { assert(validAsidVaddr); return asid; }
+ /** Accessor function for asi.*/
+ uint8_t getAsi() { assert(validAsidVaddr); return flags & ASI_BITS; }
+
+ /** Accessor function for asi.*/
+ void setAsi(uint8_t a)
+ { assert(validAsidVaddr); flags = (flags & ~ASI_BITS) | a; }
+
+ /** Accessor function for asi.*/
+ bool isMmapedIpr() { assert(validPaddr); return mmapedIpr; }
+
+ /** Accessor function for asi.*/
+ void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; }
+
/** Accessor function to check if sc result is valid. */
bool scResultValid() { return validScResult; }
/** Accessor function for store conditional return value.*/
diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py
index e7019f3ac..8226fe8d2 100644
--- a/src/python/m5/objects/Bus.py
+++ b/src/python/m5/objects/Bus.py
@@ -2,7 +2,7 @@ from m5 import build_env
from m5.params import *
from m5.proxy import *
from MemObject import MemObject
-from Tsunami import BadAddr
+from Device import BadAddr
class Bus(MemObject):
type = 'Bus'
@@ -12,7 +12,7 @@ class Bus(MemObject):
width = Param.Int(64, "bus width (bytes)")
responder_set = Param.Bool(False, "Did the user specify a default responder.")
if build_env['FULL_SYSTEM']:
- default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.")
responder = BadAddr(pio_addr=0x0, pio_latency="1ps")
+ default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.")
else:
default = Port("Default port for requests that aren't handled by a device.")
diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py
index 4672d1065..f4b873a60 100644
--- a/src/python/m5/objects/Device.py
+++ b/src/python/m5/objects/Device.py
@@ -19,3 +19,19 @@ class DmaDevice(PioDevice):
type = 'DmaDevice'
abstract = True
dma = Port(Self.pio.peerObj.port, "DMA port")
+
+class IsaFake(BasicPioDevice):
+ type = 'IsaFake'
+ pio_size = Param.Addr(0x8, "Size of address range")
+ ret_data8 = Param.UInt8(0xFF, "Default data to return")
+ ret_data16 = Param.UInt16(0xFFFF, "Default data to return")
+ ret_data32 = Param.UInt32(0xFFFFFFFF, "Default data to return")
+ ret_data64 = Param.UInt64(0xFFFFFFFFFFFFFFFF, "Default data to return")
+ ret_bad_addr = Param.Bool(False, "Return pkt status bad address on access")
+ update_data = Param.Bool(False, "Update the data that is returned on writes")
+ warn_access = Param.String("", "String to print when device is accessed")
+
+class BadAddr(IsaFake):
+ ret_bad_addr = Param.Bool(True, "Return pkt status bad address on access")
+
+
diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py
index 4e097543d..b8df6229e 100644
--- a/src/python/m5/objects/PhysicalMemory.py
+++ b/src/python/m5/objects/PhysicalMemory.py
@@ -9,6 +9,7 @@ class PhysicalMemory(MemObject):
range = Param.AddrRange(AddrRange('128MB'), "Device Address")
file = Param.String('', "memory mapped file")
latency = Param.Latency(Parent.clock, "latency of an access")
+ zero = Param.Bool(False, "zero initialize memory")
class DRAMMemory(PhysicalMemory):
type = 'DRAMMemory'
diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py
index 908c3d4ad..810a320be 100644
--- a/src/python/m5/objects/System.py
+++ b/src/python/m5/objects/System.py
@@ -15,7 +15,7 @@ class System(SimObject):
"boot processor frequency")
init_param = Param.UInt64(0, "numerical value to pass into simulator")
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
- kernel = Param.String("file that contains the kernel code")
+ kernel = Param.String("", "file that contains the kernel code")
readfile = Param.String("", "file to read startup script from")
symbolfile = Param.String("", "file to get the symbols from")
@@ -29,17 +29,40 @@ class AlphaSystem(System):
class SparcSystem(System):
type = 'SparcSystem'
_rom_base = 0xfff0000000
+ _nvram_base = 0x1f11000000
+ _hypervisor_desc_base = 0x1f12080000
+ _partition_desc_base = 0x1f12000000
# ROM for OBP/Reset/Hypervisor
rom = Param.PhysicalMemory(PhysicalMemory(range = AddrRange(_rom_base, size = '8MB')),
"Memory to hold the ROM data")
+ # nvram
+ nvram = Param.PhysicalMemory(
+ PhysicalMemory(range = AddrRange(_nvram_base, size = '8kB')),
+ "Memory to hold the nvram data")
+ # hypervisor description
+ hypervisor_desc = Param.PhysicalMemory(
+ PhysicalMemory(range = AddrRange(_hypervisor_desc_base, size = '8kB')),
+ "Memory to hold the hypervisor description")
+ # partition description
+ partition_desc = Param.PhysicalMemory(
+ PhysicalMemory(range = AddrRange(_partition_desc_base, size = '8kB')),
+ "Memory to hold the partition description")
reset_addr = Param.Addr(_rom_base, "Address to load ROM at")
hypervisor_addr = Param.Addr(Addr('64kB') + _rom_base,
"Address to load hypervisor at")
openboot_addr = Param.Addr(Addr('512kB') + _rom_base,
"Address to load openboot at")
+ nvram_addr = Param.Addr(_nvram_base, "Address to put the nvram")
+ hypervisor_desc_addr = Param.Addr(_hypervisor_desc_base,
+ "Address for the hypervisor description")
+ partition_desc_addr = Param.Addr(_partition_desc_base,
+ "Address for the partition description")
reset_bin = Param.String("file that contains the reset code")
hypervisor_bin = Param.String("file that contains the hypervisor code")
openboot_bin = Param.String("file that contains the openboot code")
+ nvram_bin = Param.String("file that contains the contents of nvram")
+ hypervisor_desc_bin = Param.String("file that contains the hypervisor description")
+ partition_desc_bin = Param.String("file that contains the partition description")
diff --git a/src/python/m5/objects/T1000.py b/src/python/m5/objects/T1000.py
new file mode 100644
index 000000000..79195d976
--- /dev/null
+++ b/src/python/m5/objects/T1000.py
@@ -0,0 +1,82 @@
+from m5.params import *
+from m5.proxy import *
+from Device import BasicPioDevice, IsaFake, BadAddr
+from Uart import Uart8250
+from Platform import Platform
+from SimConsole import SimConsole, ConsoleListener
+
+class T1000(Platform):
+ type = 'T1000'
+ system = Param.System(Parent.any, "system")
+
+ fake_clk = IsaFake(pio_addr=0x9600000000, pio_size=0x100000000,
+ warn_access="Accessing Clock Unit -- Unimplemented!")
+
+ fake_membnks = IsaFake(pio_addr=0x9700000000, pio_size=16384,
+ ret_data64=0x0000000000000000, update_data=False,
+ warn_access="Accessing Memory Banks -- Unimplemented!")
+
+ fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000,
+ warn_access="Accessing IOB -- Unimplemented!")
+
+ fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000,
+ warn_access="Accessing JBI -- Unimplemented!")
+
+ fake_l2_1 = IsaFake(pio_addr=0xA900000000, pio_size=0x8,
+ ret_data64=0x0000000000000001, update_data=True,
+ warn_access="Accessing L2 Cache Banks -- Unimplemented!")
+
+ fake_l2_2 = IsaFake(pio_addr=0xA900000040, pio_size=0x8,
+ ret_data64=0x0000000000000001, update_data=True,
+ warn_access="Accessing L2 Cache Banks -- Unimplemented!")
+
+ fake_l2_3 = IsaFake(pio_addr=0xA900000080, pio_size=0x8,
+ ret_data64=0x0000000000000001, update_data=True,
+ warn_access="Accessing L2 Cache Banks -- Unimplemented!")
+
+ fake_l2_4 = IsaFake(pio_addr=0xA9000000C0, pio_size=0x8,
+ ret_data64=0x0000000000000001, update_data=True,
+ warn_access="Accessing L2 Cache Banks -- Unimplemented!")
+
+ fake_l2esr_1 = IsaFake(pio_addr=0xAB00000000, pio_size=0x8,
+ ret_data64=0x0000000000000000, update_data=True,
+ warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!")
+
+ fake_l2esr_2 = IsaFake(pio_addr=0xAB00000040, pio_size=0x8,
+ ret_data64=0x0000000000000000, update_data=True,
+ warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!")
+
+ fake_l2esr_3 = IsaFake(pio_addr=0xAB00000080, pio_size=0x8,
+ ret_data64=0x0000000000000000, update_data=True,
+ warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!")
+
+ fake_l2esr_4 = IsaFake(pio_addr=0xAB000000C0, pio_size=0x8,
+ ret_data64=0x0000000000000000, update_data=True,
+ warn_access="Accessing L2 ESR Cache Banks -- Unimplemented!")
+
+ fake_ssi = IsaFake(pio_addr=0xff00000000, pio_size=0x10000000,
+ warn_access="Accessing SSI -- Unimplemented!")
+
+ hvuart = Uart8250(pio_addr=0xfff0c2c000)
+ puart0 = Uart8250(pio_addr=0x1f10000000)
+ console = SimConsole(listener = ConsoleListener())
+
+ # Attach I/O devices to specified bus object. Can't do this
+ # earlier, since the bus object itself is typically defined at the
+ # System level.
+ def attachIO(self, bus):
+ self.fake_clk.pio = bus.port
+ self.fake_membnks.pio = bus.port
+ self.fake_iob.pio = bus.port
+ self.fake_jbi.pio = bus.port
+ self.fake_l2_1.pio = bus.port
+ self.fake_l2_2.pio = bus.port
+ self.fake_l2_3.pio = bus.port
+ self.fake_l2_4.pio = bus.port
+ self.fake_l2esr_1.pio = bus.port
+ self.fake_l2esr_2.pio = bus.port
+ self.fake_l2esr_3.pio = bus.port
+ self.fake_l2esr_4.pio = bus.port
+ self.fake_ssi.pio = bus.port
+ self.puart0.pio = bus.port
+ self.hvuart.pio = bus.port
diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py
index ffe93727b..ac9020b47 100644
--- a/src/python/m5/objects/Tsunami.py
+++ b/src/python/m5/objects/Tsunami.py
@@ -1,6 +1,6 @@
from m5.params import *
from m5.proxy import *
-from Device import BasicPioDevice
+from Device import BasicPioDevice, IsaFake, BadAddr
from Platform import Platform
from AlphaConsole import AlphaConsole
from Uart import Uart8250
@@ -11,15 +11,6 @@ class TsunamiCChip(BasicPioDevice):
type = 'TsunamiCChip'
tsunami = Param.Tsunami(Parent.any, "Tsunami")
-class IsaFake(BasicPioDevice):
- type = 'IsaFake'
- pio_size = Param.Addr(0x8, "Size of address range")
- ret_data = Param.UInt8(0xFF, "Default data to return")
- ret_bad_addr = Param.Bool(False, "Return pkt status bad address on access")
-
-class BadAddr(IsaFake):
- ret_bad_addr = Param.Bool(True, "Return pkt status bad address on access")
-
class TsunamiIO(BasicPioDevice):
type = 'TsunamiIO'
time = Param.UInt64(1136073600,
@@ -45,7 +36,7 @@ class Tsunami(Platform):
fake_uart3 = IsaFake(pio_addr=0x801fc0002e8)
fake_uart4 = IsaFake(pio_addr=0x801fc0003f0)
- fake_ppc = IsaFake(pio_addr=0x801fc0003bc)
+ fake_ppc = IsaFake(pio_addr=0x801fc0003bb)
fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000)
diff --git a/src/sim/host.hh b/src/sim/host.hh
index a2faa206b..8b1ddbfe7 100644
--- a/src/sim/host.hh
+++ b/src/sim/host.hh
@@ -42,7 +42,7 @@
/** uint64_t constant */
#define ULL(N) ((uint64_t)N##ULL)
/** int64_t constant */
-#define LL(N) (((int64_t)N##LL)
+#define LL(N) ((int64_t)N##LL)
/** Statistics counter type. Not much excuse for not using a 64-bit
* integer here, but if you're desperate and only run short
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 4b42d41fc..b3ba1b8f1 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -89,36 +89,41 @@ System::System(Params *p)
/**
* Load the kernel code into memory
*/
- // Load kernel code
- kernel = createObjectFile(params()->kernel_path);
- if (kernel == NULL)
- fatal("Could not load kernel file %s", params()->kernel_path);
-
- // Load program sections into memory
- kernel->loadSections(&functionalPort, LoadAddrMask);
-
- // setup entry points
- kernelStart = kernel->textBase();
- kernelEnd = kernel->bssBase() + kernel->bssSize();
- kernelEntry = kernel->entryPoint();
-
- // load symbols
- if (!kernel->loadGlobalSymbols(kernelSymtab))
- panic("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(kernelSymtab))
- panic("could not load kernel local symbols\n");
-
- if (!kernel->loadGlobalSymbols(debugSymbolTable))
- panic("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(debugSymbolTable))
- panic("could not load kernel local symbols\n");
-
- DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
- DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
- DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
- DPRINTF(Loader, "Kernel loaded...\n");
+ if (params()->kernel_path == "") {
+ warn("No kernel set for full system simulation. Assuming you know what"
+ " you're doing...\n");
+ } else {
+ // Load kernel code
+ kernel = createObjectFile(params()->kernel_path);
+ if (kernel == NULL)
+ fatal("Could not load kernel file %s", params()->kernel_path);
+
+ // Load program sections into memory
+ kernel->loadSections(&functionalPort, LoadAddrMask);
+
+ // setup entry points
+ kernelStart = kernel->textBase();
+ kernelEnd = kernel->bssBase() + kernel->bssSize();
+ kernelEntry = kernel->entryPoint();
+
+ // load symbols
+ if (!kernel->loadGlobalSymbols(kernelSymtab))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(kernelSymtab))
+ panic("could not load kernel local symbols\n");
+
+ if (!kernel->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(debugSymbolTable))
+ panic("could not load kernel local symbols\n");
+
+ DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+ DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
+ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+ DPRINTF(Loader, "Kernel loaded...\n");
+ }
#endif // FULL_SYSTEM
// increment the number of running systms
diff --git a/src/unittest/rangemaptest.cc b/src/unittest/rangemaptest.cc
new file mode 100644
index 000000000..983a41520
--- /dev/null
+++ b/src/unittest/rangemaptest.cc
@@ -0,0 +1,74 @@
+/*
+ * 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_map<Addr,int> r;
+
+ range_map<Addr,int>::iterator i;
+
+ i = r.insert(RangeIn<Addr>(10,40),5);
+ assert(i != r.end());
+ i = r.insert(RangeIn<Addr>(60,90),3);
+ assert(i != r.end());
+
+ i = r.find(RangeIn(20,30));
+ assert(i != r.end());
+ cout << i->first << " " << i->second << endl;
+
+ 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;
+
+
+}
+
+
+
+
+
+
+
+