summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SConscript2
-rwxr-xr-xsrc/arch/isa_parser.py2
-rw-r--r--src/arch/sparc/faults.cc163
-rw-r--r--src/arch/sparc/faults.hh6
-rw-r--r--src/arch/sparc/intregfile.cc19
-rw-r--r--src/arch/sparc/intregfile.hh1
-rw-r--r--src/arch/sparc/isa/bitfields.isa2
-rw-r--r--src/arch/sparc/isa/decoder.isa112
-rw-r--r--src/arch/sparc/isa/formats/formats.isa3
-rw-r--r--src/arch/sparc/isa/formats/mem/basicmem.isa96
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa8
-rw-r--r--src/arch/sparc/isa/formats/mem/mem.isa2
-rw-r--r--src/arch/sparc/isa/formats/mem/util.isa134
-rw-r--r--src/arch/sparc/isa/formats/priv.isa5
-rw-r--r--src/arch/sparc/isa/operands.isa22
-rw-r--r--src/arch/sparc/isa_traits.hh15
-rw-r--r--src/arch/sparc/miscregfile.cc224
-rw-r--r--src/arch/sparc/miscregfile.hh29
-rw-r--r--src/arch/sparc/process.cc106
-rw-r--r--src/arch/sparc/process.hh9
-rw-r--r--src/arch/sparc/regfile.cc9
-rw-r--r--src/base/bitfield.hh24
-rw-r--r--src/cpu/ozone/back_end.hh2
-rw-r--r--src/cpu/ozone/dyn_inst_impl.hh2
-rw-r--r--src/cpu/ozone/front_end_impl.hh2
-rw-r--r--src/cpu/ozone/inorder_back_end.hh2
-rw-r--r--src/cpu/ozone/inorder_back_end_impl.hh2
-rw-r--r--src/cpu/ozone/lw_back_end.hh2
-rw-r--r--src/cpu/ozone/thread_state.hh2
-rw-r--r--src/cpu/simple/atomic.cc16
-rw-r--r--src/cpu/simple/base.cc6
-rw-r--r--src/cpu/thread_state.cc4
-rw-r--r--src/dev/i8254xGBe.cc53
-rw-r--r--src/mem/tport.cc83
-rw-r--r--src/mem/tport.hh33
-rw-r--r--src/sim/sim_object.cc20
-rw-r--r--src/sim/sim_object.hh2
37 files changed, 731 insertions, 493 deletions
diff --git a/src/SConscript b/src/SConscript
index 9f88bbeea..28f39bc29 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -220,7 +220,6 @@ full_system_sources = Split('''
dev/etherlink.cc
dev/etherpkt.cc
dev/ethertap.cc
- dev/i8254xGBe.cc
dev/ide_ctrl.cc
dev/ide_disk.cc
dev/io_device.cc
@@ -253,6 +252,7 @@ full_system_sources = Split('''
sim/pseudo_inst.cc
''')
#dev/sinic.cc
+ #dev/i8254xGBe.cc
if env['TARGET_ISA'] == 'alpha':
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py
index b235398f1..6504c7b32 100755
--- a/src/arch/isa_parser.py
+++ b/src/arch/isa_parser.py
@@ -1316,7 +1316,7 @@ class ControlRegOperand(Operand):
def makeWrite(self):
if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write control register as FP')
- wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name)
+ wb = 'xc->setMiscRegWithEffect(%s, %s);\n' % (self.reg_spec, self.base_name)
wb += 'if (traceData) { traceData->setData(%s); }' % \
self.base_name
return wb
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index 7b7765935..2c8da44c5 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -29,15 +29,22 @@
* Kevin Lim
*/
+#include <algorithm>
+
#include "arch/sparc/faults.hh"
-#include "cpu/thread_context.hh"
-#include "cpu/base.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/process.hh"
+#include "base/bitfield.hh"
#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
#if !FULL_SYSTEM
-#include "sim/process.hh"
#include "mem/page_table.hh"
+#include "sim/process.hh"
#endif
+using namespace std;
+
namespace SparcISA
{
@@ -229,6 +236,121 @@ FaultPriority PageTableFault::_priority = 0;
FaultStat PageTableFault::_count;
#endif
+/**
+ * This sets everything up for a normal trap except for actually jumping to
+ * the handler. It will need to be expanded to include the state machine in
+ * the manual. Right now it assumes that traps will always be to the
+ * privileged level.
+ */
+
+void doNormalFault(ThreadContext *tc, TrapType tt)
+{
+ uint64_t TL = tc->readMiscReg(MISCREG_TL);
+ uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE);
+ uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE);
+ uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE);
+ uint64_t CCR = tc->readMiscReg(MISCREG_CCR);
+ uint64_t ASI = tc->readMiscReg(MISCREG_ASI);
+ uint64_t CWP = tc->readMiscReg(MISCREG_CWP);
+ uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE);
+ uint64_t GL = tc->readMiscReg(MISCREG_GL);
+ uint64_t PC = tc->readPC();
+ uint64_t NPC = tc->readNextPC();
+
+ //Increment the trap level
+ TL++;
+ tc->setMiscReg(MISCREG_TL, TL);
+
+ //Save off state
+
+ //set TSTATE.gl to gl
+ replaceBits(TSTATE, 42, 40, GL);
+ //set TSTATE.ccr to ccr
+ replaceBits(TSTATE, 39, 32, CCR);
+ //set TSTATE.asi to asi
+ replaceBits(TSTATE, 31, 24, ASI);
+ //set TSTATE.pstate to pstate
+ replaceBits(TSTATE, 20, 8, PSTATE);
+ //set TSTATE.cwp to cwp
+ replaceBits(TSTATE, 4, 0, CWP);
+
+ //Write back TSTATE
+ tc->setMiscReg(MISCREG_TSTATE, TSTATE);
+
+ //set TPC to PC
+ tc->setMiscReg(MISCREG_TPC, PC);
+ //set TNPC to NPC
+ tc->setMiscReg(MISCREG_TNPC, NPC);
+
+ //set HTSTATE.hpstate to hpstate
+ tc->setMiscReg(MISCREG_HTSTATE, HPSTATE);
+
+ //TT = trap type;
+ tc->setMiscReg(MISCREG_TT, tt);
+
+ //Update the global register level
+ if(1/*We're delivering the trap in priveleged mode*/)
+ tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL));
+ else
+ tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL));
+
+ //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(1/*We're delivering the trap in priveleged mode*/)
+ {
+ //PSTATE.priv = 1
+ PSTATE |= (1 << 2);
+ //PSTATE.cle = PSTATE.tle
+ replaceBits(PSTATE, 9, 9, PSTATE >> 8);
+ }
+ else
+ {
+ //PSTATE.priv = 0
+ PSTATE &= ~(1 << 2);
+ //PSTATE.cle = 0
+ PSTATE &= ~(1 << 9);
+ }
+ //PSTATE.ie = 0
+ PSTATE &= ~(1 << 1);
+ //PSTATE.tle is unchanged
+ //PSTATE.tct = 0
+ //XXX Where exactly is this field?
+ tc->setMiscReg(MISCREG_PSTATE, PSTATE);
+
+ if(0/*We're delivering the trap in hyperprivileged mode*/)
+ {
+ //HPSTATE.red = 0
+ HPSTATE &= ~(1 << 5);
+ //HPSTATE.hpriv = 1
+ HPSTATE |= (1 << 2);
+ //HPSTATE.ibe = 0
+ HPSTATE &= ~(1 << 10);
+ //HPSTATE.tlz is unchanged
+ tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
+ }
+
+ bool changedCWP = true;
+ if(tt == 0x24)
+ CWP++;
+ else if(0x80 <= tt && tt <= 0xbf)
+ CWP += (CANSAVE + 2);
+ else if(0xc0 <= tt && tt <= 0xff)
+ CWP--;
+ else
+ changedCWP = false;
+
+ if(changedCWP)
+ {
+ CWP = (CWP + NWindows) % NWindows;
+ tc->setMiscRegWithEffect(MISCREG_CWP, CWP);
+ }
+}
+
#if FULL_SYSTEM
void SparcFault::invoke(ThreadContext * tc)
@@ -263,6 +385,40 @@ void TrapInstruction::invoke(ThreadContext * tc)
// Should be handled in ISA.
}
+void SpillNNormal::invoke(ThreadContext *tc)
+{
+ doNormalFault(tc, trapType());
+
+ Process *p = tc->getProcessPtr();
+
+ //This will only work in faults from a SparcLiveProcess
+ SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
+ assert(lp);
+
+ //Then adjust the PC and NPC
+ Addr spillStart = lp->readSpillStart();
+ tc->setPC(spillStart);
+ tc->setNextPC(spillStart + sizeof(MachInst));
+ tc->setNextNPC(spillStart + 2*sizeof(MachInst));
+}
+
+void FillNNormal::invoke(ThreadContext *tc)
+{
+ doNormalFault(tc, trapType());
+
+ Process * p = tc->getProcessPtr();
+
+ //This will only work in faults from a SparcLiveProcess
+ SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p);
+ assert(lp);
+
+ //The adjust the PC and NPC
+ Addr fillStart = lp->readFillStart();
+ tc->setPC(fillStart);
+ tc->setNextPC(fillStart + sizeof(MachInst));
+ tc->setNextNPC(fillStart + 2*sizeof(MachInst));
+}
+
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
@@ -282,6 +438,7 @@ void PageTableFault::invoke(ThreadContext *tc)
FaultBase::invoke(tc);
}
}
+
#endif
} // namespace SparcISA
diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh
index b279f4911..394a06294 100644
--- a/src/arch/sparc/faults.hh
+++ b/src/arch/sparc/faults.hh
@@ -39,8 +39,8 @@
namespace SparcISA
{
-typedef const uint32_t TrapType;
-typedef const uint32_t FaultPriority;
+typedef uint32_t TrapType;
+typedef uint32_t FaultPriority;
class SparcFault : public FaultBase
{
@@ -547,6 +547,7 @@ class SpillNNormal : public EnumeratedFault
FaultName name() {return _name;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
};
class SpillNOther : public EnumeratedFault
@@ -577,6 +578,7 @@ class FillNNormal : public EnumeratedFault
FaultName name() {return _name;}
FaultPriority priority() {return _priority;}
FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
};
class FillNOther : public EnumeratedFault
diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc
index bef62f6ae..164f194dd 100644
--- a/src/arch/sparc/intregfile.cc
+++ b/src/arch/sparc/intregfile.cc
@@ -75,8 +75,14 @@ IntRegFile::IntRegFile()
IntReg IntRegFile::readReg(int intReg)
{
- IntReg val =
- regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
+ IntReg val;
+ if(intReg < NumRegularIntRegs)
+ val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
+ else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
+ val = microRegs[intReg];
+ else
+ panic("Tried to read non-existant integer register\n");
+
DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
return val;
}
@@ -86,7 +92,12 @@ Fault IntRegFile::setReg(int intReg, const IntReg &val)
if(intReg)
{
DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
- regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
+ if(intReg < NumRegularIntRegs)
+ regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
+ else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs)
+ microRegs[intReg] = val;
+ else
+ panic("Tried to set non-existant integer register\n");
}
return NoFault;
}
@@ -123,6 +134,7 @@ void IntRegFile::serialize(std::ostream &os)
SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
for(x = 0; x < 2 * NWindows; x++)
SERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
+ SERIALIZE_ARRAY(microRegs, NumMicroIntRegs);
}
void IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
@@ -132,4 +144,5 @@ void IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
for(unsigned int x = 0; x < 2 * NWindows; x++)
UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
+ UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs);
}
diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh
index d305c753b..223e3b34c 100644
--- a/src/arch/sparc/intregfile.hh
+++ b/src/arch/sparc/intregfile.hh
@@ -65,6 +65,7 @@ namespace SparcISA
IntReg regGlobals[MaxGL][RegsPerFrame];
IntReg regSegments[2 * NWindows][RegsPerFrame];
+ IntReg microRegs[NumMicroIntRegs];
enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa
index 372f5c4ef..7e884866c 100644
--- a/src/arch/sparc/isa/bitfields.isa
+++ b/src/arch/sparc/isa/bitfields.isa
@@ -50,7 +50,7 @@ def bitfield D16LO <13:0>;
def bitfield DISP19 <18:0>;
def bitfield DISP22 <21:0>;
def bitfield DISP30 <29:0>;
-def bitfield FCN <29:26>;
+def bitfield FCN <29:25>;
def bitfield I <13>;
def bitfield IMM_ASI <12:5>;
def bitfield IMM22 <21:0>;
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index 45d3616d9..a64ff09bb 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -357,13 +357,9 @@ decode OP default Unknown::unknown()
}});
}
0x29: HPriv::rdhpr({{
- // XXX Need to protect with format that traps non-priv/priv
- // access
Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
}});
0x2A: Priv::rdpr({{
- // XXX Need to protect with format that traps non-priv
- // access
Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
}});
0x2B: BasicOperate::flushw({{
@@ -425,18 +421,34 @@ decode OP default Unknown::unknown()
xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13);
}});
0x31: decode FCN {
- 0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
- 0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
+ 0x0: Priv::saved({{
+ assert(Cansave < NWindows - 2);
+ assert(Otherwin || Canrestore);
+ Cansave = Cansave + 1;
+ if(Otherwin == 0)
+ Canrestore = Canrestore - 1;
+ else
+ Otherwin = Otherwin - 1;
+ }});
+ 0x1: BasicOperate::restored({{
+ assert(Cansave || Otherwin);
+ assert(Canrestore < NWindows - 2);
+ Canrestore = Canrestore + 1;
+ if(Otherwin == 0)
+ Cansave = Cansave - 1;
+ else
+ Otherwin = Otherwin - 1;
+ }});
}
0x32: Priv::wrpr({{
// XXX Need to protect with format that traps non-priv
// access
- fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
+ xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
}});
0x33: HPriv::wrhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
- fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
+ xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
}});
0x34: decode OPF{
format BasicOperate{
@@ -684,10 +696,6 @@ decode OP default Unknown::unknown()
NNPC = target;
if(fault == NoFault)
{
- //CWP should be set directly so that it always happens
- //Also, this will allow writing to the new window and
- //reading from the old one
- Cwp = (Cwp - 1 + NWindows) % NWindows;
if(Canrestore == 0)
{
if(Otherwin)
@@ -697,14 +705,17 @@ decode OP default Unknown::unknown()
}
else
{
- Rd = Rs1 + Rs2_or_imm13;
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ Cwp = (Cwp - 1 + NWindows) % NWindows;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}
- //This is here to make sure the CWP is written
- //no matter what. This ensures that the results
- //are written in the new window as well.
- xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}
}});
0x3A: decode CC
@@ -747,11 +758,11 @@ decode OP default Unknown::unknown()
fault = new SpillNOther(Wstate<5:3>);
else
fault = new SpillNNormal(Wstate<2:0>);
- Cwp = (Cwp + 2) % NWindows;
+ //Cwp = (Cwp + 2) % NWindows;
}
else if(Cleanwin - Canrestore == 0)
{
- Cwp = (Cwp + 1) % NWindows;
+ //Cwp = (Cwp + 1) % NWindows;
fault = new CleanWindow;
}
else
@@ -760,17 +771,13 @@ decode OP default Unknown::unknown()
Rd = Rs1 + Rs2_or_imm13;
Cansave = Cansave - 1;
Canrestore = Canrestore + 1;
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}
- //This is here to make sure the CWP is written
- //no matter what. This ensures that the results
- //are written in the new window as well.
- xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}});
0x3D: restore({{
- //CWP should be set directly so that it always happens
- //Also, this will allow writing to the new window and
- //reading from the old one
- Cwp = (Cwp - 1 + NWindows) % NWindows;
if(Canrestore == 0)
{
if(Otherwin)
@@ -780,14 +787,18 @@ decode OP default Unknown::unknown()
}
else
{
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ Cwp = (Cwp - 1 + NWindows) % NWindows;
Rd = Rs1 + Rs2_or_imm13;
Cansave = Cansave + 1;
Canrestore = Canrestore - 1;
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}
- //This is here to make sure the CWP is written
- //no matter what. This ensures that the results
- //are written in the new window as well.
- xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
}});
0x3E: decode FCN {
0x0: Priv::done({{
@@ -812,7 +823,7 @@ decode OP default Unknown::unknown()
Ccr = Tstate<39:32>;
Gl = Tstate<42:40>;
NPC = Tpc;
- NNPC = Tnpc + 4;
+ NNPC = Tnpc;
Tl = Tl - 1;
}});
}
@@ -840,16 +851,15 @@ decode OP default Unknown::unknown()
0x09: ldsb({{Rd = (int8_t)Mem.sb;}});
0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
- 0x0D: ldstub({{
- Rd = Mem.ub;
- Mem.ub = 0xFF;
- }});
}
+ 0x0D: LoadStore::ldstub(
+ {{Rd = Mem.ub;}},
+ {{Mem.ub = 0xFF;}});
0x0E: Store::stx({{Mem.udw = Rd}});
0x0F: LoadStore::swap(
- {{*temp = Rd.uw;
+ {{uReg0 = Rd.uw;
Rd.uw = Mem.uw;}},
- {{Mem.uw = *temp;}});
+ {{Mem.uw = uReg0;}});
format Load {
0x10: lduwa({{Rd = Mem.uw;}});
0x11: lduba({{Rd = Mem.ub;}});
@@ -877,9 +887,9 @@ decode OP default Unknown::unknown()
{{Mem.ub = 0xFF}});
0x1E: Store::stxa({{Mem.udw = Rd}});
0x1F: LoadStore::swapa(
- {{*temp = Rd.uw;
+ {{uReg0 = Rd.uw;
Rd.uw = Mem.uw;}},
- {{Mem.uw = *temp;}});
+ {{Mem.uw = uReg0;}});
format Trap {
0x20: Load::ldf({{Frd.uw = Mem.uw;}});
0x21: decode X {
@@ -1062,19 +1072,21 @@ decode OP default Unknown::unknown()
{{fault = new DataAccessException;}});
}
}
- 0x3C: Cas::casa({{
- uint64_t val = Mem.uw;
- if(Rs2.uw == val)
+ 0x3C: Cas::casa(
+ {{uReg0 = Mem.uw;}},
+ {{if(Rs2.uw == uReg0)
Mem.uw = Rd.uw;
- Rd.uw = val;
- }});
+ else
+ storeCond = false;
+ Rd.uw = uReg0;}});
0x3D: Nop::prefetcha({{ }});
- 0x3E: Cas::casxa({{
- uint64_t val = Mem.udw;
- if(Rs2 == val)
+ 0x3E: Cas::casxa(
+ {{uReg0 = Mem.udw;}},
+ {{if(Rs2 == uReg0)
Mem.udw = Rd;
- Rd = val;
- }});
+ else
+ storeCond = false;
+ Rd = uReg0;}});
}
}
}
diff --git a/src/arch/sparc/isa/formats/formats.isa b/src/arch/sparc/isa/formats/formats.isa
index 5b81a1ab1..8125e6349 100644
--- a/src/arch/sparc/isa/formats/formats.isa
+++ b/src/arch/sparc/isa/formats/formats.isa
@@ -42,9 +42,6 @@
//Include the memory formats
##include "mem/mem.isa"
-//Include the compare and swap format
-##include "cas.isa"
-
//Include the trap format
##include "trap.isa"
diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa
index c13194d0f..cb6c2f161 100644
--- a/src/arch/sparc/isa/formats/mem/basicmem.isa
+++ b/src/arch/sparc/isa/formats/mem/basicmem.isa
@@ -32,100 +32,6 @@
// Mem instructions
//
-output header {{
- /**
- * Base class for memory operations.
- */
- class Mem : public SparcStaticInst
- {
- protected:
-
- // Constructor
- Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-
- /**
- * Class for memory operations which use an immediate offset.
- */
- class MemImm : public Mem
- {
- protected:
-
- // Constructor
- MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
- Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
- {}
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
-
- const int32_t imm;
- };
-}};
-
-output decoder {{
- std::string Mem::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- std::stringstream response;
- bool load = flags[IsLoad];
- bool save = flags[IsStore];
-
- printMnemonic(response, mnemonic);
- if(save)
- {
- printReg(response, _srcRegIdx[0]);
- ccprintf(response, ", ");
- }
- ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[!save ? 0 : 1]);
- ccprintf(response, " + ");
- printReg(response, _srcRegIdx[!save ? 1 : 2]);
- ccprintf(response, " ]");
- if(load)
- {
- ccprintf(response, ", ");
- printReg(response, _destRegIdx[0]);
- }
-
- return response.str();
- }
-
- std::string MemImm::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- std::stringstream response;
- bool load = flags[IsLoad];
- bool save = flags[IsStore];
-
- printMnemonic(response, mnemonic);
- if(save)
- {
- printReg(response, _srcRegIdx[0]);
- ccprintf(response, ", ");
- }
- ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[!save ? 0 : 1]);
- if(imm >= 0)
- ccprintf(response, " + 0x%x ]", imm);
- else
- ccprintf(response, " + -0x%x ]", -imm);
- if(load)
- {
- ccprintf(response, ", ");
- printReg(response, _destRegIdx[0]);
- }
-
- return response.str();
- }
-}};
-
def template MemDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
@@ -156,7 +62,7 @@ let {{
header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
decode_block = ROrImmDecode.subst(iop)
- exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute,
+ exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, execute,
faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags)
return (header_output, decoder_output, exec_output, decode_block)
}};
diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa
index 93ad1b2b8..8b4aca473 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -56,14 +56,14 @@ output header {{
{}
};
- class BlockMemMicro : public SparcDelayedMicroInst
+ class BlockMemMicro : public SparcMicroInst
{
protected:
// Constructor
BlockMemMicro(const char *mnem, ExtMachInst _machInst,
OpClass __opClass, int8_t _offset) :
- SparcDelayedMicroInst(mnem, _machInst, __opClass),
+ SparcMicroInst(mnem, _machInst, __opClass),
offset(_offset)
{}
@@ -290,6 +290,8 @@ let {{
flag_code = ''
if (microPc == 7):
flag_code = "flags[IsLastMicroOp] = true;"
+ else:
+ flag_code = "flags[IsDelayedCommit] = true;"
pcedCode = matcher.sub("Frd_%d" % microPc, code)
iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
opt_flags, {"ea_code": addrCalcReg,
@@ -301,7 +303,7 @@ let {{
"set_flags": flag_code})
decoder_output += BlockMemMicroConstructor.subst(iop)
decoder_output += BlockMemMicroConstructor.subst(iop_imm)
- exec_output += doSplitExecute(
+ exec_output += doDualSplitExecute(
pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
makeMicroName(name, microPc),
makeMicroName(name + "Imm", microPc),
diff --git a/src/arch/sparc/isa/formats/mem/mem.isa b/src/arch/sparc/isa/formats/mem/mem.isa
index 20a22c45d..fedece2b8 100644
--- a/src/arch/sparc/isa/formats/mem/mem.isa
+++ b/src/arch/sparc/isa/formats/mem/mem.isa
@@ -41,5 +41,5 @@
//Include the block memory format
##include "blockmem.isa"
-//Include the load/store memory format
+//Include the load/store and cas memory format
##include "loadstore.isa"
diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa
index 241a25d17..b9f7fde2d 100644
--- a/src/arch/sparc/isa/formats/mem/util.isa
+++ b/src/arch/sparc/isa/formats/mem/util.isa
@@ -33,6 +33,100 @@
// Mem utility templates and functions
//
+output header {{
+ /**
+ * Base class for memory operations.
+ */
+ class Mem : public SparcStaticInst
+ {
+ protected:
+
+ // Constructor
+ Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Class for memory operations which use an immediate offset.
+ */
+ class MemImm : public Mem
+ {
+ protected:
+
+ // Constructor
+ MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13))
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int32_t imm;
+ };
+}};
+
+output decoder {{
+ std::string Mem::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, " + ");
+ printReg(response, _srcRegIdx[!save ? 1 : 2]);
+ ccprintf(response, " ]");
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string MemImm::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ if(imm >= 0)
+ ccprintf(response, " + 0x%x ]", imm);
+ else
+ ccprintf(response, " + -0x%x ]", -imm);
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+}};
+
//This template provides the execute functions for a load
def template LoadExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
@@ -102,6 +196,9 @@ def template StoreExecute {{
{
Fault fault = NoFault;
uint64_t write_result = 0;
+ //This is to support the conditional store in cas instructions.
+ //It should be optomized out in all the others
+ bool storeCond = true;
Addr EA;
%(op_decl)s;
%(op_rd)s;
@@ -112,7 +209,7 @@ def template StoreExecute {{
{
%(code)s;
}
- if(fault == NoFault)
+ if(storeCond && fault == NoFault)
{
fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
}
@@ -130,6 +227,7 @@ def template StoreExecute {{
{
Fault fault = NoFault;
uint64_t write_result = 0;
+ bool storeCond = true;
Addr EA;
%(op_decl)s;
%(op_rd)s;
@@ -140,7 +238,7 @@ def template StoreExecute {{
{
%(code)s;
}
- if(fault == NoFault)
+ if(storeCond && fault == NoFault)
{
fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
}
@@ -204,23 +302,29 @@ let {{
//and in the other they're distributed across two. Also note that for
//execute functions, the name of the base class doesn't matter.
let {{
- def doSplitExecute(code, eaRegCode, eaImmCode, execute,
+ def doSplitExecute(code, eaCode, execute,
+ faultCode, name, Name, opt_flags):
+ codeIop = InstObjParams(name, Name, '', code, opt_flags)
+ eaIop = InstObjParams(name, Name, '', eaCode,
+ opt_flags, {"fault_check": faultCode})
+ iop = InstObjParams(name, Name, '', code, opt_flags,
+ {"fault_check": faultCode, "ea_code" : eaCode})
+ (iop.ea_decl,
+ iop.ea_rd,
+ iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
+ (iop.code_decl,
+ iop.code_rd,
+ iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
+ return execute.subst(iop)
+
+
+ def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags):
- codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags)
executeCode = ''
for (eaCode, name, Name) in (
(eaRegCode, nameReg, NameReg),
(eaImmCode, nameImm, NameImm)):
- eaIop = InstObjParams(name, Name, '', eaCode,
- opt_flags, {"fault_check": faultCode})
- iop = InstObjParams(name, Name, '', code, opt_flags,
- {"fault_check": faultCode, "ea_code" : eaCode})
- (iop.ea_decl,
- iop.ea_rd,
- iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb)
- (iop.code_decl,
- iop.code_rd,
- iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb)
- executeCode += execute.subst(iop)
+ executeCode += doSplitExecute(code, eaCode,
+ execute, faultCode, name, Name, opt_flags)
return executeCode
}};
diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
index 2a38422a7..04c67d332 100644
--- a/src/arch/sparc/isa/formats/priv.isa
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -121,15 +121,14 @@ let {{
// Primary format for integer operate instructions:
def format Priv(code, *opt_flags) {{
- checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) ||
- ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)'''
+ checkCode = "!(Pstate<2:2> || Hpstate<2:2>)"
(header_output, decoder_output,
exec_output, decode_block) = doPrivFormat(code,
checkCode, name, Name, opt_flags + ('IprAccessOp',))
}};
def format HPriv(code, *opt_flags) {{
- checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)"
+ checkCode = "!Hpstate<2:2>"
(header_output, decoder_output,
exec_output, decode_block) = doPrivFormat(code,
checkCode, name, Name, opt_flags + ('IprAccessOp',))
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index b8b75170b..80b499b91 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -61,6 +61,7 @@ def operands {{
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
+ 'uReg0': ('IntReg', 'udw', 'NumRegularIntRegs+0', 'IsInteger', 6),
'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
# Each Frd_N refers to the Nth double precision register from Frd.
@@ -95,18 +96,19 @@ def operands {{
'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44),
'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45),
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46),
- 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47),
+ 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47),
+ 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48),
- 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48),
- 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49),
- 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50),
- 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51),
- 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52),
- 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53),
- 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54),
+ 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49),
+ 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50),
+ 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51),
+ 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52),
+ 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53),
+ 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54),
+ 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55),
- 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55),
- 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56),
+ 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56),
+ 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57),
# Mem gets a large number so it's always last
'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 6d5aa4251..46a0ebbfb 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -57,14 +57,17 @@ namespace SparcISA
//This makes sure the big endian versions of certain functions are used.
using namespace BigEndianGuest;
- // Alpha Does NOT have a delay slot
+ // SPARC has a delay slot
#define ISA_HAS_DELAY_SLOT 1
- //TODO this needs to be a SPARC Noop
- // Alpha UNOP (ldq_u r31,0(r0))
- const MachInst NoopMachInst = 0x2ffe0000;
+ // SPARC NOP (sethi %(hi(0), g0)
+ const MachInst NoopMachInst = 0x01000000;
- const int NumIntRegs = 32;
+ const int NumRegularIntRegs = 32;
+ const int NumMicroIntRegs = 1;
+ const int NumIntRegs =
+ NumRegularIntRegs +
+ NumMicroIntRegs;
const int NumFloatRegs = 64;
const int NumMiscRegs = 40;
@@ -87,7 +90,7 @@ namespace SparcISA
const int MaxPGL = 2;
// NWINDOWS - number of register windows, can be 3 to 32
- const int NWindows = 32;
+ const int NWindows = 8;
// semantically meaningful register indices
const int ZeroReg = 0; // architecturally meaningful
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
index 8041e45c0..bf4572878 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -202,282 +202,164 @@ MiscReg MiscRegFile::readReg(int miscReg)
}
}
-MiscReg MiscRegFile::readRegWithEffect(int miscReg,
- Fault &fault, ThreadContext * tc)
+MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
{
- fault = NoFault;
switch (miscReg) {
- case MISCREG_Y:
- case MISCREG_CCR:
- case MISCREG_ASI:
- return readReg(miscReg);
-
case MISCREG_TICK:
case MISCREG_PRIVTICK:
- // Check for reading privilege
- if (tickFields.npt && !isNonPriv()) {
- fault = new PrivilegedAction;
- return 0;
- }
return tc->getCpuPtr()->curCycle() - tickFields.counter |
tickFields.npt << 63;
- case MISCREG_PC:
- return tc->readPC();
case MISCREG_FPRS:
- fault = new UnimpFault("FPU not implemented\n");
- return 0;
+ panic("FPU not implemented\n");
case MISCREG_PCR:
- fault = new UnimpFault("Performance Instrumentation not impl\n");
- return 0;
case MISCREG_PIC:
- fault = new UnimpFault("Performance Instrumentation not impl\n");
- return 0;
- case MISCREG_GSR:
- return readReg(miscReg);
-
- /** Privilged Registers */
- case MISCREG_TPC:
- case MISCREG_TNPC:
- case MISCREG_TSTATE:
- case MISCREG_TT:
- if (tl == 0) {
- fault = new IllegalInstruction;
- return 0;
- } // NOTE THE FALL THROUGH!
- case MISCREG_PSTATE:
- case MISCREG_TL:
- return readReg(miscReg);
-
- case MISCREG_TBA:
- return readReg(miscReg) & ULL(~0x7FFF);
-
- case MISCREG_PIL:
-
- case MISCREG_CWP:
- case MISCREG_CANSAVE:
- case MISCREG_CANRESTORE:
- case MISCREG_CLEANWIN:
- case MISCREG_OTHERWIN:
- case MISCREG_WSTATE:
- case MISCREG_GL:
- return readReg(miscReg);
+ panic("Performance Instrumentation not impl\n");
/** Floating Point Status Register */
case MISCREG_FSR:
panic("Floating Point not implemented\n");
- default:
-#if FULL_SYSTEM
- return readFSRegWithEffect(miscReg, fault, tc);
-#else
- fault = new IllegalInstruction;
- return 0;
-#endif
}
+ return readReg(miscReg);
}
-Fault MiscRegFile::setReg(int miscReg, const MiscReg &val)
+void MiscRegFile::setReg(int miscReg, const MiscReg &val)
{
switch (miscReg) {
case MISCREG_Y:
y = val;
- return NoFault;
+ break;
case MISCREG_CCR:
ccr = val;
- return NoFault;
+ break;
case MISCREG_ASI:
asi = val;
- return NoFault;
+ break;
case MISCREG_FPRS:
fprs = val;
- return NoFault;
+ break;
case MISCREG_TICK:
- tick = val;
- return NoFault;
+ tick = val;
+ break;
case MISCREG_PCR:
case MISCREG_PIC:
panic("ASR number %d not implemented\n", miscReg - AsrStart);
case MISCREG_GSR:
gsr = val;
+ break;
case MISCREG_SOFTINT:
- softint = val;
- return NoFault;
+ softint = val;
+ break;
case MISCREG_TICK_CMPR:
- tick_cmpr = val;
- return NoFault;
+ tick_cmpr = val;
+ break;
case MISCREG_STICK:
- stick = val;
- return NoFault;
+ stick = val;
+ break;
case MISCREG_STICK_CMPR:
- stick_cmpr = val;
- return NoFault;
+ stick_cmpr = val;
+ break;
/** Privilged Registers */
case MISCREG_TPC:
tpc[tl-1] = val;
- return NoFault;
+ break;
case MISCREG_TNPC:
tnpc[tl-1] = val;
- return NoFault;
+ break;
case MISCREG_TSTATE:
tstate[tl-1] = val;
- return NoFault;
+ break;
case MISCREG_TT:
tt[tl-1] = val;
- return NoFault;
+ break;
case MISCREG_PRIVTICK:
panic("Priviliged access to tick regesiters not implemented\n");
case MISCREG_TBA:
- tba = val;
- return NoFault;
+ // clear lower 7 bits on writes.
+ tba = val & ULL(~0x7FFF);
+ break;
case MISCREG_PSTATE:
pstate = val;
- return NoFault;
+ break;
case MISCREG_TL:
tl = val;
- return NoFault;
+ break;
case MISCREG_PIL:
pil = val;
- return NoFault;
+ break;
case MISCREG_CWP:
cwp = val;
- return NoFault;
+ break;
case MISCREG_CANSAVE:
cansave = val;
- return NoFault;
+ break;
case MISCREG_CANRESTORE:
canrestore = val;
- return NoFault;
+ break;
case MISCREG_CLEANWIN:
cleanwin = val;
- return NoFault;
+ break;
case MISCREG_OTHERWIN:
otherwin = val;
- return NoFault;
+ break;
case MISCREG_WSTATE:
wstate = val;
- return NoFault;
+ break;
case MISCREG_GL:
gl = val;
- return NoFault;
+ break;
/** Hyper privileged registers */
case MISCREG_HPSTATE:
hpstate = val;
- return NoFault;
+ break;
case MISCREG_HTSTATE:
htstate[tl-1] = val;
- return NoFault;
+ break;
case MISCREG_HINTP:
panic("HINTP not implemented\n");
case MISCREG_HTBA:
htba = val;
- return NoFault;
+ break;
case MISCREG_STRAND_STS_REG:
strandStatusReg = val;
- return NoFault;
+ break;
case MISCREG_HSTICK_CMPR:
hstick_cmpr = val;
- return NoFault;
+ break;
/** Floating Point Status Register */
case MISCREG_FSR:
fsr = val;
- return NoFault;
+ break;
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
-Fault MiscRegFile::setRegWithEffect(int miscReg,
+void MiscRegFile::setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc)
{
const uint64_t Bit64 = (1ULL << 63);
switch (miscReg) {
- case MISCREG_Y:
- case MISCREG_CCR:
- case MISCREG_ASI:
- setReg(miscReg, val);
- return NoFault;
- case MISCREG_PRIVTICK:
case MISCREG_TICK:
- if (isNonPriv())
- return new PrivilegedOpcode;
- if (isPriv())
- return new PrivilegedAction;
tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64;
tickFields.npt = val & Bit64 ? 1 : 0;
- return NoFault;
- case MISCREG_PC:
- return new IllegalInstruction;
+ break;
case MISCREG_FPRS:
- return new UnimpFault("FPU not implemented\n");
+ //Configure the fpu based on the fprs
+ break;
case MISCREG_PCR:
- return new UnimpFault("Performance Instrumentation not impl\n");
- case MISCREG_PIC:
- return new UnimpFault("Performance Instrumentation not impl\n");
- case MISCREG_GSR:
- return setReg(miscReg, val);
-
- /** Privilged Registers */
- case MISCREG_TPC:
- case MISCREG_TNPC:
- case MISCREG_TSTATE:
- case MISCREG_TT:
- if (tl == 0)
- return new IllegalInstruction;
- setReg(miscReg, val);
- return NoFault;
-
- case MISCREG_TBA:
- // clear lower 7 bits on writes.
- setReg(miscReg, val & ULL(~0x7FFF));
- return NoFault;
-
- case MISCREG_PSTATE:
- setReg(miscReg, val);
- return NoFault;
-
- case MISCREG_TL:
- if (isHyperPriv() && val > MaxTL)
- setReg(miscReg, MaxTL);
- else if (isPriv() && !isHyperPriv() && val > MaxPTL)
- setReg(miscReg, MaxPTL);
- else
- setReg(miscReg, val);
- return NoFault;
-
+ //Set up performance counting based on pcr value
+ break;
case MISCREG_CWP:
tc->changeRegFileContext(CONTEXT_CWP, val);
- case MISCREG_CANSAVE:
- case MISCREG_CANRESTORE:
- case MISCREG_CLEANWIN:
- case MISCREG_OTHERWIN:
- case MISCREG_WSTATE:
- setReg(miscReg, val);
- return NoFault;
-
+ break;
case MISCREG_GL:
- int newval;
- if (isHyperPriv() && val > MaxGL)
- newval = MaxGL;
- else if (isPriv() && !isHyperPriv() && val > MaxPGL)
- newval = MaxPGL;
- else
- newval = val;
- tc->changeRegFileContext(CONTEXT_GLOBALS, newval);
- setReg(miscReg, newval);
- return NoFault;
-
- /** Floating Point Status Register */
- case MISCREG_FSR:
- panic("Floating Point not implemented\n");
- default:
-#if FULL_SYSTEM
- setFSRegWithEffect(miscReg, val, tc);
-#else
- return new IllegalInstruction;
-#endif
+ tc->changeRegFileContext(CONTEXT_GLOBALS, val);
+ break;
}
+ setReg(miscReg, val);
}
void MiscRegFile::serialize(std::ostream & os)
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index be143311f..771cb1ed6 100644
--- a/src/arch/sparc/miscregfile.hh
+++ b/src/arch/sparc/miscregfile.hh
@@ -56,7 +56,6 @@ namespace SparcISA
MISCREG_CCR = AsrStart + 2,
MISCREG_ASI = AsrStart + 3,
MISCREG_TICK = AsrStart + 4,
- MISCREG_PC = AsrStart + 5,
MISCREG_FPRS = AsrStart + 6,
MISCREG_PCR = AsrStart + 16,
MISCREG_PIC = AsrStart + 17,
@@ -366,31 +365,13 @@ namespace SparcISA
reset();
}
- /** read a value out of an either an SE or FS IPR. No checking is done
- * about SE vs. FS as this is mostly used to copy the regfile. Thus more
- * register are copied that are necessary for FS. However this prevents
- * a bunch of ifdefs and is rarely called so is not performance
- * criticial. */
MiscReg readReg(int miscReg);
- /** Read a value from an IPR. Only the SE iprs are here and the rest
- * are are readFSRegWithEffect (which is called by readRegWithEffect()).
- * Checking is done for permission based on state bits in the miscreg
- * file. */
- MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
-
- /** write a value into an either an SE or FS IPR. No checking is done
- * about SE vs. FS as this is mostly used to copy the regfile. Thus more
- * register are copied that are necessary for FS. However this prevents
- * a bunch of ifdefs and is rarely called so is not performance
- * criticial.*/
- Fault setReg(int miscReg, const MiscReg &val);
-
- /** Write a value into an IPR. Only the SE iprs are here and the rest
- * are are setFSRegWithEffect (which is called by setRegWithEffect()).
- * Checking is done for permission based on state bits in the miscreg
- * file. */
- Fault setRegWithEffect(int miscReg,
+ MiscReg readRegWithEffect(int miscReg, ThreadContext *tc);
+
+ void setReg(int miscReg, const MiscReg &val);
+
+ void setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc);
void serialize(std::ostream & os);
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 3323ba7a0..a3b7dde7c 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -66,6 +66,10 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
+ //Initialize these to 0s
+ fillStart = 0;
+ spillStart = 0;
}
void
@@ -88,15 +92,19 @@ SparcLiveProcess::startup()
*/
//No windows contain info from other programs
- threadContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
+ threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0);
//There are no windows to pop
- threadContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
+ threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0);
//All windows are available to save into
- threadContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
+ threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2);
//All windows are "clean"
- threadContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
+ threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows);
//Start with register window 0
- threadContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
+ threadContexts[0]->setMiscReg(MISCREG_CWP, 0);
+ //Always use spill and fill traps 0
+ threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0);
+ //Set the trap level to 0
+ threadContexts[0]->setMiscReg(MISCREG_TL, 0);
}
m5_auxv_t buildAuxVect(int64_t type, int64_t val)
@@ -107,6 +115,83 @@ m5_auxv_t buildAuxVect(int64_t type, int64_t val)
return result;
}
+//We only use 19 instructions for the trap handlers, but there would be
+//space for 32 in a real SPARC trap table.
+const int numFillInsts = 32;
+const int numSpillInsts = 32;
+
+MachInst fillHandler[numFillInsts] =
+{
+ htog(0x87802018), //wr %g0, ASI_AIUP, %asi
+ htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0
+ htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1
+ htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2
+ htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3
+ htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4
+ htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5
+ htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6
+ htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7
+ htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0
+ htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1
+ htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2
+ htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3
+ htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4
+ htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5
+ htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6
+ htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7
+ htog(0x83880000), //restored
+ htog(0x83F00000), //retry
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000) //illtrap
+};
+
+MachInst spillHandler[numSpillInsts] =
+{
+ htog(0x87802018), //wr %g0, ASI_AIUP, %asi
+ htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi
+ htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi
+ htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi
+ htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi
+ htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi
+ htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi
+ htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi
+ htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi
+ htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi
+ htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi
+ htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi
+ htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi
+ htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi
+ htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi
+ htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi
+ htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi
+ htog(0x81880000), //saved
+ htog(0x83F00000), //retry
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000), //illtrap
+ htog(0x00000000) //illtrap
+};
+
void
SparcLiveProcess::argsInit(int intSize, int pageSize)
{
@@ -317,6 +402,17 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
+ //Stuff the trap handlers into the processes address space.
+ //Since the stack grows down and is the highest area in the processes
+ //address space, we can put stuff above it and stay out of the way.
+ int fillSize = sizeof(MachInst) * numFillInsts;
+ int spillSize = sizeof(MachInst) * numSpillInsts;
+ fillStart = stack_base;
+ spillStart = fillStart + fillSize;
+ initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler, fillSize);
+ initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler, spillSize);
+
+ //Set up the thread context to start running the process
threadContexts[0]->setIntReg(ArgumentReg0, argc);
threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
index 7cc52e241..2320810c7 100644
--- a/src/arch/sparc/process.hh
+++ b/src/arch/sparc/process.hh
@@ -55,6 +55,9 @@ class SparcLiveProcess : public LiveProcess
static const Addr StackBias = 2047;
+ //The locations of the fill and spill handlers
+ Addr fillStart, spillStart;
+
std::vector<m5_auxv_t> auxv;
SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
@@ -71,6 +74,12 @@ class SparcLiveProcess : public LiveProcess
void argsInit(int intSize, int pageSize);
+ Addr readFillStart()
+ { return fillStart; }
+
+ Addr readSpillStart()
+ { return spillStart; }
+
};
#endif // __SPARC_PROCESS_HH__
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 747426781..5eb874d39 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -82,18 +82,21 @@ MiscReg RegFile::readMiscReg(int miscReg)
MiscReg RegFile::readMiscRegWithEffect(int miscReg,
Fault &fault, ThreadContext *tc)
{
- return miscRegFile.readRegWithEffect(miscReg, fault, tc);
+ fault = NoFault;
+ return miscRegFile.readRegWithEffect(miscReg, tc);
}
Fault RegFile::setMiscReg(int miscReg, const MiscReg &val)
{
- return miscRegFile.setReg(miscReg, val);
+ miscRegFile.setReg(miscReg, val);
+ return NoFault;
}
Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext * tc)
{
- return miscRegFile.setRegWithEffect(miscReg, val, tc);
+ miscRegFile.setRegWithEffect(miscReg, val, tc);
+ return NoFault;
}
FloatReg RegFile::readFloatReg(int floatReg, int width)
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
index 879780d56..177279678 100644
--- a/src/base/bitfield.hh
+++ b/src/base/bitfield.hh
@@ -69,4 +69,28 @@ sext(uint64_t val)
return sign_bit ? (val | ~mask(N)) : val;
}
+/**
+ * Return val with bits first to last set to bit_val
+ */
+template <class T, class B>
+inline
+T
+insertBits(T val, int first, int last, B bit_val)
+{
+ T bmask = mask(first - last + 1) << last;
+ return ((bit_val << last) & bmask) | (val & ~bmask);
+}
+
+/**
+ * A convenience function to replace bits first to last of val with bit_val
+ * in place.
+ */
+template <class T, class B>
+inline
+void
+replaceBits(T& val, int first, int last, B bit_val)
+{
+ val = insertBits(val, first, last, bit_val);
+}
+
#endif // __BASE_BITFIELD_HH__
diff --git a/src/cpu/ozone/back_end.hh b/src/cpu/ozone/back_end.hh
index 8debd277d..992f55c6e 100644
--- a/src/cpu/ozone/back_end.hh
+++ b/src/cpu/ozone/back_end.hh
@@ -35,7 +35,7 @@
#include <queue>
#include <string>
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "base/timebuf.hh"
#include "cpu/inst_seq.hh"
#include "cpu/ozone/rename_table.hh"
diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh
index 0a1e1c139..9d42ab05b 100644
--- a/src/cpu/ozone/dyn_inst_impl.hh
+++ b/src/cpu/ozone/dyn_inst_impl.hh
@@ -28,7 +28,7 @@
* Authors: Kevin Lim
*/
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "config/full_system.hh"
#include "cpu/ozone/dyn_inst.hh"
#include "kern/kernel_stats.hh"
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index b8fce4292..63cf0a952 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -30,7 +30,7 @@
#include "config/use_checker.hh"
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "arch/isa_traits.hh"
#include "arch/utility.hh"
#include "base/statistics.hh"
diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh
index 76eef6fad..b2522bdc8 100644
--- a/src/cpu/ozone/inorder_back_end.hh
+++ b/src/cpu/ozone/inorder_back_end.hh
@@ -33,7 +33,7 @@
#include <list>
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "base/timebuf.hh"
#include "cpu/thread_context.hh"
#include "cpu/inst_seq.hh"
diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh
index 16ebac163..8aef9c074 100644
--- a/src/cpu/ozone/inorder_back_end_impl.hh
+++ b/src/cpu/ozone/inorder_back_end_impl.hh
@@ -28,7 +28,7 @@
* Authors: Kevin Lim
*/
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "arch/types.hh"
#include "cpu/ozone/inorder_back_end.hh"
#include "cpu/ozone/thread_state.hh"
diff --git a/src/cpu/ozone/lw_back_end.hh b/src/cpu/ozone/lw_back_end.hh
index 49c6a1ae2..08a6863d0 100644
--- a/src/cpu/ozone/lw_back_end.hh
+++ b/src/cpu/ozone/lw_back_end.hh
@@ -36,7 +36,7 @@
#include <set>
#include <string>
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "base/timebuf.hh"
#include "cpu/inst_seq.hh"
#include "cpu/ozone/rename_table.hh"
diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh
index c226d7502..9a1584b4c 100644
--- a/src/cpu/ozone/thread_state.hh
+++ b/src/cpu/ozone/thread_state.hh
@@ -31,7 +31,7 @@
#ifndef __CPU_OZONE_THREAD_STATE_HH__
#define __CPU_OZONE_THREAD_STATE_HH__
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "arch/types.hh"
#include "arch/regfile.hh"
#include "base/callback.hh"
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index bfb80dc0f..dace83ac0 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -179,8 +179,11 @@ AtomicSimpleCPU::resume()
changeState(SimObject::Running);
if (thread->status() == ThreadContext::Active) {
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick);
+ if (!tickEvent.scheduled()) {
+ Tick nextTick = curTick + cycles(1) - 1;
+ nextTick -= (nextTick % (cycles(1)));
+ tickEvent.schedule(nextTick);
+ }
}
}
}
@@ -208,7 +211,9 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
ThreadContext *tc = threadContexts[i];
if (tc->status() == ThreadContext::Active && _status != Running) {
_status = Running;
- tickEvent.schedule(curTick);
+ Tick nextTick = curTick + cycles(1) - 1;
+ nextTick -= (nextTick % (cycles(1)));
+ tickEvent.schedule(nextTick);
break;
}
}
@@ -225,7 +230,10 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay)
assert(!tickEvent.scheduled());
notIdleFraction++;
- tickEvent.schedule(curTick + cycles(delay));
+ //Make sure ticks are still on multiples of cycles
+ Tick nextTick = curTick + cycles(delay + 1) - 1;
+ nextTick -= (nextTick % (cycles(1)));
+ tickEvent.schedule(nextTick);
_status = Running;
}
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index dc06c17f5..47b3b938f 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -401,13 +401,15 @@ BaseSimpleCPU::preExecute()
StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
if (instPtr->isMacroOp()) {
curMacroStaticInst = instPtr;
- curStaticInst = curMacroStaticInst->fetchMicroOp(0);
+ curStaticInst = curMacroStaticInst->
+ fetchMicroOp(thread->readMicroPC());
} else {
curStaticInst = instPtr;
}
} else {
//Read the next micro op from the macro op
- curStaticInst = curMacroStaticInst->fetchMicroOp(thread->readMicroPC());
+ curStaticInst = curMacroStaticInst->
+ fetchMicroOp(thread->readMicroPC());
}
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 677ba6592..f81b78147 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -66,6 +66,8 @@ ThreadState::serialize(std::ostream &os)
// thread_num and cpu_id are deterministic from the config
SERIALIZE_SCALAR(funcExeInst);
SERIALIZE_SCALAR(inst);
+ SERIALIZE_SCALAR(microPC);
+ SERIALIZE_SCALAR(nextMicroPC);
#if FULL_SYSTEM
Tick quiesceEndTick = 0;
@@ -85,6 +87,8 @@ ThreadState::unserialize(Checkpoint *cp, const std::string &section)
// thread_num and cpu_id are deterministic from the config
UNSERIALIZE_SCALAR(funcExeInst);
UNSERIALIZE_SCALAR(inst);
+ UNSERIALIZE_SCALAR(microPC);
+ UNSERIALIZE_SCALAR(nextMicroPC);
#if FULL_SYSTEM
Tick quiesceEndTick;
diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc
index e52a3e73d..7fc68f4e7 100644
--- a/src/dev/i8254xGBe.cc
+++ b/src/dev/i8254xGBe.cc
@@ -38,6 +38,7 @@
#include "base/inet.hh"
#include "dev/i8254xGBe.hh"
#include "mem/packet.hh"
+#include "mem/packet_access.hh"
#include "sim/builder.hh"
#include "sim/stats.hh"
#include "sim/system.hh"
@@ -66,12 +67,17 @@ IGbE::IGbE(Params *p)
regs.tctl.reg = 0;
regs.manc.reg = 0;
+ regs.pba.rxa = 0x30;
+ regs.pba.txa = 0x10;
+
eeOpBits = 0;
eeAddrBits = 0;
eeDataBits = 0;
eeOpcode = 0;
- memset(&flash, 0, EEPROM_SIZE);
+ // clear all 64 16 bit words of the eeprom
+ memset(&flash, 0, EEPROM_SIZE*2);
+
// Magic happy checksum value
flash[0] = 0xBABA;
}
@@ -108,7 +114,7 @@ IGbE::read(PacketPtr pkt)
// Only 32bit accesses allowed
assert(pkt->getSize() == 4);
- DPRINTF(Ethernet, "Read device register %#X\n", daddr);
+ //DPRINTF(Ethernet, "Read device register %#X\n", daddr);
pkt->allocate();
@@ -116,6 +122,7 @@ IGbE::read(PacketPtr pkt)
/// Handle read of register here
///
+
switch (daddr) {
case CTRL:
pkt->set<uint32_t>(regs.ctrl.reg);
@@ -141,11 +148,23 @@ IGbE::read(PacketPtr pkt)
case TCTL:
pkt->set<uint32_t>(regs.tctl.reg);
break;
+ case PBA:
+ pkt->set<uint32_t>(regs.pba.reg);
+ break;
+ case WUC:
+ case LEDCTL:
+ pkt->set<uint32_t>(0); // We don't care, so just return 0
+ break;
case MANC:
pkt->set<uint32_t>(regs.manc.reg);
break;
default:
- panic("Read request to unknown register number: %#x\n", daddr);
+ if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
+ !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
+ !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
+ pkt->set<uint32_t>(0);
+ else
+ panic("Read request to unknown register number: %#x\n", daddr);
};
pkt->result = Packet::Success;
@@ -168,7 +187,7 @@ IGbE::write(PacketPtr pkt)
// Only 32bit accesses allowed
assert(pkt->getSize() == sizeof(uint32_t));
- DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
+ //DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
///
/// Handle write of register here
@@ -195,10 +214,10 @@ IGbE::write(PacketPtr pkt)
eeAddr = eeAddr << 1 | regs.eecd.din;
eeAddrBits++;
} else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
- assert(eeAddr < EEPROM_SIZE);
- DPRINTF(Ethernet, "EEPROM bit read: %d word: %#X\n",
- flash[eeAddr] >> eeDataBits & 0x1, flash[eeAddr]);
- regs.eecd.dout = (flash[eeAddr] >> eeDataBits) & 0x1;
+ assert(eeAddr>>1 < EEPROM_SIZE);
+ DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
+ flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]);
+ regs.eecd.dout = (flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1;
eeDataBits++;
} else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
regs.eecd.dout = 0;
@@ -219,8 +238,9 @@ IGbE::write(PacketPtr pkt)
eeAddr = 0;
}
- DPRINTF(Ethernet, "EEPROM: opcode: %#X:%d\n",
- (uint32_t)eeOpcode, (uint32_t) eeOpBits);
+ DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
+ (uint32_t)eeOpcode, (uint32_t) eeOpBits,
+ (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI ||
eeOpcode == EEPROM_RDSR_OPCODE_SPI ))
panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
@@ -246,11 +266,22 @@ IGbE::write(PacketPtr pkt)
case TCTL:
regs.tctl.reg = val;
break;
+ case PBA:
+ regs.pba.rxa = val;
+ regs.pba.txa = 64 - regs.pba.rxa;
+ break;
+ case WUC:
+ case LEDCTL:
+ ; // We don't care, so don't store anything
+ break;
case MANC:
regs.manc.reg = val;
break;
default:
- panic("Write request to unknown register number: %#x\n", daddr);
+ if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) &&
+ !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) &&
+ !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4))
+ panic("Write request to unknown register number: %#x\n", daddr);
};
pkt->result = Packet::Success;
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
index 55a461a8b..086d91279 100644
--- a/src/mem/tport.cc
+++ b/src/mem/tport.cc
@@ -33,16 +33,18 @@
void
SimpleTimingPort::recvFunctional(PacketPtr pkt)
{
- std::list<PacketPtr>::iterator i = transmitList.begin();
- std::list<PacketPtr>::iterator end = transmitList.end();
+ std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
+ bool done = false;
- while (i != end) {
- PacketPtr target = *i;
+ while (i != end && !done) {
+ PacketPtr target = i->second;
// If the target contains data, and it overlaps the
// probed request, need to update data
if (target->intersect(pkt))
- fixPacket(pkt, target);
+ done = fixPacket(pkt, target);
+ i++;
}
//Then just do an atomic access and throw away the returned latency
@@ -63,7 +65,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
// turn packet around to go back to requester if response expected
if (pkt->needsResponse()) {
pkt->makeTimingResponse();
- sendTimingLater(pkt, latency);
+ sendTiming(pkt, latency);
}
else {
if (pkt->cmd != Packet::UpgradeReq)
@@ -78,14 +80,14 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
void
SimpleTimingPort::recvRetry()
{
- assert(outTiming > 0);
assert(!transmitList.empty());
- if (sendTiming(transmitList.front())) {
+ if (Port::sendTiming(transmitList.front().second)) {
transmitList.pop_front();
- outTiming--;
DPRINTF(Bus, "No Longer waiting on retry\n");
- if (!transmitList.empty())
- sendTimingLater(transmitList.front(), 1);
+ if (!transmitList.empty()) {
+ Tick time = transmitList.front().first;
+ sendEvent.schedule(time <= curTick ? curTick+1 : time);
+ }
}
if (transmitList.empty() && drainEvent) {
@@ -95,38 +97,61 @@ SimpleTimingPort::recvRetry()
}
void
+SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
+{
+ // Nothing is on the list: add it and schedule an event
+ if (transmitList.empty()) {
+ assert(!sendEvent.scheduled());
+ sendEvent.schedule(curTick+time);
+ transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ return;
+ }
+
+ // something is on the list and this belongs at the end
+ if (time+curTick >= transmitList.back().first) {
+ transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ return;
+ }
+ // Something is on the list and this belongs somewhere else
+ std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
+ bool done = false;
+
+ while (i != end && !done) {
+ if (time+curTick < i->first)
+ transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ i++;
+ }
+}
+
+void
SimpleTimingPort::SendEvent::process()
{
- assert(port->outTiming > 0);
- if (!port->transmitList.empty() && port->transmitList.front() != packet) {
- //We are not the head of the list
- port->transmitList.push_back(packet);
- } else if (port->sendTiming(packet)) {
- // send successful
- if (port->transmitList.size()) {
- port->transmitList.pop_front();
- port->outTiming--;
- if (!port->transmitList.empty())
- port->sendTimingLater(port->transmitList.front(), 1);
+ assert(port->transmitList.size());
+ assert(port->transmitList.front().first <= curTick);
+ if (port->Port::sendTiming(port->transmitList.front().second)) {
+ //send successful, remove packet
+ port->transmitList.pop_front();
+ if (!port->transmitList.empty()) {
+ Tick time = port->transmitList.front().first;
+ schedule(time <= curTick ? curTick+1 : time);
}
if (port->transmitList.empty() && port->drainEvent) {
port->drainEvent->process();
port->drainEvent = NULL;
}
- } else {
- // send unsuccessful (due to flow control). Will get retry
- // callback later; save for then if not already
- DPRINTF(Bus, "Waiting on retry\n");
- if (!(port->transmitList.front() == packet))
- port->transmitList.push_back(packet);
+ return;
}
+ // send unsuccessful (due to flow control). Will get retry
+ // callback later; save for then if not already
+ DPRINTF(Bus, "Waiting on retry\n");
}
unsigned int
SimpleTimingPort::drain(Event *de)
{
- if (outTiming == 0 && transmitList.size() == 0)
+ if (transmitList.size() == 0)
return 0;
drainEvent = de;
return 1;
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
index b419b7c7f..3d28ea3e5 100644
--- a/src/mem/tport.hh
+++ b/src/mem/tport.hh
@@ -60,23 +60,22 @@ class SimpleTimingPort : public Port
protected:
/** A list of outgoing timing response packets that haven't been
* serviced yet. */
- std::list<PacketPtr> transmitList;
+ std::list<std::pair<Tick,PacketPtr> > transmitList;
/**
* This class is used to implemented sendTiming() with a delay. When
- * a delay is requested a new event is created. When the event time
- * expires it attempts to send the packet. If it cannot, the packet
- * is pushed onto the transmit list to be sent when recvRetry() is
- * called. */
+ * a delay is requested a the event is scheduled if it isn't already.
+ * When the event time expires it attempts to send the packet.
+ * If it cannot, the packet sent when recvRetry() is called.
+ **/
class SendEvent : public Event
{
SimpleTimingPort *port;
- PacketPtr packet;
public:
- SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t)
- : Event(&mainEventQueue), port(p), packet(pkt)
- { setFlags(AutoDelete); schedule(curTick + t); }
+ SendEvent(SimpleTimingPort *p)
+ : Event(&mainEventQueue), port(p)
+ { }
virtual void process();
@@ -84,19 +83,17 @@ class SimpleTimingPort : public Port
{ return "Future scheduled sendTiming event"; }
};
-
- /** Number of timing requests that are emulating the device timing before
- * attempting to end up on the bus.
- */
- int outTiming;
+ SendEvent sendEvent;
/** If we need to drain, keep the drain event around until we're done
* here.*/
Event *drainEvent;
- /** Schedule a sendTiming() event to be called in the future. */
- void sendTimingLater(PacketPtr pkt, Tick time)
- { outTiming++; new SendEvent(this, pkt, time); }
+ /** Schedule a sendTiming() event to be called in the future.
+ * @param pkt packet to send
+ * @param time increment from now (in ticks) to send packet
+ */
+ void sendTiming(PacketPtr pkt, Tick time);
/** This function is notification that the device should attempt to send a
* packet again. */
@@ -118,7 +115,7 @@ class SimpleTimingPort : public Port
public:
SimpleTimingPort(std::string pname, MemObject *_owner = NULL)
- : Port(pname, _owner), outTiming(0), drainEvent(NULL)
+ : Port(pname, _owner), sendEvent(this), drainEvent(NULL)
{}
/** Hook for draining timing accesses from the system. The
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index d12b06b7a..8fc8fe58f 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -92,11 +92,6 @@ SimObject::SimObject(const string &_name)
}
void
-SimObject::connect()
-{
-}
-
-void
SimObject::init()
{
}
@@ -160,21 +155,6 @@ SimObject::regAllStats()
}
//
-// static function: call connect() on all SimObjects.
-//
-void
-SimObject::connectAll()
-{
- SimObjectList::iterator i = simObjectList.begin();
- SimObjectList::iterator end = simObjectList.end();
-
- for (; i != end; ++i) {
- SimObject *obj = *i;
- obj->connect();
- }
-}
-
-//
// static function: call init() on all SimObjects.
//
void
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 32807b69d..93802e247 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -101,9 +101,7 @@ class SimObject : public Serializable, protected StartupCallback
// initialization pass of all objects.
// Gets invoked after construction, before unserialize.
virtual void init();
- virtual void connect();
static void initAll();
- static void connectAll();
// register statistics for this object
virtual void regStats();