first cut at a sparc tlb

src/arch/sparc/SConscript:
    Add code to serialize/unserialze tlb entries
src/arch/sparc/asi.cc:
src/arch/sparc/asi.hh:
    update asi names for how they're listed in the supplement
    add asis
    add more asi functions
src/arch/sparc/isa_traits.hh:
    move the interrupt stuff and some basic address space stuff into isa traits
src/arch/sparc/miscregfile.cc:
src/arch/sparc/miscregfile.hh:
    add mmu registers to tlb
    get rid of implicit asi stuff... the tlb will handle it
src/arch/sparc/regfile.hh:
    make isnt/dataAsid return ints not asis
src/arch/sparc/tlb.cc:
src/arch/sparc/tlb.hh:
    first cut at sparc tlb
src/arch/sparc/vtophys.hh:
    pagatable nedes to be included here
src/mem/request.hh:
    add asi and if the request is a memory mapped register to the requset object
src/sim/host.hh:
    fix incorrect definition of LL

--HG--
extra : convert_revision : 6c85cd1681c62c8cd8eab04f70b1f15a034b0aa3
This commit is contained in:
Ali Saidi 2006-11-23 01:42:57 -05:00
parent ef5b842247
commit 271b9a5435
17 changed files with 1692 additions and 199 deletions

View file

@ -56,6 +56,7 @@ base_sources = Split('''
full_system_sources = Split('''
arguments.cc
remote_gdb.cc
pagetable.cc
stacktrace.cc
system.cc
tlb.cc

View file

@ -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) ||
@ -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) ||
@ -189,8 +189,8 @@ namespace SparcISA
(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) ||
@ -248,8 +248,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 +256,38 @@ namespace SparcISA
return asi == ASI_QUEUE;
}
bool AsiIsDtlb(ASI asi)
{
return
(asi == ASI_DTLB_DATA_IN_REG) ||
(asi == ASI_DTLB_DATA_ACCESS_REG) ||
(asi == ASI_DTLB_TAG_READ_REG);
}
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_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);
}
}

View file

@ -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__
@ -53,64 +54,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_USB_BASE_PS1 = 0x3A,
ASI_DMMU_CTXT_NONZERO_CONFIG = 0x3B,
//0x3C implementation dependent
ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0 = 0x3D,
ASI_IMMU_CTXT_NONZERO_USB_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,
@ -195,6 +242,7 @@ namespace SparcISA
ASI_BLK_SL = 0xF9,
ASI_BLOCK_SECONDARY_LITTLE = ASI_BLK_SL,
//0xFA-0xFF implementation dependent
ASI_IMPLICIT = 0xFF,
MAX_ASI = 0xFF
};
@ -216,6 +264,10 @@ namespace SparcISA
bool AsiIsQueue(ASI);
bool AsiIsDtlb(ASI);
bool AsiIsMmu(ASI);
bool AsiIsUnPriv(ASI);
bool AsiIsPriv(ASI);
bool AsiIsHPriv(ASI);
bool AsiIsReg(ASI);
};

View file

@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
* Ali Saidi
*/
#ifndef __ARCH_SPARC_ISA_TRAITS_HH__
@ -46,10 +47,6 @@ class StaticInstPtr;
namespace BigEndianGuest {}
#if FULL_SYSTEM
#include "arch/sparc/isa_fullsys_traits.hh"
#endif
namespace SparcISA
{
class RegFile;
@ -133,6 +130,30 @@ namespace SparcISA
// return a no-op instruction... used for instruction fetch faults
extern const MachInst NoopMachInst;
#if FULL_SYSTEM
////////// Interrupt Stuff ///////////
enum InterruptLevels
{
INTLEVEL_MIN = 1,
INTLEVEL_MAX = 15,
NumInterruptLevels = INTLEVEL_MAX - INTLEVEL_MIN
};
// 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);
/////////// 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);
#endif
}
#endif // __ARCH_SPARC_ISA_TRAITS_HH__

View file

@ -95,8 +95,32 @@ void MiscRegFile::reset()
hstick_cmpr = 0;
strandStatusReg = 0;
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)
@ -180,6 +204,69 @@ MiscReg MiscRegFile::readReg(int miscReg)
/** Floating Point Status Register */
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];
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
@ -326,35 +413,95 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
case MISCREG_FSR:
fsr = val;
break;
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;
case MISCREG_SCRATCHPAD_R1:
scratchPad[1] = val;
case MISCREG_SCRATCHPAD_R2:
scratchPad[2] = val;
case MISCREG_SCRATCHPAD_R3:
scratchPad[3] = val;
case MISCREG_SCRATCHPAD_R4:
scratchPad[4] = val;
case MISCREG_SCRATCHPAD_R5:
scratchPad[5] = val;
case MISCREG_SCRATCHPAD_R6:
scratchPad[6] = val;
case MISCREG_SCRATCHPAD_R7:
scratchPad[7] = val;
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
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;
}
}
void MiscRegFile::setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc)
{
@ -376,11 +523,9 @@ void MiscRegFile::setRegWithEffect(int miscReg,
break;
case MISCREG_PSTATE:
pstate = val;
setImplicitAsis();
return;
case MISCREG_TL:
tl = val;
setImplicitAsis();
return;
case MISCREG_CWP:
tc->changeRegFileContext(CONTEXT_CWP, val);
@ -483,8 +628,28 @@ 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);
}
void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
@ -514,12 +679,28 @@ 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;
}
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);}
#if FULL_SYSTEM
void

View file

@ -92,7 +92,42 @@ namespace SparcISA
MISCREG_HSTICK_CMPR,
/** Floating Point Status Register */
MISCREG_FSR
MISCREG_FSR,
/** MMU Internal Registers */
MISCREG_MMU_P_CONTEXT,
MISCREG_MMU_S_CONTEXT,
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,
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,
MISCREG_SCRATCHPAD_R1,
MISCREG_SCRATCHPAD_R2,
MISCREG_SCRATCHPAD_R3,
MISCREG_SCRATCHPAD_R4,
MISCREG_SCRATCHPAD_R5,
MISCREG_SCRATCHPAD_R6,
MISCREG_SCRATCHPAD_R7
};
// The control registers, broken out into fields
@ -146,8 +181,32 @@ 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];
// These need to check the int_dis field and if 0 then
// set appropriate bit in softint and checkinterrutps on the cpu
@ -188,14 +247,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 +268,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();
};
}

View file

@ -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};
}

194
src/arch/sparc/pagetable.hh Normal file
View file

@ -0,0 +1,194 @@
/*
* 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 "config/full_system.hh"
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 {
uint64_t entry4u = 0;
entry4u |= entry & ULL(0x8000000000000000); //valid
entry4u |= (entry & 0x3) << 61; //size[1:0]
entry4u |= (entry & ULL(0x4000000000000000)) >> 2; //nfo
entry4u |= (entry & 0x1000) << 47; //ie
//entry4u |= (entry & 0x3F00000000000000) >> 7; //soft2
entry4u |= (entry & 0x4) << 48; //size[2]
//diag?
entry4u |= (entry & ULL(0x0000FFFFFFFFE000)); //paddr
entry4u |= (entry & 0x400) >> 5; //cp
entry4u |= (entry & 0x200) >> 5; //cv
entry4u |= (entry & 0x800) >> 8; //e
entry4u |= (entry & 0x100) >> 6; //p
entry4u |= (entry & 0x40) >> 5; //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 entry4u & ULL(0x8000000000000000) && populated; }
uint8_t _size() const { assert(populated);
return ((entry4u & 0x6) >> 61) |
((entry4u & ULL(0x000080000000000)) >> 46); }
Addr size() const { return pageSizes[_size()]; }
bool ie() const { return entry4u >> 59 & 0x1; }
Addr pfn() const { assert(populated);
return entry4u >> 13 & ULL(0xFFFFFFFFFF); }
Addr paddr() const { assert(populated);
return entry4u & ULL(0x0000FFFFFFFFE000); }
bool locked() const { assert(populated);
return entry4u & 0x40; }
bool cv() const { assert(populated);
return entry4u & 0x10; }
bool cp() const { assert(populated);
return entry4u & 0x20; }
bool priv() const { assert(populated);
return entry4u & 0x4; }
bool writable() const { assert(populated);
return entry4u & 0x2; }
bool nofault() const { assert(populated);
return entry4u & ULL(0x1000000000000000); }
bool sideffect() const { assert(populated);
return entry4u & 0x8; }
};
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__

View file

@ -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();
}

View file

@ -25,55 +25,548 @@
* (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/tlb.hh"
#include "sim/builder.hh"
#include "arch/sparc/miscregfile.hh"
#include "cpu/thread_context.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)
{
// 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.");
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)
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)
{
MapIter i;
TlbEntry *new_entry;
int x = -1;
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 (x == -1)
x = 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--;
}
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;
// 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()) {
return NULL;
}
// Mark the entries used bit and clear other used bits in needed
t = i->second;
if (!t->used) {
t->used = true;
usedEntries++;
if (usedEntries == size) {
clearUsedBits();
t->used = true;
usedEntries++;
}
}
return t;
}
void
TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
{
TlbRange tr;
MapIter i;
// 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;
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;
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;
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->setMiscReg(reg, sfsr);
}
void
ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct,
bool se, FaultTypes ft, int asi)
{
TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi);
}
void
DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
bool se, FaultTypes ft, int asi)
{
TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi);
tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
}
Fault
ITB::translate(RequestPtr &req, ThreadContext *tc)
{
uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
uint64_t tl = tc->readMiscReg(MISCREG_TL);
uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
bool addr_mask = pstate >> 3 & 0x1;
bool priv = pstate >> 2 & 0x1;
Addr vaddr = req->getVaddr();
int context;
ContextType ct;
int asi;
bool real = false;
TlbEntry *e;
assert(req->getAsi() == ASI_IMPLICIT);
if (tl > 0) {
asi = ASI_N;
ct = Nucleus;
context = 0;
} else {
asi = ASI_P;
ct = Primary;
context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
}
if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
req->setPaddr(req->getVaddr() & PAddrImplMask);
return NoFault;
}
// If the asi is unaligned trap
if (vaddr & 0x7) {
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 (lsuIm) {
e = lookup(req->getVaddr(), 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;
}
req->setPaddr(e->pte.paddr() & ~e->pte.size() |
req->getVaddr() & e->pte.size());
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 hpstate = tc->readMiscReg(MISCREG_HPSTATE);
uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
uint64_t tl = tc->readMiscReg(MISCREG_TL);
uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
bool hpriv = hpstate >> 2 & 0x1;
bool red = hpstate >> 5 >> 0x1;
bool addr_mask = pstate >> 3 & 0x1;
bool priv = pstate >> 2 & 0x1;
bool implicit = false;
bool real = false;
Addr vaddr = req->getVaddr();
ContextType ct;
int context;
ASI asi;
TlbEntry *e;
asi = (ASI)req->getAsi();
if (asi == ASI_IMPLICIT)
implicit = true;
if (implicit) {
if (tl > 0) {
asi = ASI_N;
ct = Nucleus;
context = 0;
} else {
asi = ASI_P;
ct = Primary;
context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
}
} else if (!hpriv && !red) {
if (tl > 0) {
ct = Nucleus;
context = 0;
} else if (AsiIsSecondary(asi)) {
ct = Secondary;
context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
} else {
context = tc->readMiscReg(MISCREG_MMU_P_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;
}
}
// If the asi is unaligned trap
if (AsiIsBlock(asi) && vaddr & 0x3f || vaddr & 0x7) {
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 (!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 (AsiIsTwin(asi))
panic("Twin ASIs not supported\n");
if (AsiIsPartialStore(asi))
panic("Partial Store ASIs not supported\n");
if (AsiIsMmu(asi))
goto handleMmuRegAccess;
if (AsiIsScratchPad(asi))
goto handleScratchRegAccess;
}
if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
real = true;
context = 0;
};
if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
req->setPaddr(req->getVaddr() & PAddrImplMask);
return NoFault;
}
e = lookup(req->getVaddr(), part_id, real, context);
if (e == NULL || !e->valid) {
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
vaddr & ~BytesInPageMask | context);
if (real)
return new DataRealTranslationMiss;
else
return new FastDataAccessMMUMiss;
}
if (write && !e->pte.writable()) {
writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
return new FastDataAccessProtection;
}
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);
if (!priv && e->pte.priv()) {
writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
return new DataAccessException;
}
req->setPaddr(e->pte.paddr() & ~e->pte.size() |
req->getVaddr() & e->pte.size());
return NoFault;
/*** End of normal Path ***/
handleMmuRegAccess:
handleScratchRegAccess:
panic("How are we ever going to deal with this?\n");
};
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)
}

View file

@ -31,6 +31,7 @@
#ifndef __ARCH_SPARC_TLB_HH__
#define __ARCH_SPARC_TLB_HH__
#include "arch/sparc/tlb_map.hh"
#include "base/misc.hh"
#include "mem/request.hh"
#include "sim/faults.hh"
@ -40,48 +41,114 @@ class ThreadContext;
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;
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
{
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;
}
};
/** 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);
/** 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();
public:
TLB(const std::string &name, int size);
// 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)
{
}
Fault translate(RequestPtr &req, ThreadContext *tc);
private:
void writeSfsr(ThreadContext *tc, bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
};
class DTB : public TLB
{
public:
DTB(const std::string &name, int size) : TLB(name, size)
{
}
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
private:
void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
};
}
#endif // __ARCH_SPARC_TLB_HH__

135
src/arch/sparc/tlb_map.hh Normal file
View file

@ -0,0 +1,135 @@
/*
* 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())
// 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__

View file

@ -33,6 +33,7 @@
#define __ARCH_SPARC_VTOPHYS_H__
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/pagetable.hh"
class ThreadContext;
class FunctionalPort;

129
src/base/range_map.hh Normal file
View file

@ -0,0 +1,129 @@
/*
* 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())
// 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();
}
};
#endif //__BASE_RANGE_MAP_HH__

View file

@ -95,6 +95,11 @@ class Request
/** The address space ID. */
int asid;
/** The ASI is any -- SPARC ONLY */
int asi;
/** This request is to a memory mapped register. */
bool mmapedReg;
/** The virtual address of the request. */
Addr vaddr;
@ -215,6 +220,16 @@ class Request
/** Accessor function for asid.*/
int getAsid() { assert(validAsidVaddr); return asid; }
/** Accessor function for asi.*/
int getAsi() { assert(validAsidVaddr); return asi; }
/** Accessor function for asi.*/
void setAsi(int a) { assert(validAsidVaddr); asi = a; }
/** Accessor function for asi.*/
bool getMmapedReg() { assert(validPaddr); return mmapedReg; }
/** Accessor function for asi.*/
void setMmapedReg(bool r) { assert(validPaddr); mmapedReg = r; }
/** Accessor function to check if sc result is valid. */
bool scResultValid() { return validScResult; }
/** Accessor function for store conditional return value.*/

View file

@ -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

View file

@ -0,0 +1,63 @@
/*
* 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>(0,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());
}