X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcpu%2Fsimple%2Fbase.cc;h=bdc4b0f44e869eab55485a0aadaa0a517b92975f;hb=b265d9925c123f0df50db98cf56dab6a3596b54b;hp=9fc1d1dd9320288761b7b28a0c0573b76267f17c;hpb=418ddf43e645133b3693ab8bf2e56656efcf1ebf;p=gem5.git diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 9fc1d1dd9..bdc4b0f44 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010-2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -28,62 +40,78 @@ * Authors: Steve Reinhardt */ +#include "arch/kernel_stats.hh" +#include "arch/stacktrace.hh" +#include "arch/tlb.hh" #include "arch/utility.hh" -#include "arch/faults.hh" +#include "arch/vtophys.hh" +#include "base/loader/symtab.hh" +#include "base/cp_annotate.hh" #include "base/cprintf.hh" #include "base/inifile.hh" -#include "base/loader/symtab.hh" #include "base/misc.hh" #include "base/pollevent.hh" #include "base/range.hh" -#include "base/stats/events.hh" #include "base/trace.hh" +#include "base/types.hh" +#include "config/the_isa.hh" +#include "cpu/simple/base.hh" #include "cpu/base.hh" +#include "cpu/checker/cpu.hh" +#include "cpu/checker/thread_context.hh" #include "cpu/exetrace.hh" #include "cpu/profile.hh" -#include "cpu/simple/base.hh" #include "cpu/simple_thread.hh" #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" +#include "debug/Decode.hh" +#include "debug/Fetch.hh" +#include "debug/Quiesce.hh" +#include "mem/mem_object.hh" #include "mem/packet.hh" +#include "mem/request.hh" +#include "params/BaseSimpleCPU.hh" #include "sim/byteswap.hh" #include "sim/debug.hh" -#include "sim/host.hh" +#include "sim/faults.hh" +#include "sim/full_system.hh" #include "sim/sim_events.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" #include "sim/system.hh" -#if FULL_SYSTEM -#include "arch/kernel_stats.hh" -#include "arch/stacktrace.hh" -#include "arch/tlb.hh" -#include "arch/vtophys.hh" -#include "base/remote_gdb.hh" -#else // !FULL_SYSTEM -#include "mem/mem_object.hh" -#endif // FULL_SYSTEM - using namespace std; using namespace TheISA; -BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), traceData(NULL), thread(NULL), predecoder(NULL) +BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p) + : BaseCPU(p), traceData(NULL), thread(NULL) { -#if FULL_SYSTEM - thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); -#else - thread = new SimpleThread(this, /* thread_num */ 0, p->process, - p->itb, p->dtb, /* asid */ 0); -#endif // !FULL_SYSTEM + if (FullSystem) + thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); + else + thread = new SimpleThread(this, /* thread_num */ 0, p->system, + p->workload[0], p->itb, p->dtb); - thread->setStatus(ThreadContext::Unallocated); + thread->setStatus(ThreadContext::Halted); tc = thread->getTC(); + if (p->checker) { + BaseCPU *temp_checker = p->checker; + checker = dynamic_cast(temp_checker); + checker->setSystem(p->system); + // Manipulate thread context + ThreadContext *cpu_tc = tc; + tc = new CheckerThreadContext(cpu_tc, this->checker); + } else { + checker = NULL; + } + numInst = 0; startNumInst = 0; + numOp = 0; + startNumOp = 0; numLoad = 0; startNumLoad = 0; lastIcacheStall = 0; @@ -91,6 +119,7 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p) threadContexts.push_back(tc); + fetchOffset = 0; stayAtPC = false; } @@ -100,7 +129,7 @@ BaseSimpleCPU::~BaseSimpleCPU() } void -BaseSimpleCPU::deallocateContext(int thread_num) +BaseSimpleCPU::deallocateContext(ThreadID thread_num) { // for now, these are equivalent suspendContext(thread_num); @@ -108,7 +137,7 @@ BaseSimpleCPU::deallocateContext(int thread_num) void -BaseSimpleCPU::haltContext(int thread_num) +BaseSimpleCPU::haltContext(ThreadID thread_num) { // for now, these are equivalent suspendContext(thread_num); @@ -123,13 +152,78 @@ BaseSimpleCPU::regStats() BaseCPU::regStats(); numInsts - .name(name() + ".num_insts") - .desc("Number of instructions executed") + .name(name() + ".committedInsts") + .desc("Number of instructions committed") + ; + + numOps + .name(name() + ".committedOps") + .desc("Number of ops (including micro ops) committed") + ; + + numIntAluAccesses + .name(name() + ".num_int_alu_accesses") + .desc("Number of integer alu accesses") + ; + + numFpAluAccesses + .name(name() + ".num_fp_alu_accesses") + .desc("Number of float alu accesses") + ; + + numCallsReturns + .name(name() + ".num_func_calls") + .desc("number of times a function call or return occured") + ; + + numCondCtrlInsts + .name(name() + ".num_conditional_control_insts") + .desc("number of instructions that are conditional controls") + ; + + numIntInsts + .name(name() + ".num_int_insts") + .desc("number of integer instructions") + ; + + numFpInsts + .name(name() + ".num_fp_insts") + .desc("number of float instructions") + ; + + numIntRegReads + .name(name() + ".num_int_register_reads") + .desc("number of times the integer registers were read") + ; + + numIntRegWrites + .name(name() + ".num_int_register_writes") + .desc("number of times the integer registers were written") + ; + + numFpRegReads + .name(name() + ".num_fp_register_reads") + .desc("number of times the floating registers were read") + ; + + numFpRegWrites + .name(name() + ".num_fp_register_writes") + .desc("number of times the floating registers were written") ; numMemRefs - .name(name() + ".num_refs") - .desc("Number of memory references") + .name(name()+".num_mem_refs") + .desc("number of memory refs") + ; + + numStoreInsts + .name(name() + ".num_store_insts") + .desc("Number of store instructions") + ; + + numLoadInsts + .name(name() + ".num_load_insts") + .desc("Number of load instructions") ; notIdleFraction @@ -142,6 +236,16 @@ BaseSimpleCPU::regStats() .desc("Percentage of idle cycles") ; + numBusyCycles + .name(name() + ".num_busy_cycles") + .desc("Number of busy cycles") + ; + + numIdleCycles + .name(name()+".num_idle_cycles") + .desc("Number of idle cycles") + ; + icacheStallCycles .name(name() + ".icache_stall_cycles") .desc("ICache total stall cycles") @@ -167,18 +271,21 @@ BaseSimpleCPU::regStats() ; idleFraction = constant(1.0) - notIdleFraction; + numIdleCycles = idleFraction * numCycles; + numBusyCycles = (notIdleFraction)*numCycles; } void BaseSimpleCPU::resetStats() { // startNumInst = numInst; - // notIdleFraction = (_status != Idle); + notIdleFraction = (_status != Idle); } void BaseSimpleCPU::serialize(ostream &os) { + SERIALIZE_ENUM(_status); BaseCPU::serialize(os); // SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc.0", name())); @@ -188,163 +295,60 @@ BaseSimpleCPU::serialize(ostream &os) void BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { + UNSERIALIZE_ENUM(_status); BaseCPU::unserialize(cp, section); // UNSERIALIZE_SCALAR(inst); thread->unserialize(cp, csprintf("%s.xc.0", section)); } void -change_thread_state(int thread_number, int activate, int priority) +change_thread_state(ThreadID tid, int activate, int priority) { } -Fault -BaseSimpleCPU::copySrcTranslate(Addr src) -{ -#if 0 - static bool no_warn = true; - int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; - // Only support block sizes of 64 atm. - assert(blk_size == 64); - int offset = src & (blk_size - 1); - - // Make sure block doesn't span page - if (no_warn && - (src & PageMask) != ((src + blk_size) & PageMask) && - (src >> 40) != 0xfffffc) { - warn("Copied block source spans pages %x.", src); - no_warn = false; - } - - memReq->reset(src & ~(blk_size - 1), blk_size); - - // translate to physical address - Fault fault = thread->translateDataReadReq(req); - - if (fault == NoFault) { - thread->copySrcAddr = src; - thread->copySrcPhysAddr = memReq->paddr + offset; - } else { - assert(!fault->isAlignmentFault()); - - thread->copySrcAddr = 0; - thread->copySrcPhysAddr = 0; - } - return fault; -#else - return NoFault; -#endif -} - -Fault -BaseSimpleCPU::copy(Addr dest) -{ -#if 0 - static bool no_warn = true; - int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; - // Only support block sizes of 64 atm. - assert(blk_size == 64); - uint8_t data[blk_size]; - //assert(thread->copySrcAddr); - int offset = dest & (blk_size - 1); - - // Make sure block doesn't span page - if (no_warn && - (dest & PageMask) != ((dest + blk_size) & PageMask) && - (dest >> 40) != 0xfffffc) { - no_warn = false; - warn("Copied block destination spans pages %x. ", dest); - } - - memReq->reset(dest & ~(blk_size -1), blk_size); - // translate to physical address - Fault fault = thread->translateDataWriteReq(req); - - if (fault == NoFault) { - Addr dest_addr = memReq->paddr + offset; - // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = thread->copySrcPhysAddr; - thread->mem->read(memReq, data); - memReq->paddr = dest_addr; - thread->mem->write(memReq, data); - if (dcacheInterface) { - memReq->cmd = Copy; - memReq->completionEvent = NULL; - memReq->paddr = thread->copySrcPhysAddr; - memReq->dest = dest_addr; - memReq->size = 64; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - dcacheInterface->access(memReq); - } - } - else - assert(!fault->isAlignmentFault()); - - return fault; -#else - panic("copy not implemented"); - return NoFault; -#endif -} - -#if FULL_SYSTEM Addr BaseSimpleCPU::dbg_vtophys(Addr addr) { return vtophys(tc, addr); } -#endif // FULL_SYSTEM -#if FULL_SYSTEM void -BaseSimpleCPU::post_interrupt(int int_num, int index) +BaseSimpleCPU::wakeup() { - BaseCPU::post_interrupt(int_num, index); + if (thread->status() != ThreadContext::Suspended) + return; - if (thread->status() == ThreadContext::Suspended) { - DPRINTF(Quiesce,"Suspended Processor awoke\n"); - thread->activate(); - } + DPRINTF(Quiesce,"Suspended Processor awoke\n"); + thread->activate(); } -#endif // FULL_SYSTEM void BaseSimpleCPU::checkForInterrupts() { -#if FULL_SYSTEM - if (check_interrupts(tc)) { - Fault interrupt = interrupts.getInterrupt(tc); + if (checkInterrupts(tc)) { + Fault interrupt = interrupts->getInterrupt(tc); if (interrupt != NoFault) { - interrupts.updateIntrInfo(tc); + fetchOffset = 0; + interrupts->updateIntrInfo(tc); interrupt->invoke(tc); + thread->decoder.reset(); } } -#endif } -Fault +void BaseSimpleCPU::setupFetchRequest(Request *req) { - Addr threadPC = thread->readPC(); + Addr instAddr = thread->instAddr(); // set up memory request for instruction fetch -#if ISA_HAS_DELAY_SLOT - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, - thread->readNextPC(),thread->readNextNPC()); -#else - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, - thread->readNextPC()); -#endif - - Addr fetchPC = (threadPC & PCMask) + fetchOffset; - req->setVirt(0, fetchPC, sizeof(MachInst), 0, threadPC); - - Fault fault = thread->translateInstReq(req); + DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr); - return fault; + Addr fetchPC = (instAddr & PCMask) + fetchOffset; + req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instMasterId(), + instAddr); } @@ -359,34 +363,39 @@ BaseSimpleCPU::preExecute() // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); + system->instEventQueue.serviceEvents(system->totalNumInsts); // decode the instruction inst = gtoh(inst); - //If we're not in the middle of a macro instruction - if (!curMacroStaticInst) { + TheISA::PCState pcState = thread->pcState(); + if (isRomMicroPC(pcState.microPC())) { + stayAtPC = false; + curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(), + curMacroStaticInst); + } else if (!curMacroStaticInst) { + //We're not in the middle of a macro instruction StaticInstPtr instPtr = NULL; + TheISA::Decoder *decoder = &(thread->decoder); + //Predecode, ie bundle up an ExtMachInst //This should go away once the constructor can be set up properly - predecoder.setTC(thread->getTC()); + decoder->setTC(thread->getTC()); //If more fetch data is needed, pass it in. - Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; - //if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), fetchPC, inst); + Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset; + //if(decoder->needMoreBytes()) + decoder->moreBytes(pcState, fetchPC, inst); //else - // predecoder.process(); + // decoder->process(); - //If an instruction is ready, decode it. Otherwise, we'll have to + //Decode an instruction if one is ready. 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 + instPtr = decoder->decode(pcState); + if (instPtr) { stayAtPC = false; - instPtr = StaticInst::decode(predecoder.getExtMachInst(), - thread->readPC()); + thread->pcState(pcState); } else { stayAtPC = true; fetchOffset += sizeof(MachInst); @@ -396,46 +405,41 @@ BaseSimpleCPU::preExecute() //out micro ops if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; - curStaticInst = curMacroStaticInst-> - fetchMicroop(thread->readMicroPC()); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op - curStaticInst = curMacroStaticInst-> - fetchMicroop(thread->readMicroPC()); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } //If we decoded an instruction this "tick", record information about it. - if(curStaticInst) - { + if (curStaticInst) { #if TRACING_ON - traceData = tracer->getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); + traceData = tracer->getInstRecord(curTick(), tc, + curStaticInst, thread->pcState(), curMacroStaticInst); - DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", + DPRINTF(Decode,"Decode: Decoded %s instruction: %#x\n", curStaticInst->getName(), curStaticInst->machInst); #endif // TRACING_ON - -#if FULL_SYSTEM - thread->setInst(inst); -#endif // FULL_SYSTEM } } void BaseSimpleCPU::postExecute() { -#if FULL_SYSTEM - if (thread->profile && curStaticInst) { + assert(curStaticInst); + + TheISA::PCState pc = tc->pcState(); + Addr instAddr = pc.instAddr(); + if (FullSystem && thread->profile) { bool usermode = TheISA::inUserMode(tc); - thread->profilePC = usermode ? 1 : thread->readPC(); + thread->profilePC = usermode ? 1 : instAddr; ProfileNode *node = thread->profile->consume(tc, curStaticInst); if (node) thread->profileNode = node; } -#endif if (curStaticInst->isMemRef()) { numMemRefs++; @@ -446,7 +450,45 @@ BaseSimpleCPU::postExecute() comLoadEventQueue[0]->serviceEvents(numLoad); } - traceFunctions(thread->readPC()); + if (CPA::available()) { + CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr()); + } + + /* Power model statistics */ + //integer alu accesses + if (curStaticInst->isInteger()){ + numIntAluAccesses++; + numIntInsts++; + } + + //float alu accesses + if (curStaticInst->isFloating()){ + numFpAluAccesses++; + numFpInsts++; + } + + //number of function calls/returns to get window accesses + if (curStaticInst->isCall() || curStaticInst->isReturn()){ + numCallsReturns++; + } + + //the number of branch predictions that will be made + if (curStaticInst->isCondCtrl()){ + numCondCtrlInsts++; + } + + //result bus acceses + if (curStaticInst->isLoad()){ + numLoadInsts++; + } + + if (curStaticInst->isStore()){ + numStoreInsts++; + } + /* End power model statistics */ + + if (FullSystem) + traceFunctions(instAddr); if (traceData) { traceData->dump(); @@ -463,42 +505,50 @@ BaseSimpleCPU::advancePC(Fault fault) fetchOffset = 0; if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; - fault->invoke(tc); - thread->setMicroPC(0); - thread->setNextMicroPC(1); + fault->invoke(tc, curStaticInst); + thread->decoder.reset(); } else { - //If we're at the last micro op for this instruction - if (curStaticInst && curStaticInst->isLastMicroop()) { - //We should be working with a macro op - assert(curMacroStaticInst); - //Close out this macro op, and clean up the - //microcode state - curMacroStaticInst = StaticInst::nullStaticInstPtr; - thread->setMicroPC(0); - thread->setNextMicroPC(1); - } - //If we're still in a macro op - if (curMacroStaticInst) { - //Advance the micro pc - thread->setMicroPC(thread->readNextMicroPC()); - //Advance the "next" micro pc. Note that there are no delay - //slots, and micro ops are "word" addressed. - thread->setNextMicroPC(thread->readNextMicroPC() + 1); - } else { - // go to the next instruction - thread->setPC(thread->readNextPC()); - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); - assert(thread->readNextPC() != thread->readNextNPC()); + if (curStaticInst) { + if (curStaticInst->isLastMicroop()) + curMacroStaticInst = StaticInst::nullStaticInstPtr; + TheISA::PCState pcState = thread->pcState(); + TheISA::advancePC(pcState, curStaticInst); + thread->pcState(pcState); } } - -#if FULL_SYSTEM - Addr oldpc; - do { - oldpc = thread->readPC(); - system->pcEventQueue.service(tc); - } while (oldpc != thread->readPC()); -#endif } +/*Fault +BaseSimpleCPU::CacheOp(uint8_t Op, Addr EffAddr) +{ + // translate to physical address + Fault fault = NoFault; + int CacheID = Op & 0x3; // Lower 3 bits identify Cache + int CacheOP = Op >> 2; // Upper 3 bits identify Cache Operation + if(CacheID > 1) + { + warn("CacheOps not implemented for secondary/tertiary caches\n"); + } + else + { + switch(CacheOP) + { // Fill Packet Type + case 0: warn("Invalidate Cache Op\n"); + break; + case 1: warn("Index Load Tag Cache Op\n"); + break; + case 2: warn("Index Store Tag Cache Op\n"); + break; + case 4: warn("Hit Invalidate Cache Op\n"); + break; + case 5: warn("Fill/Hit Writeback Invalidate Cache Op\n"); + break; + case 6: warn("Hit Writeback\n"); + break; + case 7: warn("Fetch & Lock Cache Op\n"); + break; + default: warn("Unimplemented Cache Op\n"); + } + } + return fault; +}*/