Merge zizzer.eecs.umich.edu:/bk/newmem
into ewok.(none):/home/gblack/m5/newmemo3 src/sim/byteswap.hh: Hand Merge --HG-- extra : convert_revision : 640d33ad0c416934e8a5107768e7f1dce6709ca8
This commit is contained in:
commit
1352e55ceb
41 changed files with 1075 additions and 337 deletions
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2006 The Regents of The University of Michigan
|
||||
# Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -38,6 +38,14 @@ class CowIdeDisk(IdeDisk):
|
|||
def childImage(self, ci):
|
||||
self.image.child.image_file = ci
|
||||
|
||||
class CowMmDisk(MmDisk):
|
||||
image = CowDiskImage(child=RawDiskImage(read_only=True),
|
||||
read_only=False)
|
||||
|
||||
def childImage(self, ci):
|
||||
self.image.child.image_file = ci
|
||||
|
||||
|
||||
class BaseTsunami(Tsunami):
|
||||
ethernet = NSGigE(configdata=NSGigEPciData(),
|
||||
pci_bus=0, pci_dev=1, pci_func=0)
|
||||
|
@ -100,8 +108,9 @@ def makeSparcSystem(mem_mode, mdesc = None):
|
|||
self.hypervisor_desc.port = self.membus.port
|
||||
self.partition_desc.port = self.membus.port
|
||||
self.intrctrl = IntrControl()
|
||||
self.mem_mode = mem_mode
|
||||
|
||||
self.disk0 = CowMmDisk()
|
||||
self.disk0.childImage(disk('disk.s10hw2'))
|
||||
self.disk0.pio = self.iobus.port
|
||||
self.reset_bin = binary('reset.bin')
|
||||
self.hypervisor_bin = binary('q.bin')
|
||||
self.openboot_bin = binary('openboot.bin')
|
||||
|
|
|
@ -52,6 +52,11 @@ namespace AlphaISA
|
|||
newInfoSet = false;
|
||||
}
|
||||
|
||||
void post(int int_type)
|
||||
{
|
||||
// sparc only
|
||||
}
|
||||
|
||||
void post(int int_num, int index)
|
||||
{
|
||||
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace AlphaISA {
|
|||
bool _kre() const { return (entry >> 8) & 0x1; }
|
||||
bool _nomb() const { return (entry >> 7) & 0x1; }
|
||||
int _gh() const { return (entry >> 5) & 0x3; }
|
||||
bool _asm() const { return (entry >> 4) & 0x1; }
|
||||
bool _asm_() const { return (entry >> 4) & 0x1; }
|
||||
bool _foe() const { return (entry >> 3) & 0x1; }
|
||||
bool _fow() const { return (entry >> 2) & 0x1; }
|
||||
bool _for() const { return (entry >> 1) & 0x1; }
|
||||
|
|
|
@ -179,26 +179,23 @@ namespace SparcISA
|
|||
(asi == ASI_LDTX_PL) ||
|
||||
(asi == ASI_LDTX_SL) ||
|
||||
(asi == ASI_BLK_PL) ||
|
||||
(asi == ASI_BLK_SL);
|
||||
(asi == ASI_BLK_SL) ||
|
||||
(asi == ASI_LTX_L);
|
||||
}
|
||||
|
||||
bool AsiIsTwin(ASI asi)
|
||||
{
|
||||
return
|
||||
(asi == ASI_QUAD_LDD) ||
|
||||
(asi == ASI_LDTX_AIUP) ||
|
||||
(asi == ASI_LDTX_AIUS) ||
|
||||
(asi == ASI_LDTX_REAL) ||
|
||||
(asi == ASI_LDTX_N) ||
|
||||
(asi == ASI_LDTX_AIUP_L) ||
|
||||
(asi == ASI_LDTX_AIUS_L) ||
|
||||
(asi == ASI_LDTX_REAL_L) ||
|
||||
(asi == ASI_LDTX_NL) ||
|
||||
(asi == ASI_LDTX_P) ||
|
||||
(asi == ASI_LDTX_S) ||
|
||||
(asi == ASI_LDTX_PL) ||
|
||||
(asi == ASI_LDTX_SL) ||
|
||||
(asi == ASI_LTX_L);
|
||||
(asi >= ASI_LDTX_AIUP &&
|
||||
asi <= ASI_LDTX_N &&
|
||||
asi != ASI_QUEUE) ||
|
||||
(asi >= ASI_LDTX_AIUP_L &&
|
||||
asi <= ASI_LDTX_NL &&
|
||||
asi != 0x2D) ||
|
||||
asi == ASI_LDTX_P ||
|
||||
asi == ASI_LDTX_S ||
|
||||
asi == ASI_LDTX_PL ||
|
||||
asi == ASI_LDTX_SL;
|
||||
}
|
||||
|
||||
bool AsiIsPartialStore(ASI asi)
|
||||
|
|
|
@ -197,7 +197,7 @@ template<> SparcFaultBase::FaultVals
|
|||
|
||||
template<> SparcFaultBase::FaultVals
|
||||
SparcFault<InterruptLevelN>::vals =
|
||||
{"interrupt_level_n", 0x041, 0, {P, P, SH}};
|
||||
{"interrupt_level_n", 0x040, 0, {P, P, SH}};
|
||||
|
||||
template<> SparcFaultBase::FaultVals
|
||||
SparcFault<HstickMatch>::vals =
|
||||
|
@ -240,7 +240,7 @@ template<> SparcFaultBase::FaultVals
|
|||
{"dev_mondo", 0x07D, 1611, {P, P, SH}};
|
||||
|
||||
template<> SparcFaultBase::FaultVals
|
||||
SparcFault<ResumeableError>::vals =
|
||||
SparcFault<ResumableError>::vals =
|
||||
{"resume_error", 0x07E, 3330, {P, P, SH}};
|
||||
|
||||
template<> SparcFaultBase::FaultVals
|
||||
|
@ -342,22 +342,8 @@ void doREDFault(ThreadContext *tc, TrapType tt)
|
|||
//Update GL
|
||||
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
|
||||
|
||||
//set PSTATE.mm to 00
|
||||
//set PSTATE.pef to 1
|
||||
PSTATE |= (1 << 4);
|
||||
//set PSTATE.am to 0
|
||||
PSTATE &= ~(1 << 3);
|
||||
/* //set PSTATE.priv to 0
|
||||
PSTATE &= ~(1 << 2);*/
|
||||
//set PSTATE.ie to 0
|
||||
//PSTATE.priv is set to 1 here. The manual says it should be 0, but
|
||||
//Legion sets it to 1.
|
||||
PSTATE |= (1 << 2);
|
||||
//set PSTATE.cle to 0
|
||||
PSTATE &= ~(1 << 9);
|
||||
//PSTATE.tle is unchanged
|
||||
//XXX Where is the tct bit?
|
||||
//set PSTATE.tct to 0
|
||||
PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit
|
||||
PSTATE |= (1 << 4); //set PSTATE.pef to 1
|
||||
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||
|
||||
//set HPSTATE.red to 1
|
||||
|
@ -440,64 +426,45 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
|
|||
tc->setMiscReg(MISCREG_TT, tt);
|
||||
|
||||
//Update the global register level
|
||||
if(!gotoHpriv)
|
||||
if (!gotoHpriv)
|
||||
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL));
|
||||
else
|
||||
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
|
||||
|
||||
//PSTATE.mm is unchanged
|
||||
//PSTATE.pef = whether or not an fpu is present
|
||||
//XXX We'll say there's one present, even though there aren't
|
||||
//implementations for a decent number of the instructions
|
||||
PSTATE |= (1 << 4);
|
||||
//PSTATE.am = 0
|
||||
PSTATE &= ~(1 << 3);
|
||||
if(!gotoHpriv)
|
||||
{
|
||||
//PSTATE.priv = 1
|
||||
PSTATE |= (1 << 2);
|
||||
//PSTATE.cle = PSTATE.tle
|
||||
replaceBits(PSTATE, 9, 9, PSTATE >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
//PSTATE.priv = 0
|
||||
//PSTATE.priv is set to 1 here. The manual says it should be 0, but
|
||||
//Legion sets it to 1.
|
||||
PSTATE |= (1 << 2);
|
||||
//PSTATE.cle = 0
|
||||
PSTATE &= ~(1 << 9);
|
||||
}
|
||||
//PSTATE.ie = 0
|
||||
PSTATE &= ~(1 << 1);
|
||||
PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present
|
||||
PSTATE &= ~(1 << 3); //PSTATE.am = 0
|
||||
PSTATE &= ~(1 << 1); //PSTATE.ie = 0
|
||||
//PSTATE.tle is unchanged
|
||||
//PSTATE.tct = 0
|
||||
//XXX Where exactly is this field?
|
||||
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||
|
||||
if(gotoHpriv)
|
||||
if (gotoHpriv)
|
||||
{
|
||||
//HPSTATE.red = 0
|
||||
HPSTATE &= ~(1 << 5);
|
||||
//HPSTATE.hpriv = 1
|
||||
HPSTATE |= (1 << 2);
|
||||
//HPSTATE.ibe = 0
|
||||
HPSTATE &= ~(1 << 10);
|
||||
PSTATE &= ~(1 << 9); // PSTATE.cle = 0
|
||||
//The manual says PSTATE.priv should be 0, but Legion leaves it alone
|
||||
HPSTATE &= ~(1 << 5); //HPSTATE.red = 0
|
||||
HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1
|
||||
HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0
|
||||
//HPSTATE.tlz is unchanged
|
||||
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
|
||||
} else { // we are going to priv
|
||||
PSTATE |= (1 << 2); //PSTATE.priv = 1
|
||||
replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle
|
||||
}
|
||||
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
|
||||
|
||||
|
||||
bool changedCWP = true;
|
||||
if(tt == 0x24)
|
||||
if (tt == 0x24)
|
||||
CWP++;
|
||||
else if(0x80 <= tt && tt <= 0xbf)
|
||||
else if (0x80 <= tt && tt <= 0xbf)
|
||||
CWP += (CANSAVE + 2);
|
||||
else if(0xc0 <= tt && tt <= 0xff)
|
||||
else if (0xc0 <= tt && tt <= 0xff)
|
||||
CWP--;
|
||||
else
|
||||
changedCWP = false;
|
||||
|
||||
if(changedCWP)
|
||||
if (changedCWP)
|
||||
{
|
||||
CWP = (CWP + NWindows) % NWindows;
|
||||
tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
|
||||
|
@ -538,45 +505,45 @@ void SparcFaultBase::invoke(ThreadContext * tc)
|
|||
|
||||
//We can refer to this to see what the trap level -was-, but something
|
||||
//in the middle could change it in the regfile out from under us.
|
||||
MiscReg TL = tc->readMiscReg(MISCREG_TL);
|
||||
MiscReg TT = tc->readMiscReg(MISCREG_TT);
|
||||
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE);
|
||||
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
|
||||
MiscReg tl = tc->readMiscReg(MISCREG_TL);
|
||||
MiscReg tt = tc->readMiscReg(MISCREG_TT);
|
||||
MiscReg pstate = tc->readMiscReg(MISCREG_PSTATE);
|
||||
MiscReg hpstate = tc->readMiscReg(MISCREG_HPSTATE);
|
||||
|
||||
Addr PC, NPC;
|
||||
|
||||
PrivilegeLevel current;
|
||||
if(HPSTATE & (1 << 2))
|
||||
if (hpstate & HPSTATE::hpriv)
|
||||
current = Hyperprivileged;
|
||||
else if(PSTATE & (1 << 2))
|
||||
else if (pstate & PSTATE::priv)
|
||||
current = Privileged;
|
||||
else
|
||||
current = User;
|
||||
|
||||
PrivilegeLevel level = getNextLevel(current);
|
||||
|
||||
if(HPSTATE & (1 << 5) || TL == MaxTL - 1) {
|
||||
if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) {
|
||||
getREDVector(5, PC, NPC);
|
||||
doREDFault(tc, TT);
|
||||
doREDFault(tc, tt);
|
||||
//This changes the hpstate and pstate, so we need to make sure we
|
||||
//save the old version on the trap stack in doREDFault.
|
||||
enterREDState(tc);
|
||||
} else if(TL == MaxTL) {
|
||||
} else if (tl == MaxTL) {
|
||||
panic("Should go to error state here.. crap\n");
|
||||
//Do error_state somehow?
|
||||
//Probably inject a WDR fault using the interrupt mechanism.
|
||||
//What should the PC and NPC be set to?
|
||||
} else if(TL > MaxPTL && level == Privileged) {
|
||||
} else if (tl > MaxPTL && level == Privileged) {
|
||||
//guest_watchdog fault
|
||||
doNormalFault(tc, trapType(), true);
|
||||
getHyperVector(tc, PC, NPC, 2);
|
||||
} else if(level == Hyperprivileged ||
|
||||
} else if (level == Hyperprivileged ||
|
||||
level == Privileged && trapType() >= 384) {
|
||||
doNormalFault(tc, trapType(), true);
|
||||
getHyperVector(tc, PC, NPC, trapType());
|
||||
} else {
|
||||
doNormalFault(tc, trapType(), false);
|
||||
getPrivVector(tc, PC, NPC, trapType(), TL+1);
|
||||
getPrivVector(tc, PC, NPC, trapType(), tl+1);
|
||||
}
|
||||
|
||||
tc->setPC(PC);
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
* Kevin Lim
|
||||
*/
|
||||
|
||||
#ifndef __ALPHA_FAULTS_HH__
|
||||
#define __ALPHA_FAULTS_HH__
|
||||
#ifndef __SPARC_FAULTS_HH__
|
||||
#define __SPARC_FAULTS_HH__
|
||||
|
||||
#include "sim/faults.hh"
|
||||
|
||||
|
@ -210,7 +210,7 @@ class CpuMondo : public SparcFault<CpuMondo> {};
|
|||
|
||||
class DevMondo : public SparcFault<DevMondo> {};
|
||||
|
||||
class ResumeableError : public SparcFault<ResumeableError> {};
|
||||
class ResumableError : public SparcFault<ResumableError> {};
|
||||
|
||||
class SpillNNormal : public EnumeratedFault<SpillNNormal>
|
||||
{
|
||||
|
@ -280,4 +280,4 @@ static inline Fault genAlignmentFault()
|
|||
|
||||
} // SparcISA namespace
|
||||
|
||||
#endif // __FAULTS_HH__
|
||||
#endif // __SPARC_FAULTS_HH__
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_SPARC_INTERRUPT_HH__
|
||||
|
@ -34,19 +32,45 @@
|
|||
#include "arch/sparc/faults.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
|
||||
|
||||
namespace SparcISA
|
||||
{
|
||||
|
||||
enum interrupts_t {
|
||||
trap_level_zero,
|
||||
hstick_match,
|
||||
interrupt_vector,
|
||||
cpu_mondo,
|
||||
dev_mondo,
|
||||
resumable_error,
|
||||
soft_interrupt,
|
||||
num_interrupt_types
|
||||
};
|
||||
|
||||
class Interrupts
|
||||
{
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
bool interrupts[num_interrupt_types];
|
||||
int numPosted;
|
||||
|
||||
public:
|
||||
Interrupts()
|
||||
{
|
||||
|
||||
for (int i = 0; i < num_interrupt_types; ++i) {
|
||||
interrupts[i] = false;
|
||||
}
|
||||
numPosted = 0;
|
||||
}
|
||||
|
||||
void post(int int_type)
|
||||
{
|
||||
if (int_type < 0 || int_type >= num_interrupt_types)
|
||||
panic("posting unknown interrupt!\n");
|
||||
interrupts[int_type] = true;
|
||||
++numPosted;
|
||||
}
|
||||
|
||||
void post(int int_num, int index)
|
||||
{
|
||||
|
||||
|
@ -64,9 +88,7 @@ namespace SparcISA
|
|||
|
||||
bool check_interrupts(ThreadContext * tc) const
|
||||
{
|
||||
// so far only handle softint interrupts
|
||||
int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
|
||||
if (int_level)
|
||||
if (numPosted)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -74,20 +96,96 @@ namespace SparcISA
|
|||
|
||||
Fault getInterrupt(ThreadContext * tc)
|
||||
{
|
||||
// conditioning the softint interrups
|
||||
if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) {
|
||||
// if running in privileged mode, then pend the interrupt
|
||||
return NoFault;
|
||||
} else {
|
||||
int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
|
||||
if ((int_level <= tc->readMiscReg(MISCREG_PIL)) ||
|
||||
!(tc->readMiscReg(MISCREG_PSTATE) & ie)) {
|
||||
// if PIL or no interrupt enabled, then pend the interrupt
|
||||
return NoFault;
|
||||
int hpstate = tc->readMiscReg(MISCREG_HPSTATE);
|
||||
int pstate = tc->readMiscReg(MISCREG_PSTATE);
|
||||
bool ie = pstate & PSTATE::ie;
|
||||
|
||||
// THESE ARE IN ORDER OF PRIORITY
|
||||
// since there are early returns, and the highest
|
||||
// priority interrupts should get serviced,
|
||||
// it is v. important that new interrupts are inserted
|
||||
// in the right order of processing
|
||||
if (hpstate & HPSTATE::hpriv) {
|
||||
if (ie) {
|
||||
if (interrupts[hstick_match]) {
|
||||
if (tc->readMiscReg(MISCREG_HINTP) & 1) {
|
||||
interrupts[hstick_match] = false;
|
||||
--numPosted;
|
||||
return new HstickMatch;
|
||||
}
|
||||
}
|
||||
if (interrupts[interrupt_vector]) {
|
||||
interrupts[interrupt_vector] = false;
|
||||
--numPosted;
|
||||
//HAVEN'T IMPLed THIS YET
|
||||
return NoFault;
|
||||
}
|
||||
} else {
|
||||
return new InterruptLevelN(int_level);
|
||||
if (interrupts[hstick_match]) {
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (interrupts[trap_level_zero]) {
|
||||
if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
|
||||
interrupts[trap_level_zero] = false;
|
||||
--numPosted;
|
||||
return new TrapLevelZero;
|
||||
}
|
||||
}
|
||||
if (interrupts[hstick_match]) {
|
||||
if (tc->readMiscReg(MISCREG_HINTP) & 1) {
|
||||
interrupts[hstick_match] = false;
|
||||
--numPosted;
|
||||
return new HstickMatch;
|
||||
}
|
||||
}
|
||||
if (ie) {
|
||||
if (interrupts[cpu_mondo]) {
|
||||
interrupts[cpu_mondo] = false;
|
||||
--numPosted;
|
||||
return new CpuMondo;
|
||||
}
|
||||
if (interrupts[dev_mondo]) {
|
||||
interrupts[dev_mondo] = false;
|
||||
--numPosted;
|
||||
return new DevMondo;
|
||||
}
|
||||
if (interrupts[soft_interrupt]) {
|
||||
int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
|
||||
// it seems that interrupt vectors are right in
|
||||
// the middle of interrupt levels with regard to
|
||||
// priority, so have to check
|
||||
if ((il < 6) &&
|
||||
interrupts[interrupt_vector]) {
|
||||
// may require more details here since there
|
||||
// may be lots of interrupts embedded in an
|
||||
// platform interrupt vector
|
||||
interrupts[interrupt_vector] = false;
|
||||
--numPosted;
|
||||
//HAVEN'T IMPLed YET
|
||||
return NoFault;
|
||||
} else {
|
||||
if (il > tc->readMiscReg(MISCREG_PIL)) {
|
||||
uint64_t si = tc->readMiscReg(MISCREG_SOFTINT);
|
||||
uint64_t more = si & ~(1 << (il + 1));
|
||||
if (!InterruptLevel(more)) {
|
||||
interrupts[soft_interrupt] = false;
|
||||
--numPosted;
|
||||
}
|
||||
return new InterruptLevelN(il);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (interrupts[resumable_error]) {
|
||||
interrupts[resumable_error] = false;
|
||||
--numPosted;
|
||||
return new ResumableError;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
void updateIntrInfo(ThreadContext * tc)
|
||||
|
|
|
@ -120,6 +120,8 @@ void IntRegFile::setReg(int intReg, const IntReg &val)
|
|||
void IntRegFile::setCWP(int cwp)
|
||||
{
|
||||
int index = ((NWindows - cwp) % NWindows) * 2;
|
||||
if (index < 0)
|
||||
panic("Index less than 0. cwp=%d nwin=%d\n", cwp, NWindows);
|
||||
offset[Outputs] = FrameOffset + (index * RegsPerFrame);
|
||||
offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
|
||||
offset[Inputs] = FrameOffset +
|
||||
|
@ -137,6 +139,11 @@ void IntRegFile::setGlobals(int gl)
|
|||
|
||||
regView[Globals] = regGlobals[gl];
|
||||
offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
|
||||
|
||||
if (regView[Globals] == regView[Inputs] ||
|
||||
regView[Globals] == regView[Locals] ||
|
||||
regView[Globals] == regView[Outputs] )
|
||||
panic("Two register arrays set to the same thing!\n");
|
||||
}
|
||||
|
||||
void IntRegFile::serialize(std::ostream &os)
|
||||
|
|
|
@ -190,7 +190,7 @@ decode OP default Unknown::unknown()
|
|||
}});
|
||||
0x0B: smul({{
|
||||
Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
|
||||
Y = Rd.sdw;
|
||||
Y = Rd.sdw<63:32>;
|
||||
}});
|
||||
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
|
||||
0x0D: udivx({{
|
||||
|
@ -471,12 +471,12 @@ decode OP default Unknown::unknown()
|
|||
//0x11-0x1F should cause an illegal instruction exception
|
||||
}
|
||||
0x2B: BasicOperate::flushw({{
|
||||
if(NWindows - 2 - Cansave == 0)
|
||||
if(NWindows - 2 - Cansave != 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
fault = new SpillNOther(Wstate<5:3>);
|
||||
fault = new SpillNOther(4*Wstate<5:3>);
|
||||
else
|
||||
fault = new SpillNNormal(Wstate<2:0>);
|
||||
fault = new SpillNNormal(4*Wstate<2:0>);
|
||||
}
|
||||
}});
|
||||
0x2C: decode MOVCC3
|
||||
|
@ -891,9 +891,9 @@ decode OP default Unknown::unknown()
|
|||
if(Canrestore == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
fault = new FillNOther(Wstate<5:3>);
|
||||
fault = new FillNOther(4*Wstate<5:3>);
|
||||
else
|
||||
fault = new FillNNormal(Wstate<2:0>);
|
||||
fault = new FillNNormal(4*Wstate<2:0>);
|
||||
}
|
||||
//Check for alignment faults
|
||||
else if(target & 0x3)
|
||||
|
@ -941,9 +941,9 @@ decode OP default Unknown::unknown()
|
|||
if(Cansave == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
fault = new SpillNOther(Wstate<5:3>);
|
||||
fault = new SpillNOther(4*Wstate<5:3>);
|
||||
else
|
||||
fault = new SpillNNormal(Wstate<2:0>);
|
||||
fault = new SpillNNormal(4*Wstate<2:0>);
|
||||
}
|
||||
else if(Cleanwin - Canrestore == 0)
|
||||
{
|
||||
|
@ -961,9 +961,9 @@ decode OP default Unknown::unknown()
|
|||
if(Canrestore == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
fault = new FillNOther(Wstate<5:3>);
|
||||
fault = new FillNOther(4*Wstate<5:3>);
|
||||
else
|
||||
fault = new FillNNormal(Wstate<2:0>);
|
||||
fault = new FillNNormal(4*Wstate<2:0>);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1040,6 +1040,12 @@ decode OP default Unknown::unknown()
|
|||
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
||||
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
|
||||
0x13: decode EXT_ASI {
|
||||
//ASI_LDTD_AIUP
|
||||
0x22: TwinLoad::ldtx_aiup(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
//ASI_LDTD_AIUS
|
||||
0x23: TwinLoad::ldtx_aius(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
//ASI_QUAD_LDD
|
||||
0x24: TwinLoad::ldtx_quad_ldd(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
|
@ -1058,6 +1064,12 @@ decode OP default Unknown::unknown()
|
|||
//ASI_LDTX_N_L
|
||||
0x2F: TwinLoad::ldtx_n_l(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
//ASI_LDTX_P
|
||||
0xE2: TwinLoad::ldtx_p(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
//ASI_LDTX_S
|
||||
0xE3: TwinLoad::ldtx_s(
|
||||
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
|
||||
default: ldtwa({{
|
||||
uint64_t val = Mem.udw;
|
||||
RdLow = val<31:0>;
|
||||
|
|
|
@ -451,6 +451,8 @@ let {{
|
|||
flag_code = ''
|
||||
if (microPc == 7):
|
||||
flag_code = "flags[IsLastMicroOp] = true;"
|
||||
elif (microPc == 0):
|
||||
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
|
||||
else:
|
||||
flag_code = "flags[IsDelayedCommit] = true;"
|
||||
pcedCode = matcher.sub("Frd_%d" % microPc, code)
|
||||
|
@ -492,7 +494,7 @@ let {{
|
|||
flag_code = "flags[IsLastMicroOp] = true;"
|
||||
pcedCode = matcher.sub("RdHigh", code)
|
||||
else:
|
||||
flag_code = "flags[IsDelayedCommit] = true;"
|
||||
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
|
||||
pcedCode = matcher.sub("RdLow", code)
|
||||
iop = InstObjParams(name, Name, 'TwinMem',
|
||||
{"code": pcedCode, "ea_code": addrCalcReg,
|
||||
|
|
|
@ -96,15 +96,6 @@ namespace SparcISA
|
|||
StaticInstPtr decodeInst(ExtMachInst);
|
||||
|
||||
#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
|
||||
|
|
|
@ -215,7 +215,7 @@ MiscReg MiscRegFile::readReg(int miscReg)
|
|||
case MISCREG_HTSTATE:
|
||||
return htstate[tl-1];
|
||||
case MISCREG_HINTP:
|
||||
panic("HINTP not implemented\n");
|
||||
return hintp;
|
||||
case MISCREG_HTBA:
|
||||
return htba;
|
||||
case MISCREG_HVER:
|
||||
|
@ -322,13 +322,13 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
|
|||
// I'm not sure why legion ignores the lowest two bits, but we'll go
|
||||
// with it
|
||||
// change from curCycle() to instCount() until we're done with legion
|
||||
DPRINTFN("Instruction Count when TICK read: %#X stick=%#X\n",
|
||||
DPRINTF(Timer, "Instruction Count when TICK read: %#X stick=%#X\n",
|
||||
tc->getCpuPtr()->instCount(), stick);
|
||||
return mbits(tc->getCpuPtr()->instCount() + (int32_t)stick,62,2) |
|
||||
return mbits(tc->getCpuPtr()->instCount() + (int64_t)stick,62,2) |
|
||||
mbits(tick,63,63);
|
||||
case MISCREG_FPRS:
|
||||
warn("FPRS register read and FPU stuff not really implemented\n");
|
||||
return 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");
|
||||
|
@ -386,7 +386,6 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
|||
asi = val;
|
||||
break;
|
||||
case MISCREG_FPRS:
|
||||
warn("FPU not really implemented writing %#X to FPRS\n", val);
|
||||
fprs = val;
|
||||
break;
|
||||
case MISCREG_TICK:
|
||||
|
@ -400,7 +399,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
|||
gsr = val;
|
||||
break;
|
||||
case MISCREG_SOFTINT:
|
||||
softint |= val;
|
||||
softint = val;
|
||||
break;
|
||||
case MISCREG_TICK_CMPR:
|
||||
tick_cmpr = val;
|
||||
|
@ -470,7 +469,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
|||
htstate[tl-1] = val;
|
||||
break;
|
||||
case MISCREG_HINTP:
|
||||
panic("HINTP not implemented\n");
|
||||
hintp = val;
|
||||
case MISCREG_HTBA:
|
||||
htba = val;
|
||||
break;
|
||||
|
@ -609,6 +608,8 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
|
|||
void MiscRegFile::setRegWithEffect(int miscReg,
|
||||
const MiscReg &val, ThreadContext * tc)
|
||||
{
|
||||
MiscReg new_val = val;
|
||||
|
||||
switch (miscReg) {
|
||||
case MISCREG_STICK:
|
||||
case MISCREG_TICK:
|
||||
|
@ -616,7 +617,7 @@ void MiscRegFile::setRegWithEffect(int miscReg,
|
|||
// use stick for offset and tick for holding intrrupt bit
|
||||
stick = mbits(val,62,0) - tc->getCpuPtr()->instCount();
|
||||
tick = mbits(val,63,63);
|
||||
DPRINTFN("Writing TICK=%#X\n", val);
|
||||
DPRINTF(Timer, "Writing TICK=%#X\n", val);
|
||||
break;
|
||||
case MISCREG_FPRS:
|
||||
//Configure the fpu based on the fprs
|
||||
|
@ -631,13 +632,16 @@ void MiscRegFile::setRegWithEffect(int miscReg,
|
|||
tl = val;
|
||||
return;
|
||||
case MISCREG_CWP:
|
||||
tc->changeRegFileContext(CONTEXT_CWP, val);
|
||||
new_val = val > NWindows ? NWindows - 1 : val;
|
||||
tc->changeRegFileContext(CONTEXT_CWP, new_val);
|
||||
break;
|
||||
case MISCREG_GL:
|
||||
tc->changeRegFileContext(CONTEXT_GLOBALS, val);
|
||||
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:
|
||||
|
@ -666,7 +670,7 @@ void MiscRegFile::setRegWithEffect(int miscReg,
|
|||
panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val);
|
||||
#endif
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
setReg(miscReg, new_val);
|
||||
}
|
||||
|
||||
void MiscRegFile::serialize(std::ostream & os)
|
||||
|
|
|
@ -142,24 +142,26 @@ namespace SparcISA
|
|||
MISCREG_NUMMISCREGS
|
||||
};
|
||||
|
||||
enum HPStateFields {
|
||||
id = 0x800, // this impl. dependent (id) field must always be '1' for T1000
|
||||
ibe = 0x400,
|
||||
red = 0x20,
|
||||
hpriv = 0x4,
|
||||
tlz = 0x1
|
||||
struct HPSTATE {
|
||||
const static uint64_t id = 0x800; // this impl. dependent (id) field m
|
||||
const static uint64_t ibe = 0x400;
|
||||
const static uint64_t red = 0x20;
|
||||
const static uint64_t hpriv = 0x4;
|
||||
const static uint64_t tlz = 0x1;
|
||||
};
|
||||
|
||||
enum PStateFields {
|
||||
cle = 0x200,
|
||||
tle = 0x100,
|
||||
mm = 0xC0,
|
||||
pef = 0x10,
|
||||
am = 0x8,
|
||||
priv = 0x4,
|
||||
ie = 0x2
|
||||
|
||||
struct PSTATE {
|
||||
const static int cle = 0x200;
|
||||
const static int tle = 0x100;
|
||||
const static int mm = 0xC0;
|
||||
const static int pef = 0x10;
|
||||
const static int am = 0x8;
|
||||
const static int priv = 0x4;
|
||||
const static int ie = 0x2;
|
||||
};
|
||||
|
||||
|
||||
const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
|
||||
const int NumMiscRegs = MISCREG_NUMMISCREGS;
|
||||
|
||||
|
|
|
@ -255,10 +255,10 @@ int SparcISA::InterruptLevel(uint64_t softint)
|
|||
if (softint & 0x10000 || softint & 0x1)
|
||||
return 14;
|
||||
|
||||
int level = 14;
|
||||
while (level >= 0 && !(1 << (level + 1) & softint))
|
||||
int level = 15;
|
||||
while (level > 0 && !(1 << level & softint))
|
||||
level--;
|
||||
if (1 << (level + 1) & softint)
|
||||
if (1 << level & softint)
|
||||
return level;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -81,21 +81,45 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
|
|||
|
||||
MapIter i;
|
||||
TlbEntry *new_entry = NULL;
|
||||
TlbRange tr;
|
||||
// TlbRange tr;
|
||||
int x;
|
||||
|
||||
cacheValid = false;
|
||||
tr.va = va;
|
||||
va &= ~(PTE.size()-1);
|
||||
/* tr.va = va;
|
||||
tr.size = PTE.size() - 1;
|
||||
tr.contextId = context_id;
|
||||
tr.partitionId = partition_id;
|
||||
tr.real = real;
|
||||
|
||||
*/
|
||||
|
||||
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n",
|
||||
va, PTE.paddr(), partition_id, context_id, (int)real, entry);
|
||||
|
||||
// Demap any entry that conflicts
|
||||
for (x = 0; x < size; x++) {
|
||||
if (tlb[x].range.real == real &&
|
||||
tlb[x].range.partitionId == partition_id &&
|
||||
tlb[x].range.va < va + PTE.size() - 1 &&
|
||||
tlb[x].range.va + tlb[x].range.size >= va &&
|
||||
(real || tlb[x].range.contextId == context_id ))
|
||||
{
|
||||
if (tlb[x].valid) {
|
||||
freeList.push_front(&tlb[x]);
|
||||
DPRINTF(TLB, "TLB: Conflicting entry %#X , deleting it\n", x);
|
||||
|
||||
tlb[x].valid = false;
|
||||
if (tlb[x].used) {
|
||||
tlb[x].used = false;
|
||||
usedEntries--;
|
||||
}
|
||||
lookupTable.erase(tlb[x].range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
i = lookupTable.find(tr);
|
||||
if (i != lookupTable.end()) {
|
||||
i->second->valid = false;
|
||||
|
@ -108,7 +132,7 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
|
|||
i->second);
|
||||
lookupTable.erase(i);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (entry != -1) {
|
||||
assert(entry < size && entry >= 0);
|
||||
|
@ -127,7 +151,6 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
|
|||
} while (tlb[x].pte.locked());
|
||||
lastReplaced = x;
|
||||
new_entry = &tlb[x];
|
||||
lookupTable.erase(new_entry->range);
|
||||
}
|
||||
/*
|
||||
for (x = 0; x < size; x++) {
|
||||
|
@ -142,10 +165,15 @@ insertAllLocked:
|
|||
// Update the last ently if their all locked
|
||||
if (!new_entry) {
|
||||
new_entry = &tlb[size-1];
|
||||
lookupTable.erase(new_entry->range);
|
||||
}
|
||||
|
||||
freeList.remove(new_entry);
|
||||
if (new_entry->valid && new_entry->used)
|
||||
usedEntries--;
|
||||
|
||||
lookupTable.erase(new_entry->range);
|
||||
|
||||
|
||||
DPRINTF(TLB, "Using entry: %#X\n", new_entry);
|
||||
|
||||
assert(PTE.valid());
|
||||
|
@ -315,10 +343,12 @@ TLB::invalidateAll()
|
|||
cacheValid = false;
|
||||
|
||||
freeList.clear();
|
||||
lookupTable.clear();
|
||||
for (x = 0; x < size; x++) {
|
||||
if (tlb[x].valid == true)
|
||||
freeList.push_back(&tlb[x]);
|
||||
tlb[x].valid = false;
|
||||
tlb[x].used = false;
|
||||
}
|
||||
usedEntries = 0;
|
||||
}
|
||||
|
@ -385,6 +415,9 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
|
|||
void
|
||||
TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context)
|
||||
{
|
||||
DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n",
|
||||
va, context, mbits(va, 63,13) | mbits(context,12,0));
|
||||
|
||||
tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0));
|
||||
}
|
||||
|
||||
|
@ -507,8 +540,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
|
|||
}
|
||||
|
||||
if (e == NULL || !e->valid) {
|
||||
tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
|
||||
vaddr & ~BytesInPageMask | context);
|
||||
writeTagAccess(tc, vaddr, context);
|
||||
if (real)
|
||||
return new InstructionRealTranslationMiss;
|
||||
else
|
||||
|
@ -581,7 +613,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
|||
int part_id = bits(tlbdata,15,8);
|
||||
int tl = bits(tlbdata,18,16);
|
||||
int pri_context = bits(tlbdata,47,32);
|
||||
int sec_context = bits(tlbdata,47,32);
|
||||
int sec_context = bits(tlbdata,63,48);
|
||||
|
||||
bool real = false;
|
||||
ContextType ct = Primary;
|
||||
|
@ -602,52 +634,42 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
|||
ct = Primary;
|
||||
context = pri_context;
|
||||
}
|
||||
} else if (!hpriv && !red) {
|
||||
if (tl > 0 || AsiIsNucleus(asi)) {
|
||||
ct = Nucleus;
|
||||
context = 0;
|
||||
} else if (AsiIsSecondary(asi)) {
|
||||
ct = Secondary;
|
||||
context = sec_context;
|
||||
} else {
|
||||
context = pri_context;
|
||||
ct = Primary; //???
|
||||
}
|
||||
|
||||
} else {
|
||||
// We need to check for priv level/asi priv
|
||||
if (!priv && !AsiIsUnPriv(asi)) {
|
||||
if (!priv && !hpriv && !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)) {
|
||||
|
||||
if (!hpriv && AsiIsHPriv(asi)) {
|
||||
writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
|
||||
return new DataAccessException;
|
||||
}
|
||||
|
||||
} else if (hpriv) {
|
||||
if (asi == ASI_P) {
|
||||
if (AsiIsPrimary(asi)) {
|
||||
context = pri_context;
|
||||
ct = Primary;
|
||||
} else if (AsiIsSecondary(asi)) {
|
||||
context = sec_context;
|
||||
ct = Secondary;
|
||||
} else if (AsiIsNucleus(asi)) {
|
||||
ct = Nucleus;
|
||||
context = 0;
|
||||
} else { // ????
|
||||
ct = Primary;
|
||||
context = pri_context;
|
||||
goto continueDtbFlow;
|
||||
}
|
||||
}
|
||||
|
||||
if (!implicit) {
|
||||
if (!implicit && asi != ASI_P && asi != ASI_S) {
|
||||
if (AsiIsLittle(asi))
|
||||
panic("Little Endian ASIs not supported\n");
|
||||
if (AsiIsBlock(asi))
|
||||
panic("Block ASIs not supported\n");
|
||||
if (AsiIsNoFault(asi))
|
||||
panic("No Fault ASIs not supported\n");
|
||||
if (write && asi == ASI_LDTX_P)
|
||||
// block init store (like write hint64)
|
||||
goto continueDtbFlow;
|
||||
if (!write && asi == ASI_QUAD_LDD)
|
||||
goto continueDtbFlow;
|
||||
|
||||
if (AsiIsTwin(asi))
|
||||
panic("Twin ASIs not supported\n");
|
||||
if (AsiIsPartialStore(asi))
|
||||
panic("Partial Store ASIs not supported\n");
|
||||
if (AsiIsInterrupt(asi))
|
||||
|
@ -662,11 +684,11 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
|
|||
if (AsiIsSparcError(asi))
|
||||
goto handleSparcErrorRegAccess;
|
||||
|
||||
if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
|
||||
if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) &&
|
||||
!AsiIsTwin(asi))
|
||||
panic("Accessing ASI %#X. Should we?\n", asi);
|
||||
}
|
||||
|
||||
continueDtbFlow:
|
||||
// If the asi is unaligned trap
|
||||
if (vaddr & size-1) {
|
||||
writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
|
||||
|
@ -682,7 +704,7 @@ continueDtbFlow:
|
|||
}
|
||||
|
||||
|
||||
if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) {
|
||||
if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) {
|
||||
real = true;
|
||||
context = 0;
|
||||
};
|
||||
|
@ -695,8 +717,7 @@ continueDtbFlow:
|
|||
e = lookup(vaddr, part_id, real, context);
|
||||
|
||||
if (e == NULL || !e->valid) {
|
||||
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
|
||||
vaddr & ~BytesInPageMask | context);
|
||||
writeTagAccess(tc, vaddr, context);
|
||||
DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
|
||||
if (real)
|
||||
return new DataRealTranslationMiss;
|
||||
|
@ -868,7 +889,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
|||
break;
|
||||
case ASI_SPARC_ERROR_STATUS_REG:
|
||||
warn("returning 0 for SPARC ERROR regsiter read\n");
|
||||
pkt->set(0);
|
||||
pkt->set((uint64_t)0);
|
||||
break;
|
||||
case ASI_HYP_SCRATCHPAD:
|
||||
case ASI_SCRATCHPAD:
|
||||
|
@ -880,6 +901,9 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
|||
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
|
||||
pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
|
||||
break;
|
||||
case 0x18:
|
||||
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR));
|
||||
break;
|
||||
case 0x30:
|
||||
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS));
|
||||
break;
|
||||
|
@ -893,6 +917,12 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
|||
temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
|
||||
pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
|
||||
break;
|
||||
case 0x18:
|
||||
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR));
|
||||
break;
|
||||
case 0x20:
|
||||
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR));
|
||||
break;
|
||||
case 0x30:
|
||||
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS));
|
||||
break;
|
||||
|
@ -929,10 +959,40 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
|
|||
data = mbits(tsbtemp,63,13);
|
||||
if (bits(tsbtemp,12,12))
|
||||
data |= ULL(1) << (13+bits(tsbtemp,3,0));
|
||||
data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
|
||||
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
||||
pkt->set(data);
|
||||
break;
|
||||
case ASI_IMMU_TSB_PS0_PTR_REG:
|
||||
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
|
||||
if (bits(temp,12,0) == 0) {
|
||||
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0);
|
||||
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
|
||||
} else {
|
||||
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0);
|
||||
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
|
||||
}
|
||||
data = mbits(tsbtemp,63,13);
|
||||
data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
|
||||
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
||||
pkt->set(data);
|
||||
break;
|
||||
case ASI_IMMU_TSB_PS1_PTR_REG:
|
||||
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
|
||||
if (bits(temp,12,0) == 0) {
|
||||
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1);
|
||||
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
|
||||
} else {
|
||||
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1);
|
||||
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
|
||||
}
|
||||
data = mbits(tsbtemp,63,13);
|
||||
if (bits(tsbtemp,12,12))
|
||||
data |= ULL(1) << (13+bits(tsbtemp,3,0));
|
||||
data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
|
||||
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
|
||||
pkt->set(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
doMmuReadError:
|
||||
|
@ -1044,7 +1104,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
|
|||
break;
|
||||
case ASI_IMMU:
|
||||
switch (va) {
|
||||
case 0x18:
|
||||
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data);
|
||||
break;
|
||||
case 0x30:
|
||||
sext<59>(bits(data, 59,0));
|
||||
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data);
|
||||
break;
|
||||
default:
|
||||
|
@ -1115,7 +1179,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
|
|||
break;
|
||||
case ASI_DMMU:
|
||||
switch (va) {
|
||||
case 0x18:
|
||||
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data);
|
||||
break;
|
||||
case 0x30:
|
||||
sext<59>(bits(data, 59,0));
|
||||
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data);
|
||||
break;
|
||||
case 0x80:
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* 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/miscregfile.hh"
|
||||
|
@ -38,103 +36,107 @@ using namespace SparcISA;
|
|||
|
||||
void
|
||||
MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
|
||||
ThreadContext *tc)
|
||||
ThreadContext *tc)
|
||||
{
|
||||
int64_t time;
|
||||
switch (miscReg) {
|
||||
/* Full system only ASRs */
|
||||
case MISCREG_SOFTINT:
|
||||
// Check if we are going to interrupt because of something
|
||||
setReg(miscReg, val);
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
warn("Writing to softint not really supported, writing: %#x\n", val);
|
||||
break;
|
||||
case MISCREG_SOFTINT:
|
||||
setReg(miscReg, val);;
|
||||
break;
|
||||
|
||||
case MISCREG_SOFTINT_CLR:
|
||||
return setRegWithEffect(miscReg, ~val & softint, tc);
|
||||
case MISCREG_SOFTINT_SET:
|
||||
return setRegWithEffect(miscReg, val | softint, tc);
|
||||
case MISCREG_SOFTINT_CLR:
|
||||
return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
|
||||
case MISCREG_SOFTINT_SET:
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
tc->getCpuPtr()->post_interrupt(soft_interrupt);
|
||||
return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
|
||||
|
||||
case MISCREG_TICK_CMPR:
|
||||
if (tickCompare == NULL)
|
||||
tickCompare = new TickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
|
||||
tickCompare->deschedule();
|
||||
time = (tick_cmpr & mask(63)) - (tick & mask(63));
|
||||
if (!(tick_cmpr & ~mask(63)) && time > 0)
|
||||
tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
|
||||
warn ("writing to TICK compare register %#X\n", val);
|
||||
break;
|
||||
case MISCREG_TICK_CMPR:
|
||||
if (tickCompare == NULL)
|
||||
tickCompare = new TickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
|
||||
tickCompare->deschedule();
|
||||
time = (tick_cmpr & mask(63)) - (tick & mask(63));
|
||||
if (!(tick_cmpr & ~mask(63)) && time > 0)
|
||||
tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
|
||||
panic("writing to TICK compare register %#X\n", val);
|
||||
break;
|
||||
|
||||
case MISCREG_STICK_CMPR:
|
||||
if (sTickCompare == NULL)
|
||||
sTickCompare = new STickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((stick_cmpr & mask(63)) && sTickCompare->scheduled())
|
||||
sTickCompare->deschedule();
|
||||
time = (stick_cmpr & mask(63)) - (stick & mask(63));
|
||||
if (!(stick_cmpr & ~mask(63)) && time > 0)
|
||||
sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
|
||||
warn ("writing to sTICK compare register value %#X\n", val);
|
||||
break;
|
||||
case MISCREG_STICK_CMPR:
|
||||
if (sTickCompare == NULL)
|
||||
sTickCompare = new STickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
|
||||
sTickCompare->deschedule();
|
||||
time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
tc->getCpuPtr()->instCount();
|
||||
if (!(stick_cmpr & ~mask(63)) && time > 0)
|
||||
sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
|
||||
DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
|
||||
break;
|
||||
|
||||
case MISCREG_PSTATE:
|
||||
if (val & ie && !(pstate & ie)) {
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
case MISCREG_PSTATE:
|
||||
if (val & PSTATE::ie && !(pstate & PSTATE::ie)) {
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
|
||||
case MISCREG_PIL:
|
||||
if (val < pil) {
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
break;
|
||||
case MISCREG_PIL:
|
||||
if (val < pil) {
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
}
|
||||
setReg(miscReg, val);
|
||||
break;
|
||||
|
||||
case MISCREG_HVER:
|
||||
panic("Shouldn't be writing HVER\n");
|
||||
case MISCREG_HVER:
|
||||
panic("Shouldn't be writing HVER\n");
|
||||
|
||||
case MISCREG_HTBA:
|
||||
// clear lower 7 bits on writes.
|
||||
setReg(miscReg, val & ULL(~0x7FFF));
|
||||
break;
|
||||
case MISCREG_HINTP:
|
||||
setReg(miscReg, val);
|
||||
|
||||
case MISCREG_QUEUE_CPU_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
||||
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_DEV_MONDO_TAIL:
|
||||
case MISCREG_QUEUE_RES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_RES_ERROR_TAIL:
|
||||
case MISCREG_QUEUE_NRES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_NRES_ERROR_TAIL:
|
||||
setReg(miscReg, val);
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
break;
|
||||
case MISCREG_HTBA:
|
||||
// clear lower 7 bits on writes.
|
||||
setReg(miscReg, val & ULL(~0x7FFF));
|
||||
break;
|
||||
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
if (hSTickCompare == NULL)
|
||||
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((hstick_cmpr & mask(63)) && hSTickCompare->scheduled())
|
||||
hSTickCompare->deschedule();
|
||||
time = (hstick_cmpr & mask(63)) - (stick & mask(63));
|
||||
if (!(hstick_cmpr & ~mask(63)) && time > 0)
|
||||
hSTickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
|
||||
warn ("writing to hsTICK compare register value %#X\n", val);
|
||||
break;
|
||||
case MISCREG_QUEUE_CPU_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
||||
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_DEV_MONDO_TAIL:
|
||||
case MISCREG_QUEUE_RES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_RES_ERROR_TAIL:
|
||||
case MISCREG_QUEUE_NRES_ERROR_HEAD:
|
||||
case MISCREG_QUEUE_NRES_ERROR_TAIL:
|
||||
setReg(miscReg, val);
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
break;
|
||||
|
||||
case MISCREG_HPSTATE:
|
||||
// T1000 spec says impl. dependent val must always be 1
|
||||
setReg(miscReg, val | id);
|
||||
break;
|
||||
case MISCREG_HTSTATE:
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
setReg(miscReg, val);
|
||||
break;
|
||||
case MISCREG_HSTICK_CMPR:
|
||||
if (hSTickCompare == NULL)
|
||||
hSTickCompare = new HSTickCompareEvent(this, tc);
|
||||
setReg(miscReg, val);
|
||||
if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
|
||||
hSTickCompare->deschedule();
|
||||
time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
tc->getCpuPtr()->instCount();
|
||||
if (!(hstick_cmpr & ~mask(63)) && time > 0)
|
||||
hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
|
||||
DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
|
||||
case MISCREG_HPSTATE:
|
||||
// T1000 spec says impl. dependent val must always be 1
|
||||
setReg(miscReg, val | HPSTATE::id);
|
||||
break;
|
||||
case MISCREG_HTSTATE:
|
||||
case MISCREG_STRAND_STS_REG:
|
||||
setReg(miscReg, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +144,7 @@ MiscReg
|
|||
MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
|
||||
{
|
||||
switch (miscReg) {
|
||||
/* Privileged registers. */
|
||||
/* Privileged registers. */
|
||||
case MISCREG_QUEUE_CPU_MONDO_HEAD:
|
||||
case MISCREG_QUEUE_CPU_MONDO_TAIL:
|
||||
case MISCREG_QUEUE_DEV_MONDO_HEAD:
|
||||
|
@ -172,12 +174,12 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
|
|||
}
|
||||
}
|
||||
/*
|
||||
In Niagra STICK==TICK so this isn't needed
|
||||
case MISCREG_STICK:
|
||||
SparcSystem *sys;
|
||||
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||
assert(sys != NULL);
|
||||
return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
|
||||
In Niagra STICK==TICK so this isn't needed
|
||||
case MISCREG_STICK:
|
||||
SparcSystem *sys;
|
||||
sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
|
||||
assert(sys != NULL);
|
||||
return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
|
||||
*/
|
||||
|
||||
|
||||
|
@ -191,12 +193,47 @@ MiscRegFile::processTickCompare(ThreadContext *tc)
|
|||
void
|
||||
MiscRegFile::processSTickCompare(ThreadContext *tc)
|
||||
{
|
||||
panic("tick compare not implemented\n");
|
||||
// since our microcode instructions take two cycles we need to check if
|
||||
// we're actually at the correct cycle or we need to wait a little while
|
||||
// more
|
||||
int ticks;
|
||||
ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
tc->getCpuPtr()->instCount();
|
||||
assert(ticks >= 0 && "stick compare missed interrupt cycle");
|
||||
|
||||
if (ticks == 0) {
|
||||
DPRINTF(Timer, "STick compare cycle reached at %#x\n",
|
||||
(stick_cmpr & mask(63)));
|
||||
if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
|
||||
tc->getCpuPtr()->post_interrupt(soft_interrupt);
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
|
||||
}
|
||||
} else
|
||||
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
|
||||
}
|
||||
|
||||
void
|
||||
MiscRegFile::processHSTickCompare(ThreadContext *tc)
|
||||
{
|
||||
panic("tick compare not implemented\n");
|
||||
// since our microcode instructions take two cycles we need to check if
|
||||
// we're actually at the correct cycle or we need to wait a little while
|
||||
// more
|
||||
int ticks;
|
||||
ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
|
||||
tc->getCpuPtr()->instCount();
|
||||
assert(ticks >= 0 && "hstick compare missed interrupt cycle");
|
||||
|
||||
if (ticks == 0) {
|
||||
DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
|
||||
(stick_cmpr & mask(63)));
|
||||
if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
|
||||
setRegWithEffect(MISCREG_HINTP, 1, tc);
|
||||
tc->getCpuPtr()->post_interrupt(hstick_match);
|
||||
tc->getCpuPtr()->checkInterrupts = true;
|
||||
}
|
||||
// Need to do something to cause interrupt to happen here !!! @todo
|
||||
} else
|
||||
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
|
||||
}
|
||||
|
||||
|
|
|
@ -340,3 +340,41 @@ ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
|
|||
{
|
||||
return loadSomeSymbols(symtab, STB_LOCAL);
|
||||
}
|
||||
|
||||
bool
|
||||
ElfObject::isDynamic()
|
||||
{
|
||||
Elf *elf;
|
||||
int sec_idx = 1; // there is a 0 but it is nothing, go figure
|
||||
Elf_Scn *section;
|
||||
GElf_Shdr shdr;
|
||||
|
||||
GElf_Ehdr ehdr;
|
||||
|
||||
// check that header matches library version
|
||||
if (elf_version(EV_CURRENT) == EV_NONE)
|
||||
panic("wrong elf version number!");
|
||||
|
||||
// get a pointer to elf structure
|
||||
elf = elf_memory((char*)fileData,len);
|
||||
assert(elf != NULL);
|
||||
|
||||
// Check that we actually have a elf file
|
||||
if (gelf_getehdr(elf, &ehdr) ==0) {
|
||||
panic("Not ELF, shouldn't be here");
|
||||
}
|
||||
|
||||
// Get the first section
|
||||
section = elf_getscn(elf, sec_idx);
|
||||
|
||||
// While there are no more sections
|
||||
while (section != NULL) {
|
||||
gelf_getshdr(section, &shdr);
|
||||
if (!strcmp(".interp", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
|
||||
return true;
|
||||
section = elf_getscn(elf, ++sec_idx);
|
||||
} // while sections
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ class ElfObject : public ObjectFile
|
|||
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
|
||||
std::numeric_limits<Addr>::max());
|
||||
|
||||
virtual bool isDynamic();
|
||||
|
||||
static ObjectFile *tryFile(const std::string &fname, int fd,
|
||||
size_t len, uint8_t *data);
|
||||
Addr programHeaderTable() {return _programHeaderTable;}
|
||||
|
|
|
@ -150,3 +150,9 @@ createObjectFile(const string &fname, bool raw)
|
|||
munmap(fileData, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectFile::isDynamic()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,8 @@ class ObjectFile
|
|||
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
|
||||
std::numeric_limits<Addr>::max()) = 0;
|
||||
|
||||
virtual bool isDynamic();
|
||||
|
||||
Arch getArch() const { return arch; }
|
||||
OpSys getOpSys() const { return opSys; }
|
||||
|
||||
|
|
|
@ -63,19 +63,19 @@ RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
|
|||
bool
|
||||
RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
|
||||
{
|
||||
int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||
/* int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||
int extStart = filename.rfind('.',filename.size());
|
||||
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
|
||||
extStart-fnameStart) + "_start");
|
||||
extStart-fnameStart) + "_start");*/
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RawObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
|
||||
{
|
||||
int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||
/* int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||
int extStart = filename.rfind('.',filename.size());
|
||||
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
|
||||
extStart-fnameStart) + "_start");
|
||||
extStart-fnameStart) + "_start");*/
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -362,6 +362,12 @@ BaseCPU::ProfileEvent::process()
|
|||
schedule(curTick + interval);
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::post_interrupt(int int_type)
|
||||
{
|
||||
interrupts.post(int_type);
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::post_interrupt(int int_num, int index)
|
||||
{
|
||||
|
|
|
@ -102,6 +102,7 @@ class BaseCPU : public MemObject
|
|||
TheISA::Interrupts interrupts;
|
||||
|
||||
public:
|
||||
virtual void post_interrupt(int int_type);
|
||||
virtual void post_interrupt(int int_num, int index);
|
||||
virtual void clear_interrupt(int int_num, int index);
|
||||
virtual void clear_interrupts();
|
||||
|
|
|
@ -36,12 +36,14 @@
|
|||
|
||||
class ThreadContext;
|
||||
|
||||
/** This class creates a global list of events that need a pointer to a
|
||||
* thread context. When a switchover takes place the events can be migrated
|
||||
* to the new thread context, otherwise you could have a wake timer interrupt
|
||||
* go off on a switched out cpu or other unfortunate events. This object MUST be
|
||||
* dynamically allocated to avoid it being deleted after a cpu switch happens.
|
||||
* */
|
||||
/**
|
||||
* This class creates a global list of events that need a pointer to a
|
||||
* thread context. When a switchover takes place the events can be
|
||||
* migrated to the new thread context, otherwise you could have a wake
|
||||
* timer interrupt go off on a switched out cpu or other unfortunate
|
||||
* events. This object MUST be dynamically allocated to avoid it being
|
||||
* deleted after a cpu switch happens.
|
||||
*/
|
||||
class CpuEvent : public Event
|
||||
{
|
||||
protected:
|
||||
|
@ -78,8 +80,8 @@ class CpuEventWrapper : public CpuEvent
|
|||
T *object;
|
||||
|
||||
public:
|
||||
CpuEventWrapper(T *obj, ThreadContext *_tc, EventQueue *q = &mainEventQueue,
|
||||
Priority p = Default_Pri)
|
||||
CpuEventWrapper(T *obj, ThreadContext *_tc,
|
||||
EventQueue *q = &mainEventQueue, Priority p = Default_Pri)
|
||||
: CpuEvent(q, _tc, p), object(obj)
|
||||
{ }
|
||||
void process() { (object->*F)(tc); }
|
||||
|
|
|
@ -59,6 +59,7 @@ using namespace TheISA;
|
|||
|
||||
#if THE_ISA == SPARC_ISA && FULL_SYSTEM
|
||||
static int diffcount = 0;
|
||||
static bool wasMicro = false;
|
||||
#endif
|
||||
|
||||
namespace Trace {
|
||||
|
@ -124,6 +125,7 @@ inline void printLevelHeader(ostream & os, int level)
|
|||
void
|
||||
Trace::InstRecord::dump(ostream &outs)
|
||||
{
|
||||
DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
|
||||
if (flags[PRINT_REG_DELTA])
|
||||
{
|
||||
#if THE_ISA == SPARC_ISA
|
||||
|
@ -317,6 +319,24 @@ Trace::InstRecord::dump(ostream &outs)
|
|||
bool diffTlb = false;
|
||||
Addr m5Pc, lgnPc;
|
||||
|
||||
// We took a trap on a micro-op...
|
||||
if (wasMicro && !staticInst->isMicroOp())
|
||||
{
|
||||
// let's skip comparing this cycle
|
||||
while (!compared)
|
||||
if (shared_data->flags == OWN_M5) {
|
||||
shared_data->flags = OWN_LEGION;
|
||||
compared = true;
|
||||
}
|
||||
compared = false;
|
||||
wasMicro = false;
|
||||
}
|
||||
|
||||
if (staticInst->isLastMicroOp())
|
||||
wasMicro = false;
|
||||
else if (staticInst->isMicroOp())
|
||||
wasMicro = true;
|
||||
|
||||
|
||||
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
|
||||
while (!compared) {
|
||||
|
@ -607,29 +627,34 @@ Trace::InstRecord::dump(ostream &outs)
|
|||
<< endl;*/
|
||||
}
|
||||
}
|
||||
printColumnLabels(outs);
|
||||
char label[8];
|
||||
for (int x = 0; x < 64; x++) {
|
||||
if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
|
||||
thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
|
||||
sprintf(label, "I-TLB:%02d", x);
|
||||
printRegPair(outs, label, thread->getITBPtr()->TteRead(x), shared_data->itb[x]);
|
||||
if (diffTlb) {
|
||||
printColumnLabels(outs);
|
||||
char label[8];
|
||||
for (int x = 0; x < 64; x++) {
|
||||
if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
|
||||
thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
|
||||
sprintf(label, "I-TLB:%02d", x);
|
||||
printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
|
||||
shared_data->itb[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 64; x++) {
|
||||
if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
|
||||
thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
|
||||
sprintf(label, "D-TLB:%02d", x);
|
||||
printRegPair(outs, label, thread->getDTBPtr()->TteRead(x), shared_data->dtb[x]);
|
||||
for (int x = 0; x < 64; x++) {
|
||||
if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
|
||||
thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
|
||||
sprintf(label, "D-TLB:%02d", x);
|
||||
printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
|
||||
shared_data->dtb[x]);
|
||||
}
|
||||
}
|
||||
thread->getITBPtr()->dumpAll();
|
||||
thread->getDTBPtr()->dumpAll();
|
||||
}
|
||||
thread->getITBPtr()->dumpAll();
|
||||
thread->getDTBPtr()->dumpAll();
|
||||
|
||||
diffcount++;
|
||||
if (diffcount > 2)
|
||||
fatal("Differences found between Legion and M5\n");
|
||||
}
|
||||
} else
|
||||
diffcount = 0;
|
||||
|
||||
compared = true;
|
||||
shared_data->flags = OWN_LEGION;
|
||||
|
|
|
@ -497,7 +497,7 @@ AtomicSimpleCPU::tick()
|
|||
|
||||
// @todo remove me after debugging with legion done
|
||||
if (curStaticInst && (!curStaticInst->isMicroOp() ||
|
||||
curStaticInst->isLastMicroOp()))
|
||||
curStaticInst->isFirstMicroOp()))
|
||||
instCnt++;
|
||||
|
||||
if (simulate_stalls) {
|
||||
|
|
|
@ -437,6 +437,7 @@ void
|
|||
BaseSimpleCPU::advancePC(Fault fault)
|
||||
{
|
||||
if (fault != NoFault) {
|
||||
curMacroStaticInst = StaticInst::nullStaticInstPtr;
|
||||
fault->invoke(tc);
|
||||
} else {
|
||||
//If we're at the last micro op for this instruction
|
||||
|
|
|
@ -146,6 +146,7 @@ class StaticInstBase : public RefCounted
|
|||
IsMicroOp, ///< Is a microop
|
||||
IsDelayedCommit, ///< This microop doesn't commit right away
|
||||
IsLastMicroOp, ///< This microop ends a microop sequence
|
||||
IsFirstMicroOp, ///< This microop begins a microop sequence
|
||||
//This flag doesn't do anything yet
|
||||
IsMicroBranch, ///< This microop branches within the microcode for a macroop
|
||||
|
||||
|
@ -244,6 +245,7 @@ class StaticInstBase : public RefCounted
|
|||
bool isMicroOp() const { return flags[IsMicroOp]; }
|
||||
bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
|
||||
bool isLastMicroOp() const { return flags[IsLastMicroOp]; }
|
||||
bool isFirstMicroOp() const { return flags[IsFirstMicroOp]; }
|
||||
//This flag doesn't do anything yet
|
||||
bool isMicroBranch() const { return flags[IsMicroBranch]; }
|
||||
//@}
|
||||
|
|
|
@ -57,17 +57,13 @@ using namespace std;
|
|||
//Should this be AlphaISA?
|
||||
using namespace TheISA;
|
||||
|
||||
TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i)
|
||||
: _name(name), event(t, i), addr(0)
|
||||
TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, time_t t, Tick i)
|
||||
: _name(n), event(tsunami, i), addr(0)
|
||||
{
|
||||
memset(clock_data, 0, sizeof(clock_data));
|
||||
stat_regA = RTCA_32768HZ | RTCA_1024HZ;
|
||||
stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
|
||||
}
|
||||
|
||||
void
|
||||
TsunamiIO::RTC::set_time(time_t t)
|
||||
{
|
||||
struct tm tm;
|
||||
gmtime_r(&t, &tm);
|
||||
|
||||
|
@ -428,7 +424,7 @@ TsunamiIO::PITimer::Counter::CounterEvent::description()
|
|||
|
||||
TsunamiIO::TsunamiIO(Params *p)
|
||||
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
|
||||
rtc(p->name + ".rtc", p->tsunami, p->frequency)
|
||||
rtc(p->name + ".rtc", p->tsunami, p->init_time, p->frequency)
|
||||
{
|
||||
pioSize = 0x100;
|
||||
|
||||
|
@ -436,7 +432,6 @@ TsunamiIO::TsunamiIO(Params *p)
|
|||
tsunami->io = this;
|
||||
|
||||
timerData = 0;
|
||||
rtc.set_time(p->init_time == 0 ? time(NULL) : p->init_time);
|
||||
picr = 0;
|
||||
picInterrupting = false;
|
||||
}
|
||||
|
|
|
@ -110,10 +110,7 @@ class TsunamiIO : public BasicPioDevice
|
|||
uint8_t stat_regB;
|
||||
|
||||
public:
|
||||
RTC(const std::string &name, Tsunami* t, Tick i);
|
||||
|
||||
/** Set the initial RTC time/date */
|
||||
void set_time(time_t t);
|
||||
RTC(const std::string &name, Tsunami* tsunami, time_t t, Tick i);
|
||||
|
||||
/** RTC address port: write address of RTC RAM data to access */
|
||||
void writeAddr(const uint8_t data);
|
||||
|
|
|
@ -37,7 +37,9 @@ Import('env')
|
|||
sources = []
|
||||
|
||||
sources += Split('''
|
||||
dtod.cc
|
||||
t1000.cc
|
||||
mm_disk.cc
|
||||
''')
|
||||
|
||||
# Convert file names to SCons File objects. This takes care of the
|
||||
|
|
115
src/dev/sparc/dtod.cc
Normal file
115
src/dev/sparc/dtod.cc
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Time of date device implementation
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/sparc/dtod.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace TheISA;
|
||||
|
||||
DumbTOD::DumbTOD(Params *p)
|
||||
: BasicPioDevice(p), todTime(p->init_time)
|
||||
{
|
||||
pioSize = 0x08;
|
||||
|
||||
struct tm tm;
|
||||
gmtime_r((time_t*)&todTime, &tm);
|
||||
DPRINTFN("Real-time clock set to %s\n", asctime(&tm));
|
||||
DPRINTFN("Real-time clock set to %d\n", todTime);
|
||||
}
|
||||
|
||||
Tick
|
||||
DumbTOD::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 8);
|
||||
|
||||
pkt->allocate();
|
||||
pkt->set(todTime);
|
||||
todTime += 1000;
|
||||
|
||||
pkt->result = Packet::Success;
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
DumbTOD::write(PacketPtr pkt)
|
||||
{
|
||||
panic("Dumb tod device doesn't support writes\n");
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DumbTOD)
|
||||
|
||||
Param<Addr> pio_addr;
|
||||
Param<Tick> pio_latency;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<System *> system;
|
||||
Param<time_t> time;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(DumbTOD)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(DumbTOD)
|
||||
|
||||
INIT_PARAM(pio_addr, "Device Address"),
|
||||
INIT_PARAM(pio_latency, "Programmed IO latency"),
|
||||
INIT_PARAM(platform, "platform"),
|
||||
INIT_PARAM(system, "system object"),
|
||||
INIT_PARAM(time, "System time to use (0 for actual time")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(DumbTOD)
|
||||
|
||||
CREATE_SIM_OBJECT(DumbTOD)
|
||||
{
|
||||
DumbTOD::Params *p = new DumbTOD::Params;
|
||||
p->name =getInstanceName();
|
||||
p->pio_addr = pio_addr;
|
||||
p->pio_delay = pio_latency;
|
||||
p->platform = platform;
|
||||
p->system = system;
|
||||
p->init_time = time;
|
||||
return new DumbTOD(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("DumbTOD", DumbTOD)
|
67
src/dev/sparc/dtod.hh
Normal file
67
src/dev/sparc/dtod.hh
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 206, 2004-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Ali Saidi
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This device acts as a simple time of date device. It's implemented as a
|
||||
* simple device register read.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_SPARC_DTOD_HH__
|
||||
#define __DEV_SPARC_DTOD_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
|
||||
|
||||
/**
|
||||
* DumbTOD simply returns some idea of time when read. Until we finish with
|
||||
* legion it starts with the start time and increments itself by 1000 each time.
|
||||
*/
|
||||
class DumbTOD : public BasicPioDevice
|
||||
{
|
||||
private:
|
||||
uint64_t todTime;
|
||||
|
||||
public:
|
||||
struct Params : public BasicPioDevice::Params
|
||||
{
|
||||
time_t init_time;
|
||||
};
|
||||
protected:
|
||||
const Params *params() const { return (const Params *)_params; }
|
||||
|
||||
public:
|
||||
DumbTOD(Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
};
|
||||
|
||||
#endif // __DEV_BADDEV_HH__
|
137
src/dev/sparc/mm_disk.cc
Normal file
137
src/dev/sparc/mm_disk.cc
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This device acts as a disk similar to the memory mapped disk device
|
||||
* in legion. Any access is translated to an offset in the disk image.
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/sparc/mm_disk.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
MmDisk::MmDisk(Params *p)
|
||||
: BasicPioDevice(p), image(p->image), curSector((uint64_t)-1), dirty(false)
|
||||
{
|
||||
memset(&bytes, 0, SectorSize);
|
||||
pioSize = image->size() * SectorSize;
|
||||
}
|
||||
|
||||
Tick
|
||||
MmDisk::read(PacketPtr pkt)
|
||||
{
|
||||
Addr accessAddr;
|
||||
off_t sector;
|
||||
off_t bytes_read;
|
||||
uint16_t *d16;
|
||||
uint32_t *d32;
|
||||
uint64_t *d64;
|
||||
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
accessAddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
sector = accessAddr / SectorSize;
|
||||
|
||||
if (sector != curSector) {
|
||||
if (dirty)
|
||||
bytes_read = image->write(bytes, curSector);
|
||||
bytes_read = image->read(bytes, sector);
|
||||
curSector = sector;
|
||||
}
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint8_t):
|
||||
pkt->set(bytes[accessAddr % SectorSize]);
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
d16 = (uint16_t*)bytes + (accessAddr % SectorSize)/2;
|
||||
pkt->set(htobe(*d16));
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
d32 = (uint32_t*)bytes + (accessAddr % SectorSize)/4;
|
||||
pkt->set(htobe(*d32));
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
d64 = (uint64_t*)bytes + (accessAddr % SectorSize)/8;
|
||||
pkt->set(htobe(*d64));
|
||||
break;
|
||||
default:
|
||||
panic("Invalid access size\n");
|
||||
}
|
||||
|
||||
pkt->result = Packet::Success;
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
Tick
|
||||
MmDisk::write(PacketPtr pkt)
|
||||
{
|
||||
panic("need to implement\n");
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MmDisk)
|
||||
Param<Addr> pio_addr;
|
||||
Param<Tick> pio_latency;
|
||||
Param<Addr> pio_size;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<DiskImage *> image;
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(MmDisk)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(MmDisk)
|
||||
|
||||
INIT_PARAM(pio_addr, "Device Address"),
|
||||
INIT_PARAM(pio_latency, "Programmed IO latency"),
|
||||
INIT_PARAM(pio_size, "Size of address range"),
|
||||
INIT_PARAM(platform, "platform"),
|
||||
INIT_PARAM(system, "system object"),
|
||||
INIT_PARAM(image, "disk image")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(MmDisk)
|
||||
|
||||
CREATE_SIM_OBJECT(MmDisk)
|
||||
{
|
||||
MmDisk::Params *p = new MmDisk::Params;
|
||||
p->name = getInstanceName();
|
||||
p->pio_addr = pio_addr;
|
||||
p->pio_delay = pio_latency;
|
||||
p->platform = platform;
|
||||
p->system = system;
|
||||
p->image = image;
|
||||
return new MmDisk(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("MmDisk", MmDisk)
|
70
src/dev/sparc/mm_disk.hh
Normal file
70
src/dev/sparc/mm_disk.hh
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This device acts as a disk similar to the memory mapped disk device
|
||||
* in legion. Any access is translated to an offset in the disk image.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_SPARC_MM_DISK_HH__
|
||||
#define __DEV_SPARC_MM_DISK_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/disk_image.hh"
|
||||
|
||||
class MmDisk : public BasicPioDevice
|
||||
{
|
||||
private:
|
||||
DiskImage *image;
|
||||
off_t curSector;
|
||||
bool dirty;
|
||||
union {
|
||||
uint8_t bytes[SectorSize];
|
||||
uint32_t words[SectorSize/4];
|
||||
};
|
||||
|
||||
public:
|
||||
struct Params : public BasicPioDevice::Params
|
||||
{
|
||||
DiskImage *image;
|
||||
};
|
||||
protected:
|
||||
const Params *params() const { return (const Params*)_params; }
|
||||
|
||||
public:
|
||||
MmDisk(Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
};
|
||||
|
||||
#endif //__DEV_SPARC_MM_DISK_HH__
|
||||
|
|
@ -304,7 +304,8 @@ def main():
|
|||
sys.argv = arguments
|
||||
sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
|
||||
|
||||
scope = { '__file__' : sys.argv[0] }
|
||||
scope = { '__file__' : sys.argv[0],
|
||||
'__name__' : '__m5_main__' }
|
||||
|
||||
# we want readline if we're doing anything interactive
|
||||
if options.interactive or options.pdb:
|
||||
|
|
|
@ -5,6 +5,18 @@ from Uart import Uart8250
|
|||
from Platform import Platform
|
||||
from SimConsole import SimConsole, ConsoleListener
|
||||
|
||||
|
||||
class MmDisk(BasicPioDevice):
|
||||
type = 'MmDisk'
|
||||
image = Param.DiskImage("Disk Image")
|
||||
pio_addr = 0x1F40000000
|
||||
|
||||
class DumbTOD(BasicPioDevice):
|
||||
type = 'DumbTOD'
|
||||
time = Param.Time('01/01/2009', "System time to use ('Now' for real time)")
|
||||
pio_addr = 0xfff0c1fff8
|
||||
|
||||
|
||||
class T1000(Platform):
|
||||
type = 'T1000'
|
||||
system = Param.System(Parent.any, "system")
|
||||
|
@ -58,6 +70,8 @@ class T1000(Platform):
|
|||
warn_access="Accessing SSI -- Unimplemented!")
|
||||
|
||||
hvuart = Uart8250(pio_addr=0xfff0c2c000)
|
||||
htod = DumbTOD()
|
||||
|
||||
puart0 = Uart8250(pio_addr=0x1f10000000)
|
||||
console = SimConsole(listener = ConsoleListener())
|
||||
|
||||
|
@ -80,3 +94,4 @@ class T1000(Platform):
|
|||
self.fake_ssi.pio = bus.port
|
||||
self.puart0.pio = bus.port
|
||||
self.hvuart.pio = bus.port
|
||||
self.htod.pio = bus.port
|
||||
|
|
|
@ -13,8 +13,8 @@ class TsunamiCChip(BasicPioDevice):
|
|||
|
||||
class TsunamiIO(BasicPioDevice):
|
||||
type = 'TsunamiIO'
|
||||
time = Param.UInt64(1136073600,
|
||||
"System time to use (0 for actual time, default is 1/1/06)")
|
||||
time = Param.Time('01/01/2009',
|
||||
"System time to use ('Now' for actual time)")
|
||||
tsunami = Param.Tsunami(Parent.any, "Tsunami")
|
||||
frequency = Param.Frequency('1024Hz', "frequency of interrupts")
|
||||
|
||||
|
|
|
@ -44,7 +44,12 @@
|
|||
#
|
||||
#####################################################################
|
||||
|
||||
import sys, inspect, copy
|
||||
import copy
|
||||
import datetime
|
||||
import inspect
|
||||
import sys
|
||||
import time
|
||||
|
||||
import convert
|
||||
from util import *
|
||||
|
||||
|
@ -513,6 +518,50 @@ class EthernetAddr(ParamValue):
|
|||
else:
|
||||
return self.value
|
||||
|
||||
def parse_time(value):
|
||||
strings = [ "%a %b %d %H:%M:%S %Z %Y",
|
||||
"%a %b %d %H:%M:%S %Z %Y",
|
||||
"%Y/%m/%d %H:%M:%S",
|
||||
"%Y/%m/%d %H:%M",
|
||||
"%Y/%m/%d",
|
||||
"%m/%d/%Y %H:%M:%S",
|
||||
"%m/%d/%Y %H:%M",
|
||||
"%m/%d/%Y",
|
||||
"%m/%d/%y %H:%M:%S",
|
||||
"%m/%d/%y %H:%M",
|
||||
"%m/%d/%y"]
|
||||
|
||||
for string in strings:
|
||||
try:
|
||||
return time.strptime(value, string)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
raise ValueError, "Could not parse '%s' as a time" % value
|
||||
|
||||
class Time(ParamValue):
|
||||
cxx_type = 'time_t'
|
||||
def __init__(self, value):
|
||||
if isinstance(value, time.struct_time):
|
||||
self.value = time.mktime(value)
|
||||
elif isinstance(value, int):
|
||||
self.value = value
|
||||
elif isinstance(value, str):
|
||||
if value in ('Now', 'Today'):
|
||||
self.value = time.time()
|
||||
else:
|
||||
self.value = time.mktime(parse_time(value))
|
||||
elif isinstance(value, (datetime.datetime, datetime.date)):
|
||||
self.value = time.mktime(value.timetuple())
|
||||
else:
|
||||
raise ValueError, "Could not parse '%s' as a time" % value
|
||||
|
||||
def __str__(self):
|
||||
return str(int(self.value))
|
||||
|
||||
def ini_str(self):
|
||||
return str(int(self.value))
|
||||
|
||||
# Enumerated types are a little more complex. The user specifies the
|
||||
# type as Enum(foo) where foo is either a list or dictionary of
|
||||
# alternatives (typically strings, but not necessarily so). (In the
|
||||
|
@ -973,6 +1022,7 @@ __all__ = ['Param', 'VectorParam',
|
|||
'NetworkBandwidth', 'MemoryBandwidth',
|
||||
'Range', 'AddrRange', 'TickRange',
|
||||
'MaxAddr', 'MaxTick', 'AllMemory',
|
||||
'Time',
|
||||
'NextEthernetAddr', 'NULL',
|
||||
'Port', 'VectorPort']
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ template <typename T> static inline T letobe(T value) {return swap_byte(value);}
|
|||
|
||||
//For conversions not involving the guest system, we can define the functions
|
||||
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
|
||||
#if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN
|
||||
#if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
|
||||
const ByteOrder HostByteOrder = BigEndianByteOrder;
|
||||
template <typename T> static inline T htole(T value) {return swap_byte(value);}
|
||||
template <typename T> static inline T letoh(T value) {return swap_byte(value);}
|
||||
|
|
|
@ -448,6 +448,11 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd,
|
|||
fatal("Can't load object file %s", executable);
|
||||
}
|
||||
|
||||
if (objFile->isDynamic())
|
||||
fatal("Object file is a dynamic executable however only static "
|
||||
"executables are supported!\n Please recompile your "
|
||||
"executable as a static binary and try again.\n");
|
||||
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
if (objFile->getArch() != ObjectFile::Alpha)
|
||||
fatal("Object file architecture does not match compiled ISA (Alpha).");
|
||||
|
|
Loading…
Reference in a new issue