X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Finorder%2Fcpu.cc;h=5a02f94d9bcc969b8ca0fcf80ab666860596aea8;hb=7d0344704a9ecc566d82ad43ec44b4becbaf4d77;hp=04176c54f9489f16c9c015bf70ee38eb9e3a3f29;hpb=dccca0d3a9c985972d3d603190e62899d03825e8;p=gem5.git diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 04176c54f..5a02f94d9 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 ARM Limited + * Copyright (c) 2013 Advanced Micro Devices, Inc. * All rights reserved * * The license below extends only to copyright in the software and shall @@ -59,6 +60,7 @@ #include "cpu/base.hh" #include "cpu/exetrace.hh" #include "cpu/quiesce_event.hh" +#include "cpu/reg_class.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "debug/Activity.hh" @@ -82,16 +84,15 @@ using namespace std; using namespace TheISA; using namespace ThePipeline; -InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit) : - CpuPort(_cacheUnit->name() + "-cache-port", _cacheUnit->cpu), +InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit, + const std::string& name) : + MasterPort(_cacheUnit->name() + name, _cacheUnit->cpu), cacheUnit(_cacheUnit) { } bool -InOrderCPU::CachePort::recvTiming(Packet *pkt) +InOrderCPU::CachePort::recvTimingResp(Packet *pkt) { - assert(pkt->isResponse()); - if (pkt->isError()) DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", pkt->getAddr()); @@ -210,10 +211,10 @@ InOrderCPU::CPUEvent::description() const } void -InOrderCPU::CPUEvent::scheduleEvent(int delay) +InOrderCPU::CPUEvent::scheduleEvent(Cycles delay) { assert(!scheduled() || squashed()); - cpu->reschedule(this, cpu->nextCycle(curTick() + cpu->ticks(delay)), true); + cpu->reschedule(this, cpu->clockEdge(delay), true); } void @@ -231,9 +232,10 @@ InOrderCPU::InOrderCPU(Params *params) tickEvent(this), stageWidth(params->stageWidth), resPool(new ResourcePool(this, params)), + isa(numThreads, NULL), timeBuffer(2 , 2), - dataPort(resPool->getDataUnit()), - instPort(resPool->getInstUnit()), + dataPort(resPool->getDataUnit(), ".dcache_port"), + instPort(resPool->getInstUnit(), ".icache_port"), removeInstsThisCycle(false), activityRec(params->name, NumStages, 10, params->activity), system(params->system), @@ -242,7 +244,6 @@ InOrderCPU::InOrderCPU(Params *params) resReqCount(0), #endif // DEBUG drainCount(0), - deferRegistration(false/*params->deferRegistration*/), stageTracing(params->stageTracing), lastRunningCycle(0), instsPerSwitch(0) @@ -281,6 +282,7 @@ InOrderCPU::InOrderCPU(Params *params) } for (ThreadID tid = 0; tid < numThreads; ++tid) { + isa[tid] = params->isa[tid]; pc[tid].set(0); lastCommittedPC[tid].set(0); @@ -291,7 +293,7 @@ InOrderCPU::InOrderCPU(Params *params) } else { if (tid < (ThreadID)params->workload.size()) { DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", - tid, params->workload[tid]->prog_fname); + tid, params->workload[tid]->progName()); thread[tid] = new Thread(this, tid, params->workload[tid]); } else { @@ -359,7 +361,10 @@ InOrderCPU::InOrderCPU(Params *params) memset(intRegs[tid], 0, sizeof(intRegs[tid])); memset(floatRegs.i[tid], 0, sizeof(floatRegs.i[tid])); - isa[tid].clear(); +#ifdef ISA_HAS_CC_REGS + memset(ccRegs[tid], 0, sizeof(ccRegs[tid])); +#endif + isa[tid]->clear(); // Define dummy instructions and resource requests to be used. dummyInst[tid] = new InOrderDynInst(this, @@ -385,7 +390,7 @@ InOrderCPU::InOrderCPU(Params *params) } // InOrderCPU always requires an interrupt controller. - if (!params->defer_registration && !interrupts) { + if (!params->switched_out && !interrupts) { fatal("InOrderCPU %s has no interrupt controller.\n" "Ensure createInterruptController() is called.\n", name()); } @@ -402,13 +407,13 @@ InOrderCPU::InOrderCPU(Params *params) frontEndSked = createFrontEndSked(); faultSked = createFaultSked(); - lastRunningCycle = curTick(); + lastRunningCycle = curCycle(); lockAddr = 0; lockFlag = false; // Schedule First Tick Event, CPU will reschedule itself from here on out. - scheduleTickEvent(0); + scheduleTickEvent(Cycles(0)); } InOrderCPU::~InOrderCPU() @@ -762,17 +767,17 @@ InOrderCPU::tick() if (!tickEvent.scheduled()) { if (_status == SwitchedOut) { // increment stat - lastRunningCycle = curTick(); + lastRunningCycle = curCycle(); } else if (!activityRec.active()) { DPRINTF(InOrderCPU, "sleeping CPU.\n"); - lastRunningCycle = curTick(); + lastRunningCycle = curCycle(); timesIdled++; } else { //Tick next_tick = curTick() + cycles(1); //tickEvent.schedule(next_tick); - schedule(&tickEvent, nextCycle(curTick() + 1)); + schedule(&tickEvent, clockEdge(Cycles(1))); DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", - nextCycle(curTick() + 1)); + clockEdge(Cycles(1))); } } @@ -787,28 +792,37 @@ InOrderCPU::init() BaseCPU::init(); for (ThreadID tid = 0; tid < numThreads; ++tid) { - // Set inSyscall so that the CPU doesn't squash when initially + // Set noSquashFromTC so that the CPU doesn't squash when initially // setting up registers. - thread[tid]->inSyscall = true; + thread[tid]->noSquashFromTC = true; // Initialise the ThreadContext's memory proxies thread[tid]->initMemProxies(thread[tid]->getTC()); } - if (FullSystem) { + if (FullSystem && !params()->switched_out) { for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; TheISA::initCPU(src_tc, src_tc->contextId()); } } - // Clear inSyscall. + // Clear noSquashFromTC. for (ThreadID tid = 0; tid < numThreads; ++tid) - thread[tid]->inSyscall = false; + thread[tid]->noSquashFromTC = false; // Call Initializiation Routine for Resource Pool resPool->init(); } +void +InOrderCPU::verifyMemoryMode() const +{ + if (!system->isTimingMode()) { + fatal("The in-order CPU requires the memory system to be in " + "'timing' mode.\n"); + } +} + Fault InOrderCPU::hwrei(ThreadID tid) { @@ -878,7 +892,7 @@ InOrderCPU::checkForInterrupts() // Schedule Squash Through-out Resource Pool resPool->scheduleEvent( (InOrderCPU::CPUEventType)ResourcePool::SquashAll, - dummyTrapInst[tid], 0); + dummyTrapInst[tid], Cycles(0)); // Finally, Setup Trap to happen at end of cycle trapContext(interrupt, tid, dummyTrapInst[tid]); @@ -913,7 +927,8 @@ InOrderCPU::processInterrupts(Fault interrupt) } void -InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay) +InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, + Cycles delay) { scheduleCpuEvent(Trap, fault, tid, inst, delay); trapPending[tid] = true; @@ -927,7 +942,8 @@ InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst) } void -InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay) +InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, + Cycles delay) { scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay); } @@ -955,25 +971,21 @@ InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num, void InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault, ThreadID tid, DynInstPtr inst, - unsigned delay, CPUEventPri event_pri) + Cycles delay, CPUEventPri event_pri) { CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, inst, event_pri); - Tick sked_tick = nextCycle(curTick() + ticks(delay)); - if (delay >= 0) { - DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n", - eventNames[c_event], curTick() + delay, tid); - schedule(cpu_event, sked_tick); - } else { - cpu_event->process(); - cpuEventRemoveList.push(cpu_event); - } + Tick sked_tick = clockEdge(delay); + DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n", + eventNames[c_event], curTick() + delay, tid); + schedule(cpu_event, sked_tick); // Broadcast event to the Resource Pool // Need to reset tid just in case this is a dummy instruction inst->setTid(tid); - resPool->scheduleEvent(c_event, inst, 0, 0, tid); + // @todo: Is this really right? Should the delay not be passed on? + resPool->scheduleEvent(c_event, inst, Cycles(0), 0, tid); } bool @@ -1077,7 +1089,7 @@ InOrderCPU::activateThreadInPipeline(ThreadID tid) } void -InOrderCPU::deactivateContext(ThreadID tid, int delay) +InOrderCPU::deactivateContext(ThreadID tid, Cycles delay) { DPRINTF(InOrderCPU,"[tid:%i]: Deactivating ...\n", tid); @@ -1159,7 +1171,7 @@ InOrderCPU::tickThreadStats() } void -InOrderCPU::activateContext(ThreadID tid, int delay) +InOrderCPU::activateContext(ThreadID tid, Cycles delay) { DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid); @@ -1174,7 +1186,7 @@ InOrderCPU::activateContext(ThreadID tid, int delay) } void -InOrderCPU::activateNextReadyContext(int delay) +InOrderCPU::activateNextReadyContext(Cycles delay) { DPRINTF(InOrderCPU,"Activating next ready thread\n"); @@ -1248,18 +1260,24 @@ InOrderCPU::getPipeStage(int stage_num) RegIndex -InOrderCPU::flattenRegIdx(RegIndex reg_idx, RegType ®_type, ThreadID tid) -{ - if (reg_idx < FP_Base_DepTag) { - reg_type = IntType; - return isa[tid].flattenIntIndex(reg_idx); - } else if (reg_idx < Ctrl_Base_DepTag) { - reg_type = FloatType; - reg_idx -= FP_Base_DepTag; - return isa[tid].flattenFloatIndex(reg_idx); - } else { - reg_type = MiscType; - return reg_idx - TheISA::Ctrl_Base_DepTag; +InOrderCPU::flattenRegIdx(RegIndex reg_idx, RegClass ®_type, ThreadID tid) +{ + RegIndex rel_idx; + + reg_type = regIdxToClass(reg_idx, &rel_idx); + + switch (reg_type) { + case IntRegClass: + return isa[tid]->flattenIntIndex(rel_idx); + + case FloatRegClass: + return isa[tid]->flattenFloatIndex(rel_idx); + + case MiscRegClass: + return rel_idx; + + default: + panic("register %d out of range\n", reg_idx); } } @@ -1290,6 +1308,19 @@ InOrderCPU::readFloatRegBits(RegIndex reg_idx, ThreadID tid) return floatRegs.i[tid][reg_idx]; } +CCReg +InOrderCPU::readCCReg(RegIndex reg_idx, ThreadID tid) +{ +#ifdef ISA_HAS_CC_REGS + DPRINTF(CCRegs, "[tid:%i]: Reading CC. Reg %i as %x\n", + tid, reg_idx, ccRegs[tid][reg_idx]); + + return ccRegs[tid][reg_idx]; +#else + panic("readCCReg: ISA does not have CC regs\n"); +#endif +} + void InOrderCPU::setIntReg(RegIndex reg_idx, uint64_t val, ThreadID tid) { @@ -1329,6 +1360,18 @@ InOrderCPU::setFloatRegBits(RegIndex reg_idx, FloatRegBits val, ThreadID tid) floatRegs.f[tid][reg_idx]); } +void +InOrderCPU::setCCReg(RegIndex reg_idx, CCReg val, ThreadID tid) +{ +#ifdef ISA_HAS_CC_REGS + DPRINTF(CCRegs, "[tid:%i]: Setting CC. Reg %i to %x\n", + tid, reg_idx, val); + ccRegs[tid][reg_idx] = val; +#else + panic("readCCReg: ISA does not have CC regs\n"); +#endif +} + uint64_t InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid) { @@ -1337,18 +1380,25 @@ InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid) tid = TheISA::getTargetThread(tcBase(tid)); } - if (reg_idx < FP_Base_DepTag) { + RegIndex rel_idx; + + switch (regIdxToClass(reg_idx, &rel_idx)) { + case IntRegClass: // Integer Register File - return readIntReg(reg_idx, tid); - } else if (reg_idx < Ctrl_Base_DepTag) { + return readIntReg(rel_idx, tid); + + case FloatRegClass: // Float Register File - reg_idx -= FP_Base_DepTag; - return readFloatRegBits(reg_idx, tid); - } else { - reg_idx -= Ctrl_Base_DepTag; - return readMiscReg(reg_idx, tid); // Misc. Register File + return readFloatRegBits(rel_idx, tid); + + case MiscRegClass: + return readMiscReg(rel_idx, tid); // Misc. Register File + + default: + panic("register %d out of range\n", reg_idx); } } + void InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, ThreadID tid) @@ -1358,39 +1408,49 @@ InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, tid = TheISA::getTargetThread(tcBase(tid)); } - if (reg_idx < FP_Base_DepTag) { // Integer Register File - setIntReg(reg_idx, val, tid); - } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File - reg_idx -= FP_Base_DepTag; - setFloatRegBits(reg_idx, val, tid); - } else { - reg_idx -= Ctrl_Base_DepTag; - setMiscReg(reg_idx, val, tid); // Misc. Register File + RegIndex rel_idx; + + switch (regIdxToClass(reg_idx, &rel_idx)) { + case IntRegClass: + setIntReg(rel_idx, val, tid); + break; + + case FloatRegClass: + setFloatRegBits(rel_idx, val, tid); + break; + + case CCRegClass: + setCCReg(rel_idx, val, tid); + break; + + case MiscRegClass: + setMiscReg(rel_idx, val, tid); // Misc. Register File + break; } } MiscReg InOrderCPU::readMiscRegNoEffect(int misc_reg, ThreadID tid) { - return isa[tid].readMiscRegNoEffect(misc_reg); + return isa[tid]->readMiscRegNoEffect(misc_reg); } MiscReg InOrderCPU::readMiscReg(int misc_reg, ThreadID tid) { - return isa[tid].readMiscReg(misc_reg, tcBase(tid)); + return isa[tid]->readMiscReg(misc_reg, tcBase(tid)); } void InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid) { - isa[tid].setMiscRegNoEffect(misc_reg, val); + isa[tid]->setMiscRegNoEffect(misc_reg, val); } void InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid) { - isa[tid].setMiscReg(misc_reg, val, tcBase(tid)); + isa[tid]->setMiscReg(misc_reg, val, tcBase(tid)); } @@ -1697,7 +1757,9 @@ InOrderCPU::wakeCPU() DPRINTF(Activity, "Waking up CPU\n"); - Tick extra_cycles = tickToCycles((curTick() - 1) - lastRunningCycle); + Tick extra_cycles = curCycle() - lastRunningCycle; + if (extra_cycles != 0) + --extra_cycles; idleCycles += extra_cycles; for (int stage_num = 0; stage_num < NumStages; stage_num++) { @@ -1706,7 +1768,7 @@ InOrderCPU::wakeCPU() numCycles += extra_cycles; - schedule(&tickEvent, nextCycle(curTick())); + schedule(&tickEvent, clockEdge()); } // Lots of copied full system code...place into BaseCPU class? @@ -1723,7 +1785,8 @@ InOrderCPU::wakeup() } void -InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay) +InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, + Cycles delay) { // Syscall must be non-speculative, so squash from last stage unsigned squash_stage = NumStages - 1; @@ -1734,7 +1797,8 @@ InOrderCPU::syscallContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay // Schedule Squash Through-out Resource Pool resPool->scheduleEvent( - (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); + (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, + Cycles(0)); scheduleCpuEvent(Syscall, fault, tid, inst, delay, Syscall_Pri); } @@ -1774,10 +1838,10 @@ InOrderCPU::getDTBPtr() return resPool->getDataUnit()->tlb(); } -Decoder * -InOrderCPU::getDecoderPtr() +TheISA::Decoder * +InOrderCPU::getDecoderPtr(unsigned tid) { - return &resPool->getInstUnit()->decoder; + return resPool->getInstUnit()->decoder[tid]; } Fault