diff options
Diffstat (limited to 'src')
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 §ion) @@ -132,4 +144,5 @@ void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) 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 36e87ec9c..60c954517 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 c86f3552e..985e09b52 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 edba55b0d..11e4d2acb 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -188,8 +188,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); + } } } } @@ -217,7 +220,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; } } @@ -234,7 +239,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 cbb3980cb..253d33243 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 c644ae8d7..e6ebcc525 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -62,6 +62,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; @@ -81,6 +83,8 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) // 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 fbe81c443..438ec56dc 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) - : Port(pname), outTiming(0), drainEvent(NULL) + : Port(pname), 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(); |