SPARC: Fold the MiscRegFile all the way into the ISA object.
This commit is contained in:
parent
de7f462219
commit
60d47aa5f9
|
@ -35,7 +35,6 @@ if env['TARGET_ISA'] == 'sparc':
|
|||
Source('asi.cc')
|
||||
Source('faults.cc')
|
||||
Source('isa.cc')
|
||||
Source('miscregfile.cc')
|
||||
Source('pagetable.cc')
|
||||
Source('remote_gdb.cc')
|
||||
Source('tlb.cc')
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include "arch/sparc/faults.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "params/SparcInterrupts.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
|
|
@ -28,47 +28,706 @@
|
|||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include "arch/sparc/asi.hh"
|
||||
#include "arch/sparc/isa.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
|
||||
enum RegMask
|
||||
{
|
||||
PSTATE_MASK = (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12)
|
||||
};
|
||||
|
||||
void
|
||||
ISA::clear()
|
||||
{
|
||||
miscRegFile.clear();
|
||||
//y = 0;
|
||||
//ccr = 0;
|
||||
asi = 0;
|
||||
tick = ULL(1) << 63;
|
||||
fprs = 0;
|
||||
gsr = 0;
|
||||
softint = 0;
|
||||
tick_cmpr = 0;
|
||||
stick = 0;
|
||||
stick_cmpr = 0;
|
||||
memset(tpc, 0, sizeof(tpc));
|
||||
memset(tnpc, 0, sizeof(tnpc));
|
||||
memset(tstate, 0, sizeof(tstate));
|
||||
memset(tt, 0, sizeof(tt));
|
||||
pstate = 0;
|
||||
tl = 0;
|
||||
pil = 0;
|
||||
cwp = 0;
|
||||
//cansave = 0;
|
||||
//canrestore = 0;
|
||||
//cleanwin = 0;
|
||||
//otherwin = 0;
|
||||
//wstate = 0;
|
||||
gl = 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;
|
||||
//This is set this way in Legion for some reason
|
||||
strandStatusReg = 0x50000;
|
||||
fsr = 0;
|
||||
|
||||
priContext = 0;
|
||||
secContext = 0;
|
||||
partId = 0;
|
||||
lsuCtrlReg = 0;
|
||||
|
||||
memset(scratchPad, 0, sizeof(scratchPad));
|
||||
#if FULL_SYSTEM
|
||||
tickCompare = NULL;
|
||||
sTickCompare = NULL;
|
||||
hSTickCompare = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
MiscReg
|
||||
ISA::readMiscRegNoEffect(int miscReg)
|
||||
{
|
||||
return miscRegFile.readRegNoEffect((MiscRegIndex)miscReg);
|
||||
|
||||
// The three miscRegs are moved up from the switch statement
|
||||
// due to more frequent calls.
|
||||
|
||||
if (miscReg == MISCREG_GL)
|
||||
return gl;
|
||||
if (miscReg == MISCREG_CWP)
|
||||
return cwp;
|
||||
if (miscReg == 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;
|
||||
}
|
||||
|
||||
switch (miscReg) {
|
||||
//case MISCREG_TLB_DATA:
|
||||
// [original contents see above]
|
||||
//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;
|
||||
//CWP, GL moved
|
||||
//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:
|
||||
return hintp;
|
||||
case MISCREG_HTBA:
|
||||
return htba;
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
return strandStatusReg;
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
return hstick_cmpr;
|
||||
|
||||
/** Floating Point Status Register */
|
||||
case MISCREG_FSR:
|
||||
DPRINTF(MiscRegs, "FSR read as: %#x\n", 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_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
|
||||
ISA::readMiscReg(int miscReg, ThreadContext * tc)
|
||||
{
|
||||
return miscRegFile.readReg((MiscRegIndex)miscReg, tc);
|
||||
switch (miscReg) {
|
||||
// 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
|
||||
DPRINTF(Timer, "Instruction Count when TICK read: %#X stick=%#X\n",
|
||||
tc->getCpuPtr()->instCount(), stick);
|
||||
return mbits(tc->getCpuPtr()->instCount() + (int64_t)stick,62,2) |
|
||||
mbits(tick,63,63);
|
||||
case MISCREG_FPRS:
|
||||
// in legion if fp is enabled du and dl are set
|
||||
return fprs | 0x3;
|
||||
case MISCREG_PCR:
|
||||
case MISCREG_PIC:
|
||||
panic("Performance Instrumentation not impl\n");
|
||||
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_HPSTATE:
|
||||
return readFSReg(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 %d in SE mode\n", miscReg);
|
||||
#endif
|
||||
|
||||
}
|
||||
return readMiscRegNoEffect(miscReg);
|
||||
}
|
||||
|
||||
void
|
||||
ISA::setMiscRegNoEffect(int miscReg, const MiscReg val)
|
||||
ISA::setMiscRegNoEffect(int miscReg, MiscReg val)
|
||||
{
|
||||
miscRegFile.setRegNoEffect((MiscRegIndex)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;
|
||||
|
||||
/** 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 & 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:
|
||||
hintp = val;
|
||||
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;
|
||||
DPRINTF(MiscRegs, "FSR written with: %#x\n", fsr);
|
||||
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_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
|
||||
ISA::setMiscReg(int miscReg, const MiscReg val, ThreadContext *tc)
|
||||
ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
|
||||
{
|
||||
miscRegFile.setReg((MiscRegIndex)miscReg, val, tc);
|
||||
MiscReg new_val = val;
|
||||
|
||||
switch (miscReg) {
|
||||
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);
|
||||
DPRINTF(Timer, "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;
|
||||
#if FULL_SYSTEM
|
||||
if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
|
||||
tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
||||
else
|
||||
tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
||||
#endif
|
||||
return;
|
||||
case MISCREG_CWP:
|
||||
new_val = val >= NWindows ? NWindows - 1 : val;
|
||||
if (val >= NWindows)
|
||||
new_val = NWindows - 1;
|
||||
break;
|
||||
case MISCREG_GL:
|
||||
break;
|
||||
case MISCREG_PIL:
|
||||
case MISCREG_SOFTINT:
|
||||
case MISCREG_SOFTINT_SET:
|
||||
case MISCREG_SOFTINT_CLR:
|
||||
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_HPSTATE:
|
||||
setFSReg(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 %d to %#x in SE mode\n",
|
||||
miscReg, val);
|
||||
#endif
|
||||
}
|
||||
setMiscRegNoEffect(miscReg, new_val);
|
||||
}
|
||||
|
||||
void
|
||||
ISA::serialize(EventManager *em, std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(asi);
|
||||
SERIALIZE_SCALAR(tick);
|
||||
SERIALIZE_SCALAR(fprs);
|
||||
SERIALIZE_SCALAR(gsr);
|
||||
SERIALIZE_SCALAR(softint);
|
||||
SERIALIZE_SCALAR(tick_cmpr);
|
||||
SERIALIZE_SCALAR(stick);
|
||||
SERIALIZE_SCALAR(stick_cmpr);
|
||||
SERIALIZE_ARRAY(tpc,MaxTL);
|
||||
SERIALIZE_ARRAY(tnpc,MaxTL);
|
||||
SERIALIZE_ARRAY(tstate,MaxTL);
|
||||
SERIALIZE_ARRAY(tt,MaxTL);
|
||||
SERIALIZE_SCALAR(tba);
|
||||
SERIALIZE_SCALAR(pstate);
|
||||
SERIALIZE_SCALAR(tl);
|
||||
SERIALIZE_SCALAR(pil);
|
||||
SERIALIZE_SCALAR(cwp);
|
||||
SERIALIZE_SCALAR(gl);
|
||||
SERIALIZE_SCALAR(hpstate);
|
||||
SERIALIZE_ARRAY(htstate,MaxTL);
|
||||
SERIALIZE_SCALAR(hintp);
|
||||
SERIALIZE_SCALAR(htba);
|
||||
SERIALIZE_SCALAR(hstick_cmpr);
|
||||
SERIALIZE_SCALAR(strandStatusReg);
|
||||
SERIALIZE_SCALAR(fsr);
|
||||
SERIALIZE_SCALAR(priContext);
|
||||
SERIALIZE_SCALAR(secContext);
|
||||
SERIALIZE_SCALAR(partId);
|
||||
SERIALIZE_SCALAR(lsuCtrlReg);
|
||||
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);
|
||||
#if FULL_SYSTEM
|
||||
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
|
||||
ThreadContext *tc = NULL;
|
||||
BaseCPU *cpu = NULL;
|
||||
int tc_num = 0;
|
||||
bool tick_intr_sched = true;
|
||||
|
||||
if (tickCompare)
|
||||
tc = tickCompare->getTC();
|
||||
else if (sTickCompare)
|
||||
tc = sTickCompare->getTC();
|
||||
else if (hSTickCompare)
|
||||
tc = hSTickCompare->getTC();
|
||||
else
|
||||
tick_intr_sched = false;
|
||||
|
||||
SERIALIZE_SCALAR(tick_intr_sched);
|
||||
|
||||
if (tc) {
|
||||
cpu = tc->getCpuPtr();
|
||||
tc_num = cpu->findContext(tc);
|
||||
if (tickCompare && tickCompare->scheduled())
|
||||
tick_cmp = tickCompare->when();
|
||||
if (sTickCompare && sTickCompare->scheduled())
|
||||
stick_cmp = sTickCompare->when();
|
||||
if (hSTickCompare && hSTickCompare->scheduled())
|
||||
hstick_cmp = hSTickCompare->when();
|
||||
|
||||
SERIALIZE_OBJPTR(cpu);
|
||||
SERIALIZE_SCALAR(tc_num);
|
||||
SERIALIZE_SCALAR(tick_cmp);
|
||||
SERIALIZE_SCALAR(stick_cmp);
|
||||
SERIALIZE_SCALAR(hstick_cmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(asi);
|
||||
UNSERIALIZE_SCALAR(tick);
|
||||
UNSERIALIZE_SCALAR(fprs);
|
||||
UNSERIALIZE_SCALAR(gsr);
|
||||
UNSERIALIZE_SCALAR(softint);
|
||||
UNSERIALIZE_SCALAR(tick_cmpr);
|
||||
UNSERIALIZE_SCALAR(stick);
|
||||
UNSERIALIZE_SCALAR(stick_cmpr);
|
||||
UNSERIALIZE_ARRAY(tpc,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tnpc,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tstate,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tt,MaxTL);
|
||||
UNSERIALIZE_SCALAR(tba);
|
||||
UNSERIALIZE_SCALAR(pstate);
|
||||
UNSERIALIZE_SCALAR(tl);
|
||||
UNSERIALIZE_SCALAR(pil);
|
||||
UNSERIALIZE_SCALAR(cwp);
|
||||
UNSERIALIZE_SCALAR(gl);
|
||||
UNSERIALIZE_SCALAR(hpstate);
|
||||
UNSERIALIZE_ARRAY(htstate,MaxTL);
|
||||
UNSERIALIZE_SCALAR(hintp);
|
||||
UNSERIALIZE_SCALAR(htba);
|
||||
UNSERIALIZE_SCALAR(hstick_cmpr);
|
||||
UNSERIALIZE_SCALAR(strandStatusReg);
|
||||
UNSERIALIZE_SCALAR(fsr);
|
||||
UNSERIALIZE_SCALAR(priContext);
|
||||
UNSERIALIZE_SCALAR(secContext);
|
||||
UNSERIALIZE_SCALAR(partId);
|
||||
UNSERIALIZE_SCALAR(lsuCtrlReg);
|
||||
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);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
|
||||
ThreadContext *tc = NULL;
|
||||
BaseCPU *cpu = NULL;
|
||||
int tc_num;
|
||||
bool tick_intr_sched;
|
||||
UNSERIALIZE_SCALAR(tick_intr_sched);
|
||||
if (tick_intr_sched) {
|
||||
UNSERIALIZE_OBJPTR(cpu);
|
||||
if (cpu) {
|
||||
UNSERIALIZE_SCALAR(tc_num);
|
||||
UNSERIALIZE_SCALAR(tick_cmp);
|
||||
UNSERIALIZE_SCALAR(stick_cmp);
|
||||
UNSERIALIZE_SCALAR(hstick_cmp);
|
||||
tc = cpu->getContext(tc_num);
|
||||
|
||||
if (tick_cmp) {
|
||||
tickCompare = new TickCompareEvent(this, tc);
|
||||
em->schedule(tickCompare, tick_cmp);
|
||||
}
|
||||
if (stick_cmp) {
|
||||
sTickCompare = new STickCompareEvent(this, tc);
|
||||
em->schedule(sTickCompare, stick_cmp);
|
||||
}
|
||||
if (hstick_cmp) {
|
||||
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||
em->schedule(hSTickCompare, hstick_cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ISA::flattenIntIndex(int reg)
|
||||
{
|
||||
int gl = miscRegFile.readRegNoEffect(MISCREG_GL);
|
||||
int cwp = miscRegFile.readRegNoEffect(MISCREG_CWP);
|
||||
int gl = readMiscRegNoEffect(MISCREG_GL);
|
||||
int cwp = readMiscRegNoEffect(MISCREG_CWP);
|
||||
//DPRINTF(RegisterWindows, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp);
|
||||
int newReg;
|
||||
//The total number of global registers
|
||||
|
@ -132,16 +791,4 @@ ISA::flattenIntIndex(int reg)
|
|||
return newReg;
|
||||
}
|
||||
|
||||
void
|
||||
ISA::serialize(EventManager *em, std::ostream &os)
|
||||
{
|
||||
miscRegFile.serialize(em, os);
|
||||
}
|
||||
|
||||
void
|
||||
ISA::unserialize(EventManager *em, Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
miscRegFile.unserialize(em, cp, section);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,21 +31,130 @@
|
|||
#ifndef __ARCH_SPARC_ISA_HH__
|
||||
#define __ARCH_SPARC_ISA_HH__
|
||||
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "cpu/cpuevent.hh"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
class Checkpoint;
|
||||
class EventManager;
|
||||
class ThreadContext;
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
class ISA
|
||||
{
|
||||
private:
|
||||
|
||||
/* ASR Registers */
|
||||
//uint64_t y; // Y (used in obsolete multiplication)
|
||||
//uint8_t ccr; // Condition Code Register
|
||||
uint8_t asi; // Address Space Identifier
|
||||
uint64_t tick; // Hardware clock-tick counter
|
||||
uint8_t fprs; // Floating-Point Register State
|
||||
uint64_t gsr; // General Status Register
|
||||
uint64_t softint;
|
||||
uint64_t tick_cmpr; // Hardware tick compare registers
|
||||
uint64_t stick; // Hardware clock-tick counter
|
||||
uint64_t stick_cmpr; // Hardware tick compare registers
|
||||
|
||||
|
||||
/* Privileged Registers */
|
||||
uint64_t tpc[MaxTL]; // Trap Program Counter (value from
|
||||
// previous trap level)
|
||||
uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
|
||||
// previous trap level)
|
||||
uint64_t tstate[MaxTL]; // Trap State
|
||||
uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
|
||||
// on the previous level)
|
||||
uint64_t tba; // Trap Base Address
|
||||
|
||||
uint16_t pstate; // Process State Register
|
||||
uint8_t tl; // Trap Level
|
||||
uint8_t pil; // Process Interrupt Register
|
||||
uint8_t cwp; // Current Window Pointer
|
||||
//uint8_t cansave; // Savable windows
|
||||
//uint8_t canrestore; // Restorable windows
|
||||
//uint8_t cleanwin; // Clean windows
|
||||
//uint8_t otherwin; // Other windows
|
||||
//uint8_t wstate; // Window State
|
||||
uint8_t gl; // Global level register
|
||||
|
||||
/** Hyperprivileged Registers */
|
||||
uint64_t hpstate; // Hyperprivileged State Register
|
||||
uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
|
||||
uint64_t hintp;
|
||||
uint64_t htba; // Hyperprivileged Trap Base Address register
|
||||
uint64_t hstick_cmpr; // Hardware tick compare registers
|
||||
|
||||
uint64_t strandStatusReg;// Per strand status register
|
||||
|
||||
/** Floating point misc registers. */
|
||||
uint64_t fsr; // Floating-Point State Register
|
||||
|
||||
/** MMU Internal Registers */
|
||||
uint16_t priContext;
|
||||
uint16_t secContext;
|
||||
uint16_t partId;
|
||||
uint64_t lsuCtrlReg;
|
||||
|
||||
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 setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc);
|
||||
MiscReg readFSReg(int miscReg, ThreadContext * tc);
|
||||
|
||||
// Update interrupt state on softint or pil change
|
||||
void checkSoftInt(ThreadContext *tc);
|
||||
|
||||
/** Process a tick compare event and generate an interrupt on the cpu if
|
||||
* appropriate. */
|
||||
void processTickCompare(ThreadContext *tc);
|
||||
void processSTickCompare(ThreadContext *tc);
|
||||
void processHSTickCompare(ThreadContext *tc);
|
||||
|
||||
typedef CpuEventWrapper<ISA,
|
||||
&ISA::processTickCompare> TickCompareEvent;
|
||||
TickCompareEvent *tickCompare;
|
||||
|
||||
typedef CpuEventWrapper<ISA,
|
||||
&ISA::processSTickCompare> STickCompareEvent;
|
||||
STickCompareEvent *sTickCompare;
|
||||
|
||||
typedef CpuEventWrapper<ISA,
|
||||
&ISA::processHSTickCompare> HSTickCompareEvent;
|
||||
HSTickCompareEvent *hSTickCompare;
|
||||
#endif
|
||||
public:
|
||||
|
||||
void clear();
|
||||
|
||||
void serialize(EventManager *em, std::ostream & os);
|
||||
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string & section);
|
||||
|
||||
protected:
|
||||
MiscRegFile miscRegFile;
|
||||
|
||||
bool isHyperPriv() { return (hpstate & (1 << 2)); }
|
||||
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
|
||||
bool isNonPriv() { return !isPriv(); }
|
||||
|
||||
public:
|
||||
void clear();
|
||||
|
||||
MiscReg readMiscRegNoEffect(int miscReg);
|
||||
MiscReg readMiscReg(int miscReg, ThreadContext *tc);
|
||||
|
@ -62,10 +171,6 @@ namespace SparcISA
|
|||
return reg;
|
||||
}
|
||||
|
||||
void serialize(EventManager *em, std::ostream &os);
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
|
||||
ISA()
|
||||
{
|
||||
clear();
|
||||
|
|
|
@ -1,724 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Ali Saidi
|
||||
*/
|
||||
|
||||
#include "arch/sparc/asi.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
using namespace SparcISA;
|
||||
using namespace std;
|
||||
|
||||
class Checkpoint;
|
||||
|
||||
enum RegMask
|
||||
{
|
||||
PSTATE_MASK = (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12)
|
||||
};
|
||||
|
||||
void MiscRegFile::clear()
|
||||
{
|
||||
//y = 0;
|
||||
//ccr = 0;
|
||||
asi = 0;
|
||||
tick = ULL(1) << 63;
|
||||
fprs = 0;
|
||||
gsr = 0;
|
||||
softint = 0;
|
||||
tick_cmpr = 0;
|
||||
stick = 0;
|
||||
stick_cmpr = 0;
|
||||
memset(tpc, 0, sizeof(tpc));
|
||||
memset(tnpc, 0, sizeof(tnpc));
|
||||
memset(tstate, 0, sizeof(tstate));
|
||||
memset(tt, 0, sizeof(tt));
|
||||
pstate = 0;
|
||||
tl = 0;
|
||||
pil = 0;
|
||||
cwp = 0;
|
||||
//cansave = 0;
|
||||
//canrestore = 0;
|
||||
//cleanwin = 0;
|
||||
//otherwin = 0;
|
||||
//wstate = 0;
|
||||
gl = 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;
|
||||
//This is set this way in Legion for some reason
|
||||
strandStatusReg = 0x50000;
|
||||
fsr = 0;
|
||||
|
||||
priContext = 0;
|
||||
secContext = 0;
|
||||
partId = 0;
|
||||
lsuCtrlReg = 0;
|
||||
|
||||
memset(scratchPad, 0, sizeof(scratchPad));
|
||||
#if FULL_SYSTEM
|
||||
tickCompare = NULL;
|
||||
sTickCompare = NULL;
|
||||
hSTickCompare = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
MiscReg MiscRegFile::readRegNoEffect(int miscReg)
|
||||
{
|
||||
|
||||
// The three miscRegs are moved up from the switch statement
|
||||
// due to more frequent calls.
|
||||
|
||||
if (miscReg == MISCREG_GL)
|
||||
return gl;
|
||||
if (miscReg == MISCREG_CWP)
|
||||
return cwp;
|
||||
if (miscReg == 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;
|
||||
}
|
||||
|
||||
switch (miscReg) {
|
||||
//case MISCREG_TLB_DATA:
|
||||
// [original contents see above]
|
||||
//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;
|
||||
//CWP, GL moved
|
||||
//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:
|
||||
return hintp;
|
||||
case MISCREG_HTBA:
|
||||
return htba;
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
return strandStatusReg;
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
return hstick_cmpr;
|
||||
|
||||
/** Floating Point Status Register */
|
||||
case MISCREG_FSR:
|
||||
DPRINTF(MiscRegs, "FSR read as: %#x\n", 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_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::readReg(int miscReg, ThreadContext * tc)
|
||||
{
|
||||
switch (miscReg) {
|
||||
// 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
|
||||
DPRINTF(Timer, "Instruction Count when TICK read: %#X stick=%#X\n",
|
||||
tc->getCpuPtr()->instCount(), stick);
|
||||
return mbits(tc->getCpuPtr()->instCount() + (int64_t)stick,62,2) |
|
||||
mbits(tick,63,63);
|
||||
case MISCREG_FPRS:
|
||||
// in legion if fp is enabled du and dl are set
|
||||
return fprs | 0x3;
|
||||
case MISCREG_PCR:
|
||||
case MISCREG_PIC:
|
||||
panic("Performance Instrumentation not impl\n");
|
||||
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_HPSTATE:
|
||||
return readFSReg(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 %d in SE mode\n", miscReg);
|
||||
#endif
|
||||
|
||||
}
|
||||
return readRegNoEffect(miscReg);
|
||||
}
|
||||
|
||||
void MiscRegFile::setRegNoEffect(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;
|
||||
|
||||
/** 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 & 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:
|
||||
hintp = val;
|
||||
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;
|
||||
DPRINTF(MiscRegs, "FSR written with: %#x\n", fsr);
|
||||
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_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::setReg(int miscReg,
|
||||
const MiscReg &val, ThreadContext * tc)
|
||||
{
|
||||
MiscReg new_val = val;
|
||||
|
||||
switch (miscReg) {
|
||||
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);
|
||||
DPRINTF(Timer, "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;
|
||||
#if FULL_SYSTEM
|
||||
if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
|
||||
tc->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
||||
else
|
||||
tc->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
||||
#endif
|
||||
return;
|
||||
case MISCREG_CWP:
|
||||
new_val = val >= NWindows ? NWindows - 1 : val;
|
||||
if (val >= NWindows)
|
||||
new_val = NWindows - 1;
|
||||
break;
|
||||
case MISCREG_GL:
|
||||
break;
|
||||
case MISCREG_PIL:
|
||||
case MISCREG_SOFTINT:
|
||||
case MISCREG_SOFTINT_SET:
|
||||
case MISCREG_SOFTINT_CLR:
|
||||
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_HPSTATE:
|
||||
setFSReg(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 %d to %#x in SE mode\n",
|
||||
miscReg, val);
|
||||
#endif
|
||||
}
|
||||
setRegNoEffect(miscReg, new_val);
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::serialize(EventManager *em, std::ostream &os)
|
||||
{
|
||||
SERIALIZE_SCALAR(asi);
|
||||
SERIALIZE_SCALAR(tick);
|
||||
SERIALIZE_SCALAR(fprs);
|
||||
SERIALIZE_SCALAR(gsr);
|
||||
SERIALIZE_SCALAR(softint);
|
||||
SERIALIZE_SCALAR(tick_cmpr);
|
||||
SERIALIZE_SCALAR(stick);
|
||||
SERIALIZE_SCALAR(stick_cmpr);
|
||||
SERIALIZE_ARRAY(tpc,MaxTL);
|
||||
SERIALIZE_ARRAY(tnpc,MaxTL);
|
||||
SERIALIZE_ARRAY(tstate,MaxTL);
|
||||
SERIALIZE_ARRAY(tt,MaxTL);
|
||||
SERIALIZE_SCALAR(tba);
|
||||
SERIALIZE_SCALAR(pstate);
|
||||
SERIALIZE_SCALAR(tl);
|
||||
SERIALIZE_SCALAR(pil);
|
||||
SERIALIZE_SCALAR(cwp);
|
||||
SERIALIZE_SCALAR(gl);
|
||||
SERIALIZE_SCALAR(hpstate);
|
||||
SERIALIZE_ARRAY(htstate,MaxTL);
|
||||
SERIALIZE_SCALAR(hintp);
|
||||
SERIALIZE_SCALAR(htba);
|
||||
SERIALIZE_SCALAR(hstick_cmpr);
|
||||
SERIALIZE_SCALAR(strandStatusReg);
|
||||
SERIALIZE_SCALAR(fsr);
|
||||
SERIALIZE_SCALAR(priContext);
|
||||
SERIALIZE_SCALAR(secContext);
|
||||
SERIALIZE_SCALAR(partId);
|
||||
SERIALIZE_SCALAR(lsuCtrlReg);
|
||||
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);
|
||||
#if FULL_SYSTEM
|
||||
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
|
||||
ThreadContext *tc = NULL;
|
||||
BaseCPU *cpu = NULL;
|
||||
int tc_num = 0;
|
||||
bool tick_intr_sched = true;
|
||||
|
||||
if (tickCompare)
|
||||
tc = tickCompare->getTC();
|
||||
else if (sTickCompare)
|
||||
tc = sTickCompare->getTC();
|
||||
else if (hSTickCompare)
|
||||
tc = hSTickCompare->getTC();
|
||||
else
|
||||
tick_intr_sched = false;
|
||||
|
||||
SERIALIZE_SCALAR(tick_intr_sched);
|
||||
|
||||
if (tc) {
|
||||
cpu = tc->getCpuPtr();
|
||||
tc_num = cpu->findContext(tc);
|
||||
if (tickCompare && tickCompare->scheduled())
|
||||
tick_cmp = tickCompare->when();
|
||||
if (sTickCompare && sTickCompare->scheduled())
|
||||
stick_cmp = sTickCompare->when();
|
||||
if (hSTickCompare && hSTickCompare->scheduled())
|
||||
hstick_cmp = hSTickCompare->when();
|
||||
|
||||
SERIALIZE_OBJPTR(cpu);
|
||||
SERIALIZE_SCALAR(tc_num);
|
||||
SERIALIZE_SCALAR(tick_cmp);
|
||||
SERIALIZE_SCALAR(stick_cmp);
|
||||
SERIALIZE_SCALAR(hstick_cmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::unserialize(EventManager *em, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(asi);
|
||||
UNSERIALIZE_SCALAR(tick);
|
||||
UNSERIALIZE_SCALAR(fprs);
|
||||
UNSERIALIZE_SCALAR(gsr);
|
||||
UNSERIALIZE_SCALAR(softint);
|
||||
UNSERIALIZE_SCALAR(tick_cmpr);
|
||||
UNSERIALIZE_SCALAR(stick);
|
||||
UNSERIALIZE_SCALAR(stick_cmpr);
|
||||
UNSERIALIZE_ARRAY(tpc,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tnpc,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tstate,MaxTL);
|
||||
UNSERIALIZE_ARRAY(tt,MaxTL);
|
||||
UNSERIALIZE_SCALAR(tba);
|
||||
UNSERIALIZE_SCALAR(pstate);
|
||||
UNSERIALIZE_SCALAR(tl);
|
||||
UNSERIALIZE_SCALAR(pil);
|
||||
UNSERIALIZE_SCALAR(cwp);
|
||||
UNSERIALIZE_SCALAR(gl);
|
||||
UNSERIALIZE_SCALAR(hpstate);
|
||||
UNSERIALIZE_ARRAY(htstate,MaxTL);
|
||||
UNSERIALIZE_SCALAR(hintp);
|
||||
UNSERIALIZE_SCALAR(htba);
|
||||
UNSERIALIZE_SCALAR(hstick_cmpr);
|
||||
UNSERIALIZE_SCALAR(strandStatusReg);
|
||||
UNSERIALIZE_SCALAR(fsr);
|
||||
UNSERIALIZE_SCALAR(priContext);
|
||||
UNSERIALIZE_SCALAR(secContext);
|
||||
UNSERIALIZE_SCALAR(partId);
|
||||
UNSERIALIZE_SCALAR(lsuCtrlReg);
|
||||
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);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
|
||||
ThreadContext *tc = NULL;
|
||||
BaseCPU *cpu = NULL;
|
||||
int tc_num;
|
||||
bool tick_intr_sched;
|
||||
UNSERIALIZE_SCALAR(tick_intr_sched);
|
||||
if (tick_intr_sched) {
|
||||
UNSERIALIZE_OBJPTR(cpu);
|
||||
if (cpu) {
|
||||
UNSERIALIZE_SCALAR(tc_num);
|
||||
UNSERIALIZE_SCALAR(tick_cmp);
|
||||
UNSERIALIZE_SCALAR(stick_cmp);
|
||||
UNSERIALIZE_SCALAR(hstick_cmp);
|
||||
tc = cpu->getContext(tc_num);
|
||||
|
||||
if (tick_cmp) {
|
||||
tickCompare = new TickCompareEvent(this, tc);
|
||||
em->schedule(tickCompare, tick_cmp);
|
||||
}
|
||||
if (stick_cmp) {
|
||||
sTickCompare = new STickCompareEvent(this, tc);
|
||||
em->schedule(sTickCompare, stick_cmp);
|
||||
}
|
||||
if (hstick_cmp) {
|
||||
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||
em->schedule(hSTickCompare, hstick_cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
* Ali Saidi
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_SPARC_MISCREGFILE_HH__
|
||||
#define __ARCH_SPARC_MISCREGFILE_HH__
|
||||
|
||||
#include "arch/sparc/faults.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/miscregs.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "cpu/cpuevent.hh"
|
||||
|
||||
#include <string>
|
||||
|
||||
class Checkpoint;
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
// The control registers, broken out into fields
|
||||
class MiscRegFile
|
||||
{
|
||||
private:
|
||||
|
||||
/* ASR Registers */
|
||||
//uint64_t y; // Y (used in obsolete multiplication)
|
||||
//uint8_t ccr; // Condition Code Register
|
||||
uint8_t asi; // Address Space Identifier
|
||||
uint64_t tick; // Hardware clock-tick counter
|
||||
uint8_t fprs; // Floating-Point Register State
|
||||
uint64_t gsr; // General Status Register
|
||||
uint64_t softint;
|
||||
uint64_t tick_cmpr; // Hardware tick compare registers
|
||||
uint64_t stick; // Hardware clock-tick counter
|
||||
uint64_t stick_cmpr; // Hardware tick compare registers
|
||||
|
||||
|
||||
/* Privileged Registers */
|
||||
uint64_t tpc[MaxTL]; // Trap Program Counter (value from
|
||||
// previous trap level)
|
||||
uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
|
||||
// previous trap level)
|
||||
uint64_t tstate[MaxTL]; // Trap State
|
||||
uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
|
||||
// on the previous level)
|
||||
uint64_t tba; // Trap Base Address
|
||||
|
||||
uint16_t pstate; // Process State Register
|
||||
uint8_t tl; // Trap Level
|
||||
uint8_t pil; // Process Interrupt Register
|
||||
uint8_t cwp; // Current Window Pointer
|
||||
//uint8_t cansave; // Savable windows
|
||||
//uint8_t canrestore; // Restorable windows
|
||||
//uint8_t cleanwin; // Clean windows
|
||||
//uint8_t otherwin; // Other windows
|
||||
//uint8_t wstate; // Window State
|
||||
uint8_t gl; // Global level register
|
||||
|
||||
/** Hyperprivileged Registers */
|
||||
uint64_t hpstate; // Hyperprivileged State Register
|
||||
uint64_t htstate[MaxTL];// Hyperprivileged Trap State Register
|
||||
uint64_t hintp;
|
||||
uint64_t htba; // Hyperprivileged Trap Base Address register
|
||||
uint64_t hstick_cmpr; // Hardware tick compare registers
|
||||
|
||||
uint64_t strandStatusReg;// Per strand status register
|
||||
|
||||
/** Floating point misc registers. */
|
||||
uint64_t fsr; // Floating-Point State Register
|
||||
|
||||
/** MMU Internal Registers */
|
||||
uint16_t priContext;
|
||||
uint16_t secContext;
|
||||
uint16_t partId;
|
||||
uint64_t lsuCtrlReg;
|
||||
|
||||
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 setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc);
|
||||
MiscReg readFSReg(int miscReg, ThreadContext * tc);
|
||||
|
||||
// Update interrupt state on softint or pil change
|
||||
void checkSoftInt(ThreadContext *tc);
|
||||
|
||||
/** Process a tick compare event and generate an interrupt on the cpu if
|
||||
* appropriate. */
|
||||
void processTickCompare(ThreadContext *tc);
|
||||
void processSTickCompare(ThreadContext *tc);
|
||||
void processHSTickCompare(ThreadContext *tc);
|
||||
|
||||
typedef CpuEventWrapper<MiscRegFile,
|
||||
&MiscRegFile::processTickCompare> TickCompareEvent;
|
||||
TickCompareEvent *tickCompare;
|
||||
|
||||
typedef CpuEventWrapper<MiscRegFile,
|
||||
&MiscRegFile::processSTickCompare> STickCompareEvent;
|
||||
STickCompareEvent *sTickCompare;
|
||||
|
||||
typedef CpuEventWrapper<MiscRegFile,
|
||||
&MiscRegFile::processHSTickCompare> HSTickCompareEvent;
|
||||
HSTickCompareEvent *hSTickCompare;
|
||||
#endif
|
||||
public:
|
||||
|
||||
void clear();
|
||||
|
||||
MiscRegFile()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
MiscReg readRegNoEffect(int miscReg);
|
||||
|
||||
MiscReg readReg(int miscReg, ThreadContext *tc);
|
||||
|
||||
void setRegNoEffect(int miscReg, const MiscReg &val);
|
||||
|
||||
void setReg(int miscReg,
|
||||
const MiscReg &val, ThreadContext * tc);
|
||||
|
||||
void serialize(EventManager *em, std::ostream & os);
|
||||
|
||||
void unserialize(EventManager *em, Checkpoint *cp,
|
||||
const std::string & section);
|
||||
|
||||
void copyMiscRegs(ThreadContext * tc);
|
||||
|
||||
protected:
|
||||
|
||||
bool isHyperPriv() { return (hpstate & (1 << 2)); }
|
||||
bool isPriv() { return (hpstate & (1 << 2)) || (pstate & (1 << 2)); }
|
||||
bool isNonPriv() { return !isPriv(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef __ARCH_SPARC_PREDECODER_HH__
|
||||
#define __ARCH_SPARC_PREDECODER_HH__
|
||||
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/misc.hh"
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "arch/sparc/asi.hh"
|
||||
#include "arch/sparc/handlers.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/process.hh"
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "arch/sparc/asi.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/tlb.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "arch/sparc/isa.hh"
|
||||
#include "arch/sparc/kernel_stats.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/base.hh"
|
||||
|
@ -39,7 +40,7 @@ using namespace std;
|
|||
|
||||
|
||||
void
|
||||
MiscRegFile::checkSoftInt(ThreadContext *tc)
|
||||
ISA::checkSoftInt(ThreadContext *tc)
|
||||
{
|
||||
BaseCPU *cpu = tc->getCpuPtr();
|
||||
|
||||
|
@ -84,7 +85,7 @@ getMiscRegName(RegIndex index)
|
|||
}
|
||||
|
||||
void
|
||||
MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
||||
ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
||||
{
|
||||
BaseCPU *cpu = tc->getCpuPtr();
|
||||
|
||||
|
@ -92,18 +93,18 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
switch (miscReg) {
|
||||
/* Full system only ASRs */
|
||||
case MISCREG_SOFTINT:
|
||||
setRegNoEffect(miscReg, val);;
|
||||
setMiscRegNoEffect(miscReg, val);;
|
||||
checkSoftInt(tc);
|
||||
break;
|
||||
case MISCREG_SOFTINT_CLR:
|
||||
return setReg(MISCREG_SOFTINT, ~val & softint, tc);
|
||||
return setMiscReg(MISCREG_SOFTINT, ~val & softint, tc);
|
||||
case MISCREG_SOFTINT_SET:
|
||||
return setReg(MISCREG_SOFTINT, val | softint, tc);
|
||||
return setMiscReg(MISCREG_SOFTINT, val | softint, tc);
|
||||
|
||||
case MISCREG_TICK_CMPR:
|
||||
if (tickCompare == NULL)
|
||||
tickCompare = new TickCompareEvent(this, tc);
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
|
||||
cpu->deschedule(tickCompare);
|
||||
time = (tick_cmpr & mask(63)) - (tick & mask(63));
|
||||
|
@ -118,7 +119,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
case MISCREG_STICK_CMPR:
|
||||
if (sTickCompare == NULL)
|
||||
sTickCompare = new STickCompareEvent(this, tc);
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
|
||||
cpu->deschedule(sTickCompare);
|
||||
time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
|
@ -132,10 +133,10 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
break;
|
||||
|
||||
case MISCREG_PSTATE:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
|
||||
case MISCREG_PIL:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
checkSoftInt(tc);
|
||||
break;
|
||||
|
||||
|
@ -143,7 +144,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
panic("Shouldn't be writing HVER\n");
|
||||
|
||||
case MISCREG_HINTP:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if (hintp)
|
||||
cpu->postInterrupt(IT_HINTP, 0);
|
||||
else
|
||||
|
@ -152,12 +153,12 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
|
||||
case MISCREG_HTBA:
|
||||
// clear lower 7 bits on writes.
|
||||
setRegNoEffect(miscReg, val & ULL(~0x7FFF));
|
||||
setMiscRegNoEffect(miscReg, val & ULL(~0x7FFF));
|
||||
break;
|
||||
|
||||
case MISCREG_QUEUE_CPU_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if (cpu_mondo_head != cpu_mondo_tail)
|
||||
cpu->postInterrupt(IT_CPU_MONDO, 0);
|
||||
else
|
||||
|
@ -165,7 +166,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
break;
|
||||
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_DEV_MONDO_TAIL:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if (dev_mondo_head != dev_mondo_tail)
|
||||
cpu->postInterrupt(IT_DEV_MONDO, 0);
|
||||
else
|
||||
|
@ -173,7 +174,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
break;
|
||||
case MISCREG_QUEUE_RES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_RES_ERROR_TAIL:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if (res_error_head != res_error_tail)
|
||||
cpu->postInterrupt(IT_RES_ERROR, 0);
|
||||
else
|
||||
|
@ -181,14 +182,14 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
break;
|
||||
case MISCREG_QUEUE_NRES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_NRES_ERROR_TAIL:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
// This one doesn't have an interrupt to report to the guest OS
|
||||
break;
|
||||
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
if (hSTickCompare == NULL)
|
||||
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
|
||||
cpu->deschedule(hSTickCompare);
|
||||
time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
|
@ -203,7 +204,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
|
||||
case MISCREG_HPSTATE:
|
||||
// T1000 spec says impl. dependent val must always be 1
|
||||
setRegNoEffect(miscReg, val | HPSTATE::id);
|
||||
setMiscRegNoEffect(miscReg, val | HPSTATE::id);
|
||||
#if FULL_SYSTEM
|
||||
if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
|
||||
cpu->postInterrupt(IT_TRAP_LEVEL_ZERO, 0);
|
||||
|
@ -212,13 +213,13 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
#endif
|
||||
break;
|
||||
case MISCREG_HTSTATE:
|
||||
setRegNoEffect(miscReg, val);
|
||||
setMiscRegNoEffect(miscReg, val);
|
||||
break;
|
||||
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
if (bits(val,2,2))
|
||||
panic("No support for setting spec_en bit\n");
|
||||
setRegNoEffect(miscReg, bits(val,0,0));
|
||||
setMiscRegNoEffect(miscReg, bits(val,0,0));
|
||||
if (!bits(val,0,0)) {
|
||||
DPRINTF(Quiesce, "Cpu executed quiescing instruction\n");
|
||||
// Time to go to sleep
|
||||
|
@ -235,7 +236,7 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
|
|||
}
|
||||
|
||||
MiscReg
|
||||
MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
|
||||
ISA::readFSReg(int miscReg, ThreadContext * tc)
|
||||
{
|
||||
uint64_t temp;
|
||||
|
||||
|
@ -257,10 +258,10 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
|
|||
case MISCREG_HINTP:
|
||||
case MISCREG_HTSTATE:
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
return readRegNoEffect(miscReg) ;
|
||||
return readMiscRegNoEffect(miscReg) ;
|
||||
|
||||
case MISCREG_HTBA:
|
||||
return readRegNoEffect(miscReg) & ULL(~0x7FFF);
|
||||
return readMiscRegNoEffect(miscReg) & ULL(~0x7FFF);
|
||||
case MISCREG_HVER:
|
||||
// XXX set to match Legion
|
||||
return ULL(0x3e) << 48 |
|
||||
|
@ -275,7 +276,7 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
|
|||
int x;
|
||||
sys = tc->getSystemPtr();
|
||||
|
||||
temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative);
|
||||
temp = readMiscRegNoEffect(miscReg) & (STS::active | STS::speculative);
|
||||
// Check that the CPU array is fully populated
|
||||
// (by calling getNumCPus())
|
||||
assert(sys->numContexts() > tc->contextId());
|
||||
|
@ -309,13 +310,13 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
|
|||
}
|
||||
|
||||
void
|
||||
MiscRegFile::processTickCompare(ThreadContext *tc)
|
||||
ISA::processTickCompare(ThreadContext *tc)
|
||||
{
|
||||
panic("tick compare not implemented\n");
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::processSTickCompare(ThreadContext *tc)
|
||||
ISA::processSTickCompare(ThreadContext *tc)
|
||||
{
|
||||
BaseCPU *cpu = tc->getCpuPtr();
|
||||
|
||||
|
@ -331,14 +332,14 @@ MiscRegFile::processSTickCompare(ThreadContext *tc)
|
|||
DPRINTF(Timer, "STick compare cycle reached at %#x\n",
|
||||
(stick_cmpr & mask(63)));
|
||||
if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
|
||||
setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
|
||||
setMiscReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
|
||||
}
|
||||
} else
|
||||
cpu->schedule(sTickCompare, curTick + ticks * cpu->ticks(1));
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::processHSTickCompare(ThreadContext *tc)
|
||||
ISA::processHSTickCompare(ThreadContext *tc)
|
||||
{
|
||||
BaseCPU *cpu = tc->getCpuPtr();
|
||||
|
||||
|
@ -357,7 +358,7 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc)
|
|||
DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
|
||||
(stick_cmpr & mask(63)));
|
||||
if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
|
||||
setReg(MISCREG_HINTP, 1, tc);
|
||||
setMiscReg(MISCREG_HINTP, 1, tc);
|
||||
}
|
||||
// Need to do something to cause interrupt to happen here !!! @todo
|
||||
} else
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include "arch/sparc/faults.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "arch/sparc/registers.hh"
|
||||
#include "arch/sparc/tlb.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/bitfield.hh"
|
||||
|
|
Loading…
Reference in a new issue