diff options
Diffstat (limited to 'src/cpu/simple')
-rw-r--r-- | src/cpu/simple/AtomicSimpleCPU.py | 43 | ||||
-rw-r--r-- | src/cpu/simple/SConscript | 2 | ||||
-rw-r--r-- | src/cpu/simple/TimingSimpleCPU.py | 41 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 6 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 4 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 54 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 9 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 14 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 11 |
9 files changed, 149 insertions, 35 deletions
diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py new file mode 100644 index 000000000..e97f059c1 --- /dev/null +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -0,0 +1,43 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.params import * +from m5 import build_env +from BaseCPU import BaseCPU + +class AtomicSimpleCPU(BaseCPU): + type = 'AtomicSimpleCPU' + width = Param.Int(1, "CPU width") + simulate_stalls = Param.Bool(False, "Simulate cache stall cycles") + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") + if build_env['FULL_SYSTEM']: + profile = Param.Latency('0ns', "trace the kernel stack") + icache_port = Port("Instruction Port") + dcache_port = Port("Data Port") + _mem_ports = ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript index 9a6a80473..ccccab2b5 100644 --- a/src/cpu/simple/SConscript +++ b/src/cpu/simple/SConscript @@ -33,10 +33,12 @@ Import('*') need_simple_base = False if 'AtomicSimpleCPU' in env['CPU_MODELS']: need_simple_base = True + SimObject('AtomicSimpleCPU.py') Source('atomic.cc') if 'TimingSimpleCPU' in env['CPU_MODELS']: need_simple_base = True + SimObject('TimingSimpleCPU.py') Source('timing.cc') if need_simple_base: diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py new file mode 100644 index 000000000..2fcde175c --- /dev/null +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -0,0 +1,41 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from m5.params import * +from m5 import build_env +from BaseCPU import BaseCPU + +class TimingSimpleCPU(BaseCPU): + type = 'TimingSimpleCPU' + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") + if build_env['FULL_SYSTEM']: + profile = Param.Latency('0ns', "trace the kernel stack") + icache_port = Port("Instruction Port") + dcache_port = Port("Data Port") + _mem_ports = ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index b0a01c3a3..ea1c7d87f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -540,8 +540,8 @@ AtomicSimpleCPU::tick() } // @todo remove me after debugging with legion done - if (curStaticInst && (!curStaticInst->isMicroOp() || - curStaticInst->isFirstMicroOp())) + if (curStaticInst && (!curStaticInst->isMicroop() || + curStaticInst->isFirstMicroop())) instCnt++; if (simulate_stalls) { @@ -557,7 +557,7 @@ AtomicSimpleCPU::tick() } } - if(predecoder.needMoreBytes() || fault != NoFault) + if(fault != NoFault || !stayAtPC) advancePC(fault); } diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index ad4aa4708..b127e3791 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -104,8 +104,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void recvRetry(); virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } + bool &snoop) + { resp.clear(); snoop = true; } }; CpuPort icachePort; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 4fed2059b..b7f60522f 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -70,7 +70,7 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), thread(NULL), predecoder(NULL) + : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); @@ -91,6 +91,9 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p) lastDcacheStall = 0; threadContexts.push_back(tc); + + fetchOffset = 0; + stayAtPC = false; } BaseSimpleCPU::~BaseSimpleCPU() @@ -326,18 +329,19 @@ BaseSimpleCPU::checkForInterrupts() Fault BaseSimpleCPU::setupFetchRequest(Request *req) { + Addr threadPC = thread->readPC(); + // set up memory request for instruction fetch #if ISA_HAS_DELAY_SLOT - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(), + DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, thread->readNextPC(),thread->readNextNPC()); #else - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p",thread->readPC(), + DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, thread->readNextPC()); #endif - req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst), - (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0, - thread->readPC()); + Addr fetchPC = (threadPC & PCMask) + fetchOffset; + req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); Fault fault = thread->translateInstReq(req); @@ -365,8 +369,10 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); + //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { + StaticInstPtr instPtr = NULL; //Predecode, ie bundle up an ExtMachInst @@ -374,36 +380,50 @@ BaseSimpleCPU::preExecute() predecoder.setTC(thread->getTC()); //If more fetch data is needed, pass it in. if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), 0, inst); + predecoder.moreBytes(thread->readPC(), + (thread->readPC() & PCMask) + fetchOffset, 0, inst); else predecoder.process(); - //If an instruction is ready, decode it - if (predecoder.extMachInstReady()) - instPtr = StaticInst::decode(predecoder.getExtMachInst()); + + //If an instruction is ready, decode it. Otherwise, we'll have to + //fetch beyond the MachInst at the current pc. + if (predecoder.extMachInstReady()) { +#if THE_ISA == X86_ISA + thread->setNextPC(thread->readPC() + predecoder.getInstSize()); +#endif // X86_ISA + stayAtPC = false; + instPtr = StaticInst::decode(predecoder.getExtMachInst(), + thread->readPC()); + } else { + stayAtPC = true; + fetchOffset += sizeof(MachInst); + } //If we decoded an instruction and it's microcoded, start pulling //out micro ops - if (instPtr && instPtr->isMacroOp()) { + if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> - fetchMicroOp(thread->readMicroPC()); + fetchMicroop(thread->readMicroPC()); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op curStaticInst = curMacroStaticInst-> - fetchMicroOp(thread->readMicroPC()); + fetchMicroop(thread->readMicroPC()); } //If we decoded an instruction this "tick", record information about it. if(curStaticInst) { +#if TRACING_ON traceData = Trace::getInstRecord(curTick, tc, curStaticInst, thread->readPC()); DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", curStaticInst->getName(), curStaticInst->machInst); +#endif // TRACING_ON #if FULL_SYSTEM thread->setInst(inst); @@ -418,7 +438,7 @@ BaseSimpleCPU::postExecute() if (thread->profile) { bool usermode = TheISA::inUserMode(tc); thread->profilePC = usermode ? 1 : thread->readPC(); - StaticInstPtr si(inst); + StaticInstPtr si(inst, thread->readPC()); ProfileNode *node = thread->profile->consume(tc, si); if (node) thread->profileNode = node; @@ -447,14 +467,16 @@ BaseSimpleCPU::postExecute() void BaseSimpleCPU::advancePC(Fault fault) { + //Since we're moving to a new pc, zero out the offset + fetchOffset = 0; if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else if (predecoder.needMoreBytes()) { + } else { //If we're at the last micro op for this instruction - if (curStaticInst && curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroop()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 787259c96..d221baca8 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -137,6 +137,12 @@ class BaseSimpleCPU : public BaseCPU StaticInstPtr curStaticInst; StaticInstPtr curMacroStaticInst; + //This is the offset from the current pc that fetch should be performed at + Addr fetchOffset; + //This flag says to stay at the current pc. This is useful for + //instructions which go beyond MachInst boundaries. + bool stayAtPC; + void checkForInterrupts(); Fault setupFetchRequest(Request *req); void preExecute(); @@ -160,6 +166,9 @@ class BaseSimpleCPU : public BaseCPU return numInst - startNumInst; } + // Mask to align PCs to MachInst sized boundaries + static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1); + // number of simulated memory references Stats::Scalar<> numMemRefs; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index fa7bb4f86..7698a588d 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -168,9 +168,7 @@ TimingSimpleCPU::resume() delete fetchEvent; } - fetchEvent = - new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); - fetchEvent->schedule(nextCycle()); + fetchEvent = new FetchEvent(this, nextCycle()); } changeState(SimObject::Running); @@ -224,9 +222,7 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) _status = Running; // kick things off by initiating the fetch of the next instruction - fetchEvent = - new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); - fetchEvent->schedule(nextCycle(curTick + cycles(delay))); + fetchEvent = new FetchEvent(this, nextCycle(curTick + cycles(delay))); } @@ -564,8 +560,7 @@ TimingSimpleCPU::IcachePort::recvTiming(PacketPtr pkt) { if (pkt->isResponse()) { // delay processing of returned data until next CPU clock edge - Tick mem_time = pkt->req->getTime(); - Tick next_tick = cpu->nextCycle(mem_time); + Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeIfetch(pkt); @@ -659,8 +654,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { if (pkt->isResponse()) { // delay processing of returned data until next CPU clock edge - Tick mem_time = pkt->req->getTime(); - Tick next_tick = cpu->nextCycle(mem_time); + Tick next_tick = cpu->nextCycle(curTick); if (next_tick == curTick) cpu->completeDataAccess(pkt); diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index ef062d24a..39958bfb6 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -66,8 +66,6 @@ class TimingSimpleCPU : public BaseSimpleCPU Event *drainEvent; - Event *fetchEvent; - private: class CpuPort : public Port @@ -93,8 +91,8 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void recvStatusChange(Status status); virtual void getDeviceAddressRanges(AddrRangeList &resp, - AddrRangeList &snoop) - { resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,0)); } + bool &snoop) + { resp.clear(); snoop = false; } struct TickEvent : public Event { @@ -199,7 +197,12 @@ class TimingSimpleCPU : public BaseSimpleCPU void completeIfetch(PacketPtr ); void completeDataAccess(PacketPtr ); void advanceInst(Fault fault); + private: + + typedef EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch> FetchEvent; + FetchEvent *fetchEvent; + void completeDrain(); }; |