X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Finorder%2Fcpu.cc;h=5a02f94d9bcc969b8ca0fcf80ab666860596aea8;hb=7d0344704a9ecc566d82ad43ec44b4becbaf4d77;hp=84f5e38509c577e22578434deb5fea96bdddfbf4;hpb=9f07d2ce7ecf435b9a1946f15fb3491bb4636637;p=gem5.git diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 84f5e3850..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,24 +84,20 @@ 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) { if (pkt->isError()) DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", pkt->getAddr()); - else if (pkt->isResponse()) + else cacheUnit->processCacheCompletion(pkt); - else { - //@note: depending on consistency model, update here - DPRINTF(InOrderCachePort, "Received snoop pkt %x,Ignoring\n", - pkt->getAddr()); - } return true; } @@ -213,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 @@ -234,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), @@ -245,7 +244,6 @@ InOrderCPU::InOrderCPU(Params *params) resReqCount(0), #endif // DEBUG drainCount(0), - deferRegistration(false/*params->deferRegistration*/), stageTracing(params->stageTracing), lastRunningCycle(0), instsPerSwitch(0) @@ -284,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); @@ -294,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 { @@ -362,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, @@ -387,6 +389,12 @@ InOrderCPU::InOrderCPU(Params *params) } + // InOrderCPU always requires an interrupt controller. + if (!params->switched_out && !interrupts) { + fatal("InOrderCPU %s has no interrupt controller.\n" + "Ensure createInterruptController() is called.\n", name()); + } + dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0); dummyReqInst->setSquashed(); dummyReqInst->resetInstCount(); @@ -399,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() @@ -759,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))); } } @@ -781,32 +789,40 @@ InOrderCPU::tick() void InOrderCPU::init() { - if (!deferRegistration) { - registerThreadContexts(); - } + BaseCPU::init(); - // Set inSyscall so that the CPU doesn't squash when initially - // setting up registers. - for (ThreadID tid = 0; tid < numThreads; ++tid) - thread[tid]->inSyscall = true; + for (ThreadID tid = 0; tid < numThreads; ++tid) { + // Set noSquashFromTC so that the CPU doesn't squash when initially + // setting up registers. + 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()); - // Initialise the ThreadContext's memory proxies - thread[tid]->initMemProxies(thread[tid]->getTC()); } } - // 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) { @@ -876,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]); @@ -911,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; @@ -925,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); } @@ -953,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 @@ -1075,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); @@ -1157,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); @@ -1172,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"); @@ -1246,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); } } @@ -1288,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) { @@ -1327,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) { @@ -1335,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) @@ -1356,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)); } @@ -1695,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++) { @@ -1704,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? @@ -1721,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; @@ -1732,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); } @@ -1772,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