diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2016-04-06 19:43:31 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2016-04-06 19:43:31 +0100 |
commit | be28d96510e0e722db83b26f1a12d3f5de979b32 (patch) | |
tree | 6a7e1807397f002f51fddb34568b89250fca45c8 /src | |
parent | 8615b27174ae06db4665016c877b1e88031af203 (diff) | |
download | gem5-be28d96510e0e722db83b26f1a12d3f5de979b32.tar.xz |
Revert power patch sets with unexpected interactions
The following patches had unexpected interactions with the current
upstream code and have been reverted for now:
e07fd01651f3: power: Add support for power models
831c7f2f9e39: power: Low-power idle power state for idle CPUs
4f749e00b667: power: Add power states to ClockedObject
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
--HG--
extra : amend_source : 0b6fb073c6bbc24be533ec431eb51fbf1b269508
Diffstat (limited to 'src')
56 files changed, 223 insertions, 1851 deletions
diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index d3286a6b0..6f66e5ae1 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -1521,7 +1521,8 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) // with unexpected atomic snoop requests. warn("Translating via MISCREG(%d) in functional mode! Fix Me!\n", misc_reg); Request req(0, val, 1, flags, Request::funcMasterId, - tc->pcState().pc(), tc->contextId()); + tc->pcState().pc(), tc->contextId(), + tc->threadId()); fault = tc->getDTBPtr()->translateFunctional(&req, tc, mode, tranType); TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR); HCR hcr = readMiscRegNoEffect(MISCREG_HCR); @@ -1767,7 +1768,7 @@ ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc) warn("Translating via MISCREG(%d) in functional mode! Fix Me!\n", misc_reg); req->setVirt(0, val, 1, flags, Request::funcMasterId, tc->pcState().pc()); - req->setContext(tc->contextId()); + req->setThreadContext(tc->contextId(), tc->threadId()); fault = tc->getDTBPtr()->translateFunctional(req, tc, mode, tranType); diff --git a/src/arch/arm/vtophys.cc b/src/arch/arm/vtophys.cc index 24fc5a5c7..3aad35818 100644 --- a/src/arch/arm/vtophys.cc +++ b/src/arch/arm/vtophys.cc @@ -69,7 +69,7 @@ try_translate(ThreadContext *tc, Addr addr) Fault fault; // Set up a functional memory Request to pass to the TLB // to get it to translate the vaddr to a paddr - Request req(0, addr, 64, 0x40, -1, 0, 0); + Request req(0, addr, 64, 0x40, -1, 0, 0, 0); ArmISA::TLB *tlb; // Check the TLBs for a translation diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 0f9fe49ea..624843f42 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -64,7 +64,6 @@ #include "debug/SyscallVerbose.hh" #include "mem/page_table.hh" #include "params/BaseCPU.hh" -#include "sim/clocked_object.hh" #include "sim/full_system.hh" #include "sim/process.hh" #include "sim/sim_events.hh" @@ -356,11 +355,6 @@ BaseCPU::startup() if (params()->progress_interval) { new CPUProgressEvent(this, params()->progress_interval); } - - // Assumption CPU start to operate instantaneously without any latency - if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED) - ClockedObject::pwrState(Enums::PwrState::ON); - } ProbePoints::PMUUPtr @@ -479,27 +473,6 @@ BaseCPU::findContext(ThreadContext *tc) } void -BaseCPU::activateContext(ThreadID thread_num) -{ - // For any active thread running, update CPU power state to active (ON) - ClockedObject::pwrState(Enums::PwrState::ON); -} - -void -BaseCPU::suspendContext(ThreadID thread_num) -{ - // Check if all threads are suspended - for (auto t : threadContexts) { - if (t->status() != ThreadContext::Suspended) { - return; - } - } - - // All CPU threads suspended, enter lower power state for the CPU - ClockedObject::pwrState(Enums::PwrState::CLK_GATED); -} - -void BaseCPU::switchOut() { assert(!_switchedOut); diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 6622339e0..438c38812 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -279,11 +279,10 @@ class BaseCPU : public MemObject Trace::InstTracer * getTracer() { return tracer; } /// Notify the CPU that the indicated context is now active. - virtual void activateContext(ThreadID thread_num); + virtual void activateContext(ThreadID thread_num) {} /// Notify the CPU that the indicated context is now suspended. - /// Check if possible to enter a lower power state - virtual void suspendContext(ThreadID thread_num); + virtual void suspendContext(ThreadID thread_num) {} /// Notify the CPU that the indicated context is now halted. virtual void haltContext(ThreadID thread_num) {} @@ -297,10 +296,6 @@ class BaseCPU : public MemObject /// Get the number of thread contexts available unsigned numContexts() { return threadContexts.size(); } - /// Convert ContextID to threadID - ThreadID contextToThread(ContextID cid) - { return static_cast<ThreadID>(cid - threadContexts[0]->contextId()); } - public: typedef BaseCPUParams Params; const Params *params() const diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index e846f6790..031337aec 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -886,7 +886,7 @@ BaseDynInst<Impl>::initiateMemRead(Addr addr, unsigned size, unsigned flags) sreqHigh = savedSreqHigh; } else { req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(), - thread->contextId()); + thread->contextId(), threadNumber); req->taskId(cpu->taskId()); @@ -942,7 +942,7 @@ BaseDynInst<Impl>::writeMem(uint8_t *data, unsigned size, sreqHigh = savedSreqHigh; } else { req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(), - thread->contextId()); + thread->contextId(), threadNumber); req->taskId(cpu->taskId()); diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index 4d5919cdf..ac476e5f4 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -155,7 +155,7 @@ CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) // Need to account for multiple accesses like the Atomic and TimingSimple while (1) { memReq = new Request(0, addr, size, flags, masterId, - thread->pcState().instAddr(), tc->contextId()); + thread->pcState().instAddr(), tc->contextId(), 0); // translate to physical address fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read); @@ -243,7 +243,7 @@ CheckerCPU::writeMem(uint8_t *data, unsigned size, // Need to account for a multiple access like Atomic and Timing CPUs while (1) { memReq = new Request(0, addr, size, flags, masterId, - thread->pcState().instAddr(), tc->contextId()); + thread->pcState().instAddr(), tc->contextId(), 0); // translate to physical address fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write); diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 5d5900aae..289861521 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -248,7 +248,8 @@ Checker<Impl>::verify(DynInstPtr &completed_inst) sizeof(MachInst), 0, masterId, - fetch_PC, thread->contextId()); + fetch_PC, thread->contextId(), + unverifiedInst->threadNumber); memReq->setVirt(0, fetch_PC, sizeof(MachInst), Request::INST_FETCH, masterId, thread->instAddr()); diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc index 0670f61c6..bf4d68603 100644 --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -1027,7 +1027,7 @@ BaseKvmCPU::doMMIOAccess(Addr paddr, void *data, int size, bool write) syncThreadContext(); Request mmio_req(paddr, size, Request::UNCACHEABLE, dataMasterId()); - mmio_req.setContext(tc->contextId()); + mmio_req.setThreadContext(tc->contextId(), 0); // Some architectures do need to massage physical addresses a bit // before they are inserted into the memory system. This enables // APIC accesses on x86 and m5ops where supported through a MMIO diff --git a/src/cpu/kvm/x86_cpu.cc b/src/cpu/kvm/x86_cpu.cc index 9e9115ef5..c6c874dc4 100644 --- a/src/cpu/kvm/x86_cpu.cc +++ b/src/cpu/kvm/x86_cpu.cc @@ -1346,7 +1346,7 @@ X86KvmCPU::handleKvmExitIO() Request io_req(pAddr, kvm_run.io.size, Request::UNCACHEABLE, dataMasterId()); - io_req.setContext(tc->contextId()); + io_req.setThreadContext(tc->contextId(), 0); const MemCmd cmd(isWrite ? MemCmd::WriteReq : MemCmd::ReadReq); // Temporarily lock and migrate to the event queue of the diff --git a/src/cpu/minor/cpu.cc b/src/cpu/minor/cpu.cc index a707c6045..cd39a8b93 100644 --- a/src/cpu/minor/cpu.cc +++ b/src/cpu/minor/cpu.cc @@ -287,8 +287,6 @@ MinorCPU::activateContext(ThreadID thread_id) threads[thread_id]->activate(); wakeupOnEvent(Minor::Pipeline::CPUStageId); pipeline->wakeupFetch(); - - BaseCPU::activateContext(thread_id); } void @@ -297,8 +295,6 @@ MinorCPU::suspendContext(ThreadID thread_id) DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id); threads[thread_id]->suspend(); - - BaseCPU::suspendContext(thread_id); } void diff --git a/src/cpu/minor/fetch1.cc b/src/cpu/minor/fetch1.cc index d19d7b042..84aaf02f5 100644 --- a/src/cpu/minor/fetch1.cc +++ b/src/cpu/minor/fetch1.cc @@ -135,7 +135,8 @@ Fetch1::fetchLine() "%s addr: 0x%x pc: %s line_offset: %d request_size: %d\n", request_id, aligned_pc, pc, line_offset, request_size); - request->request.setContext(cpu.threads[0]->getTC()->contextId()); + request->request.setThreadContext(cpu.threads[0]->getTC()->contextId(), + /* thread id */ 0); request->request.setVirt(0 /* asid */, aligned_pc, request_size, Request::INST_FETCH, cpu.instMasterId(), /* I've no idea why we need the PC, but give it */ diff --git a/src/cpu/minor/lsq.cc b/src/cpu/minor/lsq.cc index b5c0bc974..e0c5796c8 100644 --- a/src/cpu/minor/lsq.cc +++ b/src/cpu/minor/lsq.cc @@ -422,7 +422,7 @@ LSQ::SplitDataRequest::makeFragmentRequests() Request *fragment = new Request(); - fragment->setContext(request.contextId()); + fragment->setThreadContext(request.contextId(), /* thread id */ 0); fragment->setVirt(0 /* asid */, fragment_addr, fragment_size, request.getFlags(), request.masterId(), @@ -1070,8 +1070,7 @@ LSQ::tryToSend(LSQRequestPtr request) if (request->request.isMmappedIpr()) { ThreadContext *thread = - cpu.getContext(cpu.contextToThread( - request->request.contextId())); + cpu.getContext(request->request.threadId()); if (request->isLoad) { DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst)); @@ -1503,7 +1502,7 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, inst->traceData->setMem(addr, size, flags); int cid = cpu.threads[inst->id.threadId]->getTC()->contextId(); - request->request.setContext(cid); + request->request.setThreadContext(cid, /* thread id */ 0); request->request.setVirt(0 /* asid */, addr, size, flags, cpu.dataMasterId(), /* I've no idea why we need the PC, but give it */ diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 73174e4a9..79ad705bf 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -735,8 +735,6 @@ FullO3CPU<Impl>::activateContext(ThreadID tid) lastActivatedCycle = curTick(); _status = Running; - - BaseCPU::activateContext(tid); } } @@ -757,8 +755,6 @@ FullO3CPU<Impl>::suspendContext(ThreadID tid) } DPRINTF(Quiesce, "Suspending Context\n"); - - BaseCPU::suspendContext(tid); } template <class Impl> diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 3b29d87d4..4b1479bcb 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -378,7 +378,7 @@ template<class Impl> void DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) { - ThreadID tid = cpu->contextToThread(pkt->req->contextId()); + ThreadID tid = pkt->req->threadId(); DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n", tid); assert(!cpu->switchedOut()); @@ -622,7 +622,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc) RequestPtr mem_req = new Request(tid, fetchBufferBlockPC, fetchBufferSize, Request::INST_FETCH, cpu->instMasterId(), pc, - cpu->thread[tid]->contextId()); + cpu->thread[tid]->contextId(), tid); mem_req->taskId(cpu->taskId()); @@ -640,7 +640,7 @@ template <class Impl> void DefaultFetch<Impl>::finishTranslation(const Fault &fault, RequestPtr mem_req) { - ThreadID tid = cpu->contextToThread(mem_req->contextId()); + ThreadID tid = mem_req->threadId(); Addr fetchBufferBlockPC = mem_req->getVaddr(); assert(!cpu->switchedOut()); diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 6bc9b3d73..dcd676221 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -334,7 +334,7 @@ Fault LSQ<Impl>::read(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh, int load_idx) { - ThreadID tid = cpu->contextToThread(req->contextId()); + ThreadID tid = req->threadId(); return thread[tid].read(req, sreqLow, sreqHigh, load_idx); } @@ -344,7 +344,7 @@ Fault LSQ<Impl>::write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh, uint8_t *data, int store_idx) { - ThreadID tid = cpu->contextToThread(req->contextId()); + ThreadID tid = req->threadId(); return thread[tid].write(req, sreqLow, sreqHigh, data, store_idx); } diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 9080907fe..06467243d 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -347,8 +347,7 @@ LSQ<Impl>::recvTimingResp(PacketPtr pkt) DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr()); - thread[cpu->contextToThread(pkt->req->contextId())] - .completeDataAccess(pkt); + thread[pkt->req->threadId()].completeDataAccess(pkt); if (pkt->isInvalidate()) { // This response also contains an invalidate; e.g. this can be the case diff --git a/src/cpu/pred/2bit_local.cc b/src/cpu/pred/2bit_local.cc index 9e1c781c5..36ca1593e 100644 --- a/src/cpu/pred/2bit_local.cc +++ b/src/cpu/pred/2bit_local.cc @@ -78,7 +78,7 @@ LocalBP::reset() } void -LocalBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) +LocalBP::btbUpdate(Addr branch_addr, void * &bp_history) { // Place holder for a function that is called to update predictor history when // a BTB entry is invalid or not found. @@ -86,7 +86,7 @@ LocalBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) bool -LocalBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) +LocalBP::lookup(Addr branch_addr, void * &bp_history) { bool taken; uint8_t counter_val; @@ -117,8 +117,7 @@ LocalBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) } void -LocalBP::update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed) +LocalBP::update(Addr branch_addr, bool taken, void *bp_history, bool squashed) { assert(bp_history == NULL); unsigned local_predictor_idx; @@ -153,7 +152,7 @@ LocalBP::getLocalIndex(Addr &branch_addr) } void -LocalBP::uncondBranch(ThreadID tid, Addr pc, void *&bp_history) +LocalBP::uncondBranch(Addr pc, void *&bp_history) { } diff --git a/src/cpu/pred/2bit_local.hh b/src/cpu/pred/2bit_local.hh index e3f87491b..61e2dc24e 100644 --- a/src/cpu/pred/2bit_local.hh +++ b/src/cpu/pred/2bit_local.hh @@ -66,7 +66,7 @@ class LocalBP : public BPredUnit */ LocalBP(const LocalBPParams *params); - virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); + virtual void uncondBranch(Addr pc, void * &bp_history); /** * Looks up the given address in the branch predictor and returns @@ -75,7 +75,7 @@ class LocalBP : public BPredUnit * @param bp_history Pointer to any bp history state. * @return Whether or not the branch is taken. */ - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); + bool lookup(Addr branch_addr, void * &bp_history); /** * Updates the branch predictor to Not Taken if a BTB entry is @@ -84,20 +84,19 @@ class LocalBP : public BPredUnit * @param bp_history Pointer to any bp history state. * @return Whether or not the branch is taken. */ - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); + void btbUpdate(Addr branch_addr, void * &bp_history); /** * Updates the branch predictor with the actual result of a branch. * @param branch_addr The address of the branch to update. * @param taken Whether or not the branch was taken. */ - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed); + void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); - void retireSquashed(ThreadID tid, void *bp_history) + void retireSquashed(void *bp_history) { assert(bp_history == NULL); } - void squash(ThreadID tid, void *bp_history) + void squash(void *bp_history) { assert(bp_history == NULL); } void reset(); diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 2d7d0d0e2..5c52fb65e 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -42,16 +42,6 @@ class BranchPredictor(SimObject): RASSize = Param.Unsigned(16, "RAS size") instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by") - useIndirect = Param.Bool(True, "Use indirect branch predictor") - indirectHashGHR = Param.Bool(True, "Hash branch predictor GHR") - indirectHashTargets = Param.Bool(True, "Hash path history targets") - indirectSets = Param.Unsigned(256, "Cache sets for indirect predictor") - indirectWays = Param.Unsigned(2, "Ways for indirect predictor") - indirectTagSize = Param.Unsigned(16, "Indirect target cache tag bits") - indirectPathLength = Param.Unsigned(3, - "Previous indirect targets to use for path history") - - class LocalBP(BranchPredictor): type = 'LocalBP' diff --git a/src/cpu/pred/SConscript b/src/cpu/pred/SConscript index dca5e8d88..1bf94712d 100644 --- a/src/cpu/pred/SConscript +++ b/src/cpu/pred/SConscript @@ -35,11 +35,9 @@ if env['TARGET_ISA'] == 'null': SimObject('BranchPredictor.py') -DebugFlag('Indirect') Source('bpred_unit.cc') Source('2bit_local.cc') Source('btb.cc') -Source('indirect.cc') Source('ras.cc') Source('tournament.cc') Source ('bi_mode.cc') diff --git a/src/cpu/pred/bi_mode.cc b/src/cpu/pred/bi_mode.cc index 48e798d96..c2a41cd4d 100644 --- a/src/cpu/pred/bi_mode.cc +++ b/src/cpu/pred/bi_mode.cc @@ -38,7 +38,7 @@ BiModeBP::BiModeBP(const BiModeBPParams *params) : BPredUnit(params), - globalHistoryReg(params->numThreads, 0), + globalHistoryReg(0), globalHistoryBits(ceilLog2(params->globalPredictorSize)), choicePredictorSize(params->choicePredictorSize), choiceCtrBits(params->choiceCtrBits), @@ -77,23 +77,23 @@ BiModeBP::BiModeBP(const BiModeBPParams *params) * chooses the taken array and the taken array predicts taken. */ void -BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory) +BiModeBP::uncondBranch(Addr pc, void * &bpHistory) { BPHistory *history = new BPHistory; - history->globalHistoryReg = globalHistoryReg[tid]; + history->globalHistoryReg = globalHistoryReg; history->takenUsed = true; history->takenPred = true; history->notTakenPred = true; history->finalPred = true; bpHistory = static_cast<void*>(history); - updateGlobalHistReg(tid, true); + updateGlobalHistReg(true); } void -BiModeBP::squash(ThreadID tid, void *bpHistory) +BiModeBP::squash(void *bpHistory) { BPHistory *history = static_cast<BPHistory*>(bpHistory); - globalHistoryReg[tid] = history->globalHistoryReg; + globalHistoryReg = history->globalHistoryReg; delete history; } @@ -108,12 +108,12 @@ BiModeBP::squash(ThreadID tid, void *bpHistory) * direction predictors for the final branch prediction. */ bool -BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory) +BiModeBP::lookup(Addr branchAddr, void * &bpHistory) { unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt) & choiceHistoryMask); unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt) - ^ globalHistoryReg[tid]) + ^ globalHistoryReg) & globalHistoryMask); assert(choiceHistoryIdx < choicePredictorSize); @@ -128,7 +128,7 @@ BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory) bool finalPrediction; BPHistory *history = new BPHistory; - history->globalHistoryReg = globalHistoryReg[tid]; + history->globalHistoryReg = globalHistoryReg; history->takenUsed = choicePrediction; history->takenPred = takenGHBPrediction; history->notTakenPred = notTakenGHBPrediction; @@ -141,15 +141,15 @@ BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory) history->finalPred = finalPrediction; bpHistory = static_cast<void*>(history); - updateGlobalHistReg(tid, finalPrediction); + updateGlobalHistReg(finalPrediction); return finalPrediction; } void -BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory) +BiModeBP::btbUpdate(Addr branchAddr, void * &bpHistory) { - globalHistoryReg[tid] &= (historyRegisterMask & ~ULL(1)); + globalHistoryReg &= (historyRegisterMask & ~ULL(1)); } /* Only the selected direction predictor will be updated with the final @@ -159,8 +159,7 @@ BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory) * the direction predictors makes a correct final prediction. */ void -BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory, - bool squashed) +BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed) { if (bpHistory) { BPHistory *history = static_cast<BPHistory*>(bpHistory); @@ -219,11 +218,11 @@ BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory, if (squashed) { if (taken) { - globalHistoryReg[tid] = (history->globalHistoryReg << 1) | 1; + globalHistoryReg = (history->globalHistoryReg << 1) | 1; } else { - globalHistoryReg[tid] = (history->globalHistoryReg << 1); + globalHistoryReg = (history->globalHistoryReg << 1); } - globalHistoryReg[tid] &= historyRegisterMask; + globalHistoryReg &= historyRegisterMask; } else { delete history; } @@ -231,24 +230,18 @@ BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory, } void -BiModeBP::retireSquashed(ThreadID tid, void *bp_history) +BiModeBP::retireSquashed(void *bp_history) { BPHistory *history = static_cast<BPHistory*>(bp_history); delete history; } -unsigned -BiModeBP::getGHR(ThreadID tid, void *bp_history) const -{ - return static_cast<BPHistory*>(bp_history)->globalHistoryReg; -} - void -BiModeBP::updateGlobalHistReg(ThreadID tid, bool taken) +BiModeBP::updateGlobalHistReg(bool taken) { - globalHistoryReg[tid] = taken ? (globalHistoryReg[tid] << 1) | 1 : - (globalHistoryReg[tid] << 1); - globalHistoryReg[tid] &= historyRegisterMask; + globalHistoryReg = taken ? (globalHistoryReg << 1) | 1 : + (globalHistoryReg << 1); + globalHistoryReg &= historyRegisterMask; } BiModeBP* diff --git a/src/cpu/pred/bi_mode.hh b/src/cpu/pred/bi_mode.hh index 96b3b2ef7..da7c49f46 100644 --- a/src/cpu/pred/bi_mode.hh +++ b/src/cpu/pred/bi_mode.hh @@ -57,17 +57,15 @@ class BiModeBP : public BPredUnit { public: BiModeBP(const BiModeBPParams *params); - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); - void squash(ThreadID tid, void *bp_history); - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed); - void retireSquashed(ThreadID tid, void *bp_history); - unsigned getGHR(ThreadID tid, void *bp_history) const; + void uncondBranch(Addr pc, void * &bp_history); + void squash(void *bp_history); + bool lookup(Addr branch_addr, void * &bp_history); + void btbUpdate(Addr branch_addr, void * &bp_history); + void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); + void retireSquashed(void *bp_history); private: - void updateGlobalHistReg(ThreadID tid, bool taken); + void updateGlobalHistReg(bool taken); struct BPHistory { unsigned globalHistoryReg; @@ -96,7 +94,7 @@ class BiModeBP : public BPredUnit // not-taken direction predictors std::vector<SatCounter> notTakenCounters; - std::vector<unsigned> globalHistoryReg; + unsigned globalHistoryReg; unsigned globalHistoryBits; unsigned historyRegisterMask; diff --git a/src/cpu/pred/bpred_unit.cc b/src/cpu/pred/bpred_unit.cc index 04a05eaa4..8bb84f836 100644 --- a/src/cpu/pred/bpred_unit.cc +++ b/src/cpu/pred/bpred_unit.cc @@ -59,18 +59,8 @@ BPredUnit::BPredUnit(const Params *params) predHist(numThreads), BTB(params->BTBEntries, params->BTBTagSize, - params->instShiftAmt, - params->numThreads), + params->instShiftAmt), RAS(numThreads), - useIndirect(params->useIndirect), - iPred(params->indirectHashGHR, - params->indirectHashTargets, - params->indirectSets, - params->indirectWays, - params->indirectTagSize, - params->indirectPathLength, - params->instShiftAmt, - params->numThreads), instShiftAmt(params->instShiftAmt) { for (auto& r : RAS) @@ -126,27 +116,6 @@ BPredUnit::regStats() .name(name() + ".RASInCorrect") .desc("Number of incorrect RAS predictions.") ; - - indirectLookups - .name(name() + ".indirectLookups") - .desc("Number of indirect predictor lookups.") - ; - - indirectHits - .name(name() + ".indirectHits") - .desc("Number of indirect target hits.") - ; - - indirectMisses - .name(name() + ".indirectMisses") - .desc("Number of indirect misses.") - ; - - indirectMispredicted - .name(name() + "indirectMispredcited") - .desc("Number of mispredicted indirect branches.") - ; - } ProbePoints::PMUUPtr @@ -195,10 +164,10 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid); pred_taken = true; // Tell the BP there was an unconditional branch. - uncondBranch(tid, pc.instAddr(), bp_history); + uncondBranch(pc.instAddr(), bp_history); } else { ++condPredicted; - pred_taken = lookup(tid, pc.instAddr(), bp_history); + pred_taken = lookup(pc.instAddr(), bp_history); DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor" " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc); @@ -246,59 +215,31 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, tid, pc, pc, RAS[tid].topIdx()); } - if (inst->isDirectCtrl() || !useIndirect) { - // Check BTB on direct branches - if (BTB.valid(pc.instAddr(), tid)) { - ++BTBHits; - - // If it's not a return, use the BTB to get target addr. - target = BTB.lookup(pc.instAddr(), tid); - - DPRINTF(Branch, "[tid:%i]: Instruction %s predicted" - " target is %s.\n", tid, pc, target); - - } else { - DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " - "valid entry.\n",tid); - pred_taken = false; - // The Direction of the branch predictor is altered - // because the BTB did not have an entry - // The predictor needs to be updated accordingly - if (!inst->isCall() && !inst->isReturn()) { - btbUpdate(tid, pc.instAddr(), bp_history); - DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate" - " called for %s\n", tid, seqNum, pc); - } else if (inst->isCall() && !inst->isUncondCtrl()) { - RAS[tid].pop(); - predict_record.pushedRAS = false; - } - TheISA::advancePC(target, inst); - } + if (BTB.valid(pc.instAddr(), tid)) { + ++BTBHits; + + // If it's not a return, use the BTB to get the target addr. + target = BTB.lookup(pc.instAddr(), tid); + + DPRINTF(Branch, "[tid:%i]: Instruction %s predicted" + " target is %s.\n", tid, pc, target); + } else { - predict_record.wasIndirect = true; - ++indirectLookups; - //Consult indirect predictor on indirect control - if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history), - target, tid)) { - // Indirect predictor hit - ++indirectHits; - DPRINTF(Branch, "[tid:%i]: Instruction %s predicted " - "indirect target is %s.\n", tid, pc, target); - } else { - ++indirectMisses; - pred_taken = false; - DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect " - "target.\n", tid, pc); - if (!inst->isCall() && !inst->isReturn()) { - - } else if (inst->isCall() && !inst->isUncondCtrl()) { - RAS[tid].pop(); - predict_record.pushedRAS = false; - } - TheISA::advancePC(target, inst); + DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " + "valid entry.\n",tid); + pred_taken = false; + // The Direction of the branch predictor is altered because the + // BTB did not have an entry + // The predictor needs to be updated accordingly + if (!inst->isCall() && !inst->isReturn()) { + btbUpdate(pc.instAddr(), bp_history); + DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate" + " called for %s\n", tid, seqNum, pc); + } else if (inst->isCall() && !inst->isUncondCtrl()) { + RAS[tid].pop(); + predict_record.pushedRAS = false; } - iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum, - tid); + TheISA::advancePC(target, inst); } } } else { @@ -346,7 +287,7 @@ BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum, DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid); pred_taken = true; // Tell the BP there was an unconditional branch. - uncondBranch(tid, instPC.instAddr(), bp_history); + uncondBranch(instPC.instAddr(), bp_history); if (inst->isReturn() && RAS[tid].empty()) { DPRINTF(Branch, "[tid:%i] RAS is empty, predicting " @@ -356,7 +297,7 @@ BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum, } else { ++condPredicted; - pred_taken = lookup(tid, predPC.instAddr(), bp_history); + pred_taken = lookup(predPC.instAddr(), bp_history); } PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken, @@ -446,16 +387,14 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) DPRINTF(Branch, "[tid:%i]: Committing branches until " "[sn:%lli].\n", tid, done_sn); - iPred.commit(done_sn, tid); while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. if (!predHist[tid].back().wasSquashed) { - update(tid, predHist[tid].back().pc, - predHist[tid].back().predTaken, - predHist[tid].back().bpHistory, false); + update(predHist[tid].back().pc, predHist[tid].back().predTaken, + predHist[tid].back().bpHistory, false); } else { - retireSquashed(tid, predHist[tid].back().bpHistory); + retireSquashed(predHist[tid].back().bpHistory); } predHist[tid].pop_back(); @@ -467,7 +406,6 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) { History &pred_hist = predHist[tid]; - iPred.squash(squashed_sn, tid); while (!pred_hist.empty() && pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().usedRAS) { @@ -486,7 +424,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) } // This call should delete the bpHistory. - squash(tid, pred_hist.front().bpHistory); + squash(pred_hist.front().bpHistory); DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] " "PC %s.\n", tid, pred_hist.front().seqNum, @@ -546,14 +484,9 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, if ((*hist_it).usedRAS) { ++RASIncorrect; - DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n", - tid, hist_it->seqNum); } - // Have to get GHR here because the update deletes bpHistory - unsigned ghr = getGHR(tid, hist_it->bpHistory); - - update(tid, (*hist_it).pc, actually_taken, + update((*hist_it).pc, actually_taken, pred_hist.front().bpHistory, true); hist_it->wasSquashed = true; @@ -565,15 +498,12 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, RAS[tid].pop(); hist_it->usedRAS = true; } - if (hist_it->wasIndirect) { - ++indirectMispredicted; - iPred.recordTarget(hist_it->seqNum, ghr, corrTarget, tid); - } else { - DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]" - " PC: %s\n", tid,hist_it->seqNum, hist_it->pc); - BTB.update((*hist_it).pc, corrTarget, tid); - } + DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]" + " PC: %s\n", tid,hist_it->seqNum, hist_it->pc); + + BTB.update((*hist_it).pc, corrTarget, tid); + } else { //Actually not Taken if (hist_it->usedRAS) { diff --git a/src/cpu/pred/bpred_unit.hh b/src/cpu/pred/bpred_unit.hh index c5e73f59d..bef8cb949 100644 --- a/src/cpu/pred/bpred_unit.hh +++ b/src/cpu/pred/bpred_unit.hh @@ -52,7 +52,6 @@ #include "base/statistics.hh" #include "base/types.hh" #include "cpu/pred/btb.hh" -#include "cpu/pred/indirect.hh" #include "cpu/pred/ras.hh" #include "cpu/inst_seq.hh" #include "cpu/static_inst.hh" @@ -98,7 +97,7 @@ class BPredUnit : public SimObject TheISA::PCState &predPC, ThreadID tid); // @todo: Rename this function. - virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) = 0; + virtual void uncondBranch(Addr pc, void * &bp_history) = 0; /** * Tells the branch predictor to commit any updates until the given @@ -133,7 +132,7 @@ class BPredUnit : public SimObject * @param bp_history Pointer to the history object. The predictor * will need to update any state and delete the object. */ - virtual void squash(ThreadID tid, void *bp_history) = 0; + virtual void squash(void *bp_history) = 0; /** * Looks up a given PC in the BP to see if it is taken or not taken. @@ -142,7 +141,7 @@ class BPredUnit : public SimObject * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - virtual bool lookup(ThreadID tid, Addr instPC, void * &bp_history) = 0; + virtual bool lookup(Addr instPC, void * &bp_history) = 0; /** * If a branch is not taken, because the BTB address is invalid or missing, @@ -152,7 +151,7 @@ class BPredUnit : public SimObject * @param bp_history Pointer that will be set to an object that * has the branch predictor state associated with the lookup. */ - virtual void btbUpdate(ThreadID tid, Addr instPC, void * &bp_history) = 0; + virtual void btbUpdate(Addr instPC, void * &bp_history) = 0; /** * Looks up a given PC in the BTB to see if a matching entry exists. @@ -180,15 +179,15 @@ class BPredUnit : public SimObject * squash operation. * @todo Make this update flexible enough to handle a global predictor. */ - virtual void update(ThreadID tid, Addr instPC, bool taken, - void *bp_history, bool squashed) = 0; + virtual void update(Addr instPC, bool taken, void *bp_history, + bool squashed) = 0; /** * Deletes the associated history with a branch, performs no predictor * updates. Used for branches that mispredict and update tables but * are still speculative and later retire. * @param bp_history History to delete associated with this predictor */ - virtual void retireSquashed(ThreadID tid, void *bp_history) = 0; + virtual void retireSquashed(void *bp_history) = 0; /** * Updates the BTB with the target of a branch. @@ -198,9 +197,6 @@ class BPredUnit : public SimObject void BTBUpdate(Addr instPC, const TheISA::PCState &target) { BTB.update(instPC, target, 0); } - - virtual unsigned getGHR(ThreadID tid, void* bp_history) const { return 0; } - void dump(); private: @@ -214,7 +210,7 @@ class BPredUnit : public SimObject ThreadID _tid) : seqNum(seq_num), pc(instPC), bpHistory(bp_history), RASTarget(0), RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), pushedRAS(0), - wasCall(0), wasReturn(0), wasSquashed(0), wasIndirect(0) + wasCall(0), wasReturn(0), wasSquashed(0) {} bool operator==(const PredictorHistory &entry) const { @@ -259,9 +255,6 @@ class BPredUnit : public SimObject /** Whether this instruction has already mispredicted/updated bp */ bool wasSquashed; - - /** Wether this instruction was an indirect branch */ - bool wasIndirect; }; typedef std::deque<PredictorHistory> History; @@ -283,12 +276,6 @@ class BPredUnit : public SimObject /** The per-thread return address stack. */ std::vector<ReturnAddrStack> RAS; - /** Option to disable indirect predictor. */ - const bool useIndirect; - - /** The indirect target predictor. */ - IndirectPredictor iPred; - /** Stat for number of BP lookups. */ Stats::Scalar lookups; /** Stat for number of conditional branches predicted. */ @@ -308,15 +295,6 @@ class BPredUnit : public SimObject /** Stat for number of times the RAS is incorrect. */ Stats::Scalar RASIncorrect; - /** Stat for the number of indirect target lookups.*/ - Stats::Scalar indirectLookups; - /** Stat for the number of indirect target hits.*/ - Stats::Scalar indirectHits; - /** Stat for the number of indirect target misses.*/ - Stats::Scalar indirectMisses; - /** Stat for the number of indirect target mispredictions.*/ - Stats::Scalar indirectMispredicted; - protected: /** Number of bits to shift instructions by for predictor addresses. */ const unsigned instShiftAmt; diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc index c7ef1959f..393e52ccf 100644 --- a/src/cpu/pred/btb.cc +++ b/src/cpu/pred/btb.cc @@ -35,12 +35,10 @@ DefaultBTB::DefaultBTB(unsigned _numEntries, unsigned _tagBits, - unsigned _instShiftAmt, - unsigned _num_threads) + unsigned _instShiftAmt) : numEntries(_numEntries), tagBits(_tagBits), - instShiftAmt(_instShiftAmt), - log2NumThreads(floorLog2(_num_threads)) + instShiftAmt(_instShiftAmt) { DPRINTF(Fetch, "BTB: Creating BTB object.\n"); @@ -71,12 +69,10 @@ DefaultBTB::reset() inline unsigned -DefaultBTB::getIndex(Addr instPC, ThreadID tid) +DefaultBTB::getIndex(Addr instPC) { // Need to shift PC over by the word offset. - return ((instPC >> instShiftAmt) - ^ (tid << (tagShiftAmt - instShiftAmt - log2NumThreads))) - & idxMask; + return (instPC >> instShiftAmt) & idxMask; } inline @@ -89,7 +85,7 @@ DefaultBTB::getTag(Addr instPC) bool DefaultBTB::valid(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(instPC, tid); + unsigned btb_idx = getIndex(instPC); Addr inst_tag = getTag(instPC); @@ -110,7 +106,7 @@ DefaultBTB::valid(Addr instPC, ThreadID tid) TheISA::PCState DefaultBTB::lookup(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(instPC, tid); + unsigned btb_idx = getIndex(instPC); Addr inst_tag = getTag(instPC); @@ -128,7 +124,7 @@ DefaultBTB::lookup(Addr instPC, ThreadID tid) void DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid) { - unsigned btb_idx = getIndex(instPC, tid); + unsigned btb_idx = getIndex(instPC); assert(btb_idx < numEntries); diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh index 209bbdb49..3a773e40d 100644 --- a/src/cpu/pred/btb.hh +++ b/src/cpu/pred/btb.hh @@ -66,7 +66,7 @@ class DefaultBTB * @param instShiftAmt Offset amount for instructions to ignore alignment. */ DefaultBTB(unsigned numEntries, unsigned tagBits, - unsigned instShiftAmt, unsigned numThreads); + unsigned instShiftAmt); void reset(); @@ -97,7 +97,7 @@ class DefaultBTB * @param inst_PC The branch to look up. * @return Returns the index into the BTB. */ - inline unsigned getIndex(Addr instPC, ThreadID tid); + inline unsigned getIndex(Addr instPC); /** Returns the tag bits of a given address. * @param inst_PC The branch's address. @@ -125,9 +125,6 @@ class DefaultBTB /** Number of bits to shift PC when calculating tag. */ unsigned tagShiftAmt; - - /** Log2 NumThreads used for hashing threadid */ - unsigned log2NumThreads; }; #endif // __CPU_PRED_BTB_HH__ diff --git a/src/cpu/pred/indirect.cc b/src/cpu/pred/indirect.cc deleted file mode 100644 index a8934d55e..000000000 --- a/src/cpu/pred/indirect.cc +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2014 ARM Limited - * 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: Mitch Hayenga - */ - -#include "cpu/pred/indirect.hh" - -#include "base/intmath.hh" -#include "debug/Indirect.hh" - -IndirectPredictor::IndirectPredictor(bool hash_ghr, bool hash_targets, - unsigned num_sets, unsigned num_ways, - unsigned tag_bits, unsigned path_len, unsigned inst_shift, - unsigned num_threads) - : hashGHR(hash_ghr), hashTargets(hash_targets), - numSets(num_sets), numWays(num_ways), tagBits(tag_bits), - pathLength(path_len), instShift(inst_shift) -{ - if (!isPowerOf2(numSets)) { - panic("Indirect predictor requires power of 2 number of sets"); - } - - threadInfo.resize(num_threads); - - targetCache.resize(numSets); - for (unsigned i = 0; i < numSets; i++) { - targetCache[i].resize(numWays); - } -} - -bool -IndirectPredictor::lookup(Addr br_addr, unsigned ghr, TheISA::PCState& target, - ThreadID tid) -{ - Addr set_index = getSetIndex(br_addr, ghr, tid); - Addr tag = getTag(br_addr); - - assert(set_index < numSets); - - DPRINTF(Indirect, "Looking up %x (set:%d)\n", br_addr, set_index); - const auto &iset = targetCache[set_index]; - for (auto way = iset.begin(); way != iset.end(); ++way) { - if (way->tag == tag) { - DPRINTF(Indirect, "Hit %x (target:%s)\n", br_addr, way->target); - target = way->target; - return true; - } - } - DPRINTF(Indirect, "Miss %x\n", br_addr); - return false; -} - -void -IndirectPredictor::recordIndirect(Addr br_addr, Addr tgt_addr, - InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Indirect, "Recording %x seq:%d\n", br_addr, seq_num); - HistoryEntry entry(br_addr, tgt_addr, seq_num); - threadInfo[tid].pathHist.push_back(entry); -} - -void -IndirectPredictor::commit(InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Indirect, "Committing seq:%d\n", seq_num); - ThreadInfo &t_info = threadInfo[tid]; - - if (t_info.pathHist.empty()) return; - - if (t_info.headHistEntry < t_info.pathHist.size() && - t_info.pathHist[t_info.headHistEntry].seqNum <= seq_num) { - if (t_info.headHistEntry >= pathLength) { - t_info.pathHist.pop_front(); - } else { - ++t_info.headHistEntry; - } - } -} - -void -IndirectPredictor::squash(InstSeqNum seq_num, ThreadID tid) -{ - DPRINTF(Indirect, "Squashing seq:%d\n", seq_num); - ThreadInfo &t_info = threadInfo[tid]; - auto squash_itr = t_info.pathHist.begin(); - while (squash_itr != t_info.pathHist.end()) { - if (squash_itr->seqNum > seq_num) { - break; - } - ++squash_itr; - } - if (squash_itr != t_info.pathHist.end()) { - DPRINTF(Indirect, "Squashing series starting with sn:%d\n", - squash_itr->seqNum); - } - t_info.pathHist.erase(squash_itr, t_info.pathHist.end()); -} - - -void -IndirectPredictor::recordTarget(InstSeqNum seq_num, unsigned ghr, - const TheISA::PCState& target, ThreadID tid) -{ - ThreadInfo &t_info = threadInfo[tid]; - - // Should have just squashed so this branch should be the oldest - auto hist_entry = *(t_info.pathHist.rbegin()); - // Temporarily pop it off the history so we can calculate the set - t_info.pathHist.pop_back(); - Addr set_index = getSetIndex(hist_entry.pcAddr, ghr, tid); - Addr tag = getTag(hist_entry.pcAddr); - hist_entry.targetAddr = target.instAddr(); - t_info.pathHist.push_back(hist_entry); - - assert(set_index < numSets); - - auto &iset = targetCache[set_index]; - for (auto way = iset.begin(); way != iset.end(); ++way) { - if (way->tag == tag) { - DPRINTF(Indirect, "Updating Target (seq: %d br:%x set:%d target:" - "%s)\n", seq_num, hist_entry.pcAddr, set_index, target); - way->target = target; - return; - } - } - - DPRINTF(Indirect, "Allocating Target (seq: %d br:%x set:%d target:%s)\n", - seq_num, hist_entry.pcAddr, set_index, target); - // Did not find entry, random replacement - auto &way = iset[rand() % numWays]; - way.tag = tag; - way.target = target; -} - - -inline Addr -IndirectPredictor::getSetIndex(Addr br_addr, unsigned ghr, ThreadID tid) -{ - ThreadInfo &t_info = threadInfo[tid]; - - Addr hash = br_addr >> instShift; - if (hashGHR) { - hash ^= ghr; - } - if (hashTargets) { - unsigned hash_shift = floorLog2(numSets) / pathLength; - for (int i = t_info.pathHist.size()-1, p = 0; - i >= 0 && p < pathLength; i--, p++) { - hash ^= (t_info.pathHist[i].targetAddr >> - (instShift + p*hash_shift)); - } - } - return hash & (numSets-1); -} - -inline Addr -IndirectPredictor::getTag(Addr br_addr) -{ - return (br_addr >> instShift) & ((0x1<<tagBits)-1); -} diff --git a/src/cpu/pred/indirect.hh b/src/cpu/pred/indirect.hh deleted file mode 100644 index 89450530e..000000000 --- a/src/cpu/pred/indirect.hh +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2014 ARM Limited - * 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: Mitch Hayenga - */ - -#ifndef __CPU_PRED_INDIRECT_HH__ -#define __CPU_PRED_INDIRECT_HH__ - -#include <deque> - -#include "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "cpu/inst_seq.hh" - -class IndirectPredictor -{ - public: - IndirectPredictor(bool hash_ghr, bool hash_targets, - unsigned num_sets, unsigned num_ways, - unsigned tag_bits, unsigned path_len, - unsigned inst_shift, unsigned num_threads); - bool lookup(Addr br_addr, unsigned ghr, TheISA::PCState& br_target, - ThreadID tid); - void recordIndirect(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num, - ThreadID tid); - void commit(InstSeqNum seq_num, ThreadID tid); - void squash(InstSeqNum seq_num, ThreadID tid); - void recordTarget(InstSeqNum seq_num, unsigned ghr, - const TheISA::PCState& target, ThreadID tid); - - private: - const bool hashGHR; - const bool hashTargets; - const unsigned numSets; - const unsigned numWays; - const unsigned tagBits; - const unsigned pathLength; - const unsigned instShift; - - struct IPredEntry - { - IPredEntry() : tag(0), target(0) { } - Addr tag; - TheISA::PCState target; - }; - - std::vector<std::vector<IPredEntry> > targetCache; - - Addr getSetIndex(Addr br_addr, unsigned ghr, ThreadID tid); - Addr getTag(Addr br_addr); - - struct HistoryEntry - { - HistoryEntry(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num) - : pcAddr(br_addr), targetAddr(tgt_addr), seqNum(seq_num) { } - Addr pcAddr; - Addr targetAddr; - InstSeqNum seqNum; - }; - - - struct ThreadInfo { - ThreadInfo() : headHistEntry(0) { } - - std::deque<HistoryEntry> pathHist; - unsigned headHistEntry; - }; - - std::vector<ThreadInfo> threadInfo; -}; - -#endif // __CPU_PRED_INDIRECT_HH__ diff --git a/src/cpu/pred/tournament.cc b/src/cpu/pred/tournament.cc index 319606871..ea6be46fa 100644 --- a/src/cpu/pred/tournament.cc +++ b/src/cpu/pred/tournament.cc @@ -52,7 +52,6 @@ TournamentBP::TournamentBP(const TournamentBPParams *params) localHistoryBits(ceilLog2(params->localPredictorSize)), globalPredictorSize(params->globalPredictorSize), globalCtrBits(params->globalCtrBits), - globalHistory(params->numThreads, 0), globalHistoryBits( ceilLog2(params->globalPredictorSize) > ceilLog2(params->choicePredictorSize) ? @@ -93,6 +92,8 @@ TournamentBP::TournamentBP(const TournamentBPParams *params) for (int i = 0; i < globalPredictorSize; ++i) globalCtrs[i].setBits(globalCtrBits); + //Clear the global history + globalHistory = 0; // Set up the global history mask // this is equivalent to mask(log2(globalPredictorSize) globalHistoryMask = globalPredictorSize - 1; @@ -144,18 +145,18 @@ TournamentBP::calcLocHistIdx(Addr &branch_addr) inline void -TournamentBP::updateGlobalHistTaken(ThreadID tid) +TournamentBP::updateGlobalHistTaken() { - globalHistory[tid] = (globalHistory[tid] << 1) | 1; - globalHistory[tid] = globalHistory[tid] & historyRegisterMask; + globalHistory = (globalHistory << 1) | 1; + globalHistory = globalHistory & historyRegisterMask; } inline void -TournamentBP::updateGlobalHistNotTaken(ThreadID tid) +TournamentBP::updateGlobalHistNotTaken() { - globalHistory[tid] = (globalHistory[tid] << 1); - globalHistory[tid] = globalHistory[tid] & historyRegisterMask; + globalHistory = (globalHistory << 1); + globalHistory = globalHistory & historyRegisterMask; } inline @@ -176,18 +177,18 @@ TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx) void -TournamentBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history) +TournamentBP::btbUpdate(Addr branch_addr, void * &bp_history) { unsigned local_history_idx = calcLocHistIdx(branch_addr); //Update Global History to Not Taken (clear LSB) - globalHistory[tid] &= (historyRegisterMask & ~ULL(1)); + globalHistory &= (historyRegisterMask & ~ULL(1)); //Update Local History to Not Taken localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1)); } bool -TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) +TournamentBP::lookup(Addr branch_addr, void * &bp_history) { bool local_prediction; unsigned local_history_idx; @@ -203,16 +204,16 @@ TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) local_prediction = localCtrs[local_predictor_idx].read() > localThreshold; //Lookup in the global predictor to get its branch prediction - global_prediction = globalThreshold < - globalCtrs[globalHistory[tid] & globalHistoryMask].read(); + global_prediction = + globalCtrs[globalHistory & globalHistoryMask].read() > globalThreshold; //Lookup in the choice predictor to see which one to use - choice_prediction = choiceThreshold < - choiceCtrs[globalHistory[tid] & choiceHistoryMask].read(); + choice_prediction = + choiceCtrs[globalHistory & choiceHistoryMask].read() > choiceThreshold; // Create BPHistory and pass it back to be recorded. BPHistory *history = new BPHistory; - history->globalHistory = globalHistory[tid]; + history->globalHistory = globalHistory; history->localPredTaken = local_prediction; history->globalPredTaken = global_prediction; history->globalUsed = choice_prediction; @@ -226,21 +227,21 @@ TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) // all histories. if (choice_prediction) { if (global_prediction) { - updateGlobalHistTaken(tid); + updateGlobalHistTaken(); updateLocalHistTaken(local_history_idx); return true; } else { - updateGlobalHistNotTaken(tid); + updateGlobalHistNotTaken(); updateLocalHistNotTaken(local_history_idx); return false; } } else { if (local_prediction) { - updateGlobalHistTaken(tid); + updateGlobalHistTaken(); updateLocalHistTaken(local_history_idx); return true; } else { - updateGlobalHistNotTaken(tid); + updateGlobalHistNotTaken(); updateLocalHistNotTaken(local_history_idx); return false; } @@ -248,11 +249,11 @@ TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history) } void -TournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history) +TournamentBP::uncondBranch(Addr pc, void * &bp_history) { // Create BPHistory and pass it back to be recorded. BPHistory *history = new BPHistory; - history->globalHistory = globalHistory[tid]; + history->globalHistory = globalHistory; history->localPredTaken = true; history->globalPredTaken = true; history->globalUsed = true; @@ -260,12 +261,12 @@ TournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history) history->localHistory = invalidPredictorIndex; bp_history = static_cast<void *>(history); - updateGlobalHistTaken(tid); + updateGlobalHistTaken(); } void -TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, - void *bp_history, bool squashed) +TournamentBP::update(Addr branch_addr, bool taken, void *bp_history, + bool squashed) { unsigned local_history_idx; unsigned local_predictor_idx M5_VAR_USED; @@ -331,15 +332,15 @@ TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, } if (squashed) { if (taken) { - globalHistory[tid] = (history->globalHistory << 1) | 1; - globalHistory[tid] = globalHistory[tid] & historyRegisterMask; + globalHistory = (history->globalHistory << 1) | 1; + globalHistory = globalHistory & historyRegisterMask; if (old_local_pred_valid) { localHistoryTable[local_history_idx] = (history->localHistory << 1) | 1; } } else { - globalHistory[tid] = (history->globalHistory << 1); - globalHistory[tid] = globalHistory[tid] & historyRegisterMask; + globalHistory = (history->globalHistory << 1); + globalHistory = globalHistory & historyRegisterMask; if (old_local_pred_valid) { localHistoryTable[local_history_idx] = history->localHistory << 1; @@ -358,19 +359,19 @@ TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken, } void -TournamentBP::retireSquashed(ThreadID tid, void *bp_history) +TournamentBP::retireSquashed(void *bp_history) { BPHistory *history = static_cast<BPHistory *>(bp_history); delete history; } void -TournamentBP::squash(ThreadID tid, void *bp_history) +TournamentBP::squash(void *bp_history) { BPHistory *history = static_cast<BPHistory *>(bp_history); // Restore global history to state prior to this branch. - globalHistory[tid] = history->globalHistory; + globalHistory = history->globalHistory; // Restore local history if (history->localHistoryIdx != invalidPredictorIndex) { @@ -387,12 +388,6 @@ TournamentBPParams::create() return new TournamentBP(this); } -unsigned -TournamentBP::getGHR(ThreadID tid, void *bp_history) const -{ - return static_cast<BPHistory *>(bp_history)->globalHistory; -} - #ifdef DEBUG int TournamentBP::BPHistory::newCount = 0; diff --git a/src/cpu/pred/tournament.hh b/src/cpu/pred/tournament.hh index 3aa17e030..8fb5b515c 100644 --- a/src/cpu/pred/tournament.hh +++ b/src/cpu/pred/tournament.hh @@ -77,7 +77,7 @@ class TournamentBP : public BPredUnit * @param bp_history Pointer that will be set to the BPHistory object. * @return Whether or not the branch is taken. */ - bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history); + bool lookup(Addr branch_addr, void * &bp_history); /** * Records that there was an unconditional branch, and modifies @@ -85,7 +85,7 @@ class TournamentBP : public BPredUnit * global history stored in it. * @param bp_history Pointer that will be set to the BPHistory object. */ - void uncondBranch(ThreadID tid, Addr pc, void * &bp_history); + void uncondBranch(Addr pc, void * &bp_history); /** * Updates the branch predictor to Not Taken if a BTB entry is * invalid or not found. @@ -93,7 +93,7 @@ class TournamentBP : public BPredUnit * @param bp_history Pointer to any bp history state. * @return Whether or not the branch is taken. */ - void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history); + void btbUpdate(Addr branch_addr, void * &bp_history); /** * Updates the branch predictor with the actual result of a branch. * @param branch_addr The address of the branch to update. @@ -103,19 +103,19 @@ class TournamentBP : public BPredUnit * @param squashed is set when this function is called during a squash * operation. */ - void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, - bool squashed); + void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); - void retireSquashed(ThreadID tid, void *bp_history); + void retireSquashed(void *bp_history); /** * Restores the global branch history on a squash. * @param bp_history Pointer to the BPHistory object that has the * previous global branch history in it. */ - void squash(ThreadID tid, void *bp_history); + void squash(void *bp_history); - unsigned getGHR(ThreadID tid, void *bp_history) const; + /** Returns the global history. */ + inline unsigned readGlobalHist() { return globalHistory; } private: /** @@ -132,10 +132,10 @@ class TournamentBP : public BPredUnit inline unsigned calcLocHistIdx(Addr &branch_addr); /** Updates global history as taken. */ - inline void updateGlobalHistTaken(ThreadID tid); + inline void updateGlobalHistTaken(); /** Updates global history as not taken. */ - inline void updateGlobalHistNotTaken(ThreadID tid); + inline void updateGlobalHistNotTaken(); /** * Updates local histories as taken. @@ -209,7 +209,7 @@ class TournamentBP : public BPredUnit /** Global history register. Contains as much history as specified by * globalHistoryBits. Actual number of bits used is determined by * globalHistoryMask and choiceHistoryMask. */ - std::vector<unsigned> globalHistory; + unsigned globalHistory; /** Number of bits for the global history. Determines maximum number of entries in global and choice predictor tables. */ diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index a8e97f14c..f3e14d401 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -87,9 +87,9 @@ AtomicSimpleCPU::init() BaseSimpleCPU::init(); int cid = threadContexts[0]->contextId(); - ifetch_req.setContext(cid); - data_read_req.setContext(cid); - data_write_req.setContext(cid); + ifetch_req.setThreadContext(cid, 0); + data_read_req.setThreadContext(cid, 0); + data_write_req.setThreadContext(cid, 0); } AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) @@ -247,8 +247,6 @@ AtomicSimpleCPU::activateContext(ThreadID thread_num) == activeThreads.end()) { activeThreads.push_back(thread_num); } - - BaseCPU::activateContext(thread_num); } @@ -275,7 +273,6 @@ AtomicSimpleCPU::suspendContext(ThreadID thread_num) } } - BaseCPU::suspendContext(thread_num); } @@ -557,9 +554,9 @@ AtomicSimpleCPU::tick() if (numThreads > 1) { ContextID cid = threadContexts[curThread]->contextId(); - ifetch_req.setContext(cid); - data_read_req.setContext(cid); - data_write_req.setContext(cid); + ifetch_req.setThreadContext(cid, curThread); + data_read_req.setThreadContext(cid, curThread); + data_write_req.setThreadContext(cid, curThread); } SimpleExecContext& t_info = *threadInfo[curThread]; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 515d6b23c..43f4eb9f4 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -218,8 +218,6 @@ TimingSimpleCPU::activateContext(ThreadID thread_num) == activeThreads.end()) { activeThreads.push_back(thread_num); } - - BaseCPU::activateContext(thread_num); } @@ -245,8 +243,6 @@ TimingSimpleCPU::suspendContext(ThreadID thread_num) deschedule(fetchEvent); } } - - BaseCPU::suspendContext(thread_num); } bool @@ -423,6 +419,7 @@ TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags) Fault fault; const int asid = 0; + const ThreadID tid = curThread; const Addr pc = thread->instAddr(); unsigned block_size = cacheLineSize(); BaseTLB::Mode mode = BaseTLB::Read; @@ -430,8 +427,9 @@ TimingSimpleCPU::initiateMemRead(Addr addr, unsigned size, unsigned flags) if (traceData) traceData->setMem(addr, size, flags); - RequestPtr req = new Request(asid, addr, size, flags, dataMasterId(), pc, - thread->contextId()); + RequestPtr req = new Request(asid, addr, size, + flags, dataMasterId(), pc, + thread->contextId(), tid); req->taskId(taskId()); @@ -496,6 +494,7 @@ TimingSimpleCPU::writeMem(uint8_t *data, unsigned size, uint8_t *newData = new uint8_t[size]; const int asid = 0; + const ThreadID tid = curThread; const Addr pc = thread->instAddr(); unsigned block_size = cacheLineSize(); BaseTLB::Mode mode = BaseTLB::Write; @@ -511,8 +510,9 @@ TimingSimpleCPU::writeMem(uint8_t *data, unsigned size, if (traceData) traceData->setMem(addr, size, flags); - RequestPtr req = new Request(asid, addr, size, flags, dataMasterId(), pc, - thread->contextId()); + RequestPtr req = new Request(asid, addr, size, + flags, dataMasterId(), pc, + thread->contextId(), tid); req->taskId(taskId()); @@ -614,7 +614,7 @@ TimingSimpleCPU::fetch() _status = BaseSimpleCPU::Running; Request *ifetch_req = new Request(); ifetch_req->taskId(taskId()); - ifetch_req->setContext(thread->contextId()); + ifetch_req->setThreadContext(thread->contextId(), curThread); setupFetchRequest(ifetch_req); DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr()); thread->itb->translateTiming(ifetch_req, thread->getTC(), diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index c2c721bcf..223532088 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -245,7 +245,7 @@ MemTest::tick() bool do_functional = (random_mt.random(0, 100) < percentFunctional) && !uncacheable; Request *req = new Request(paddr, 1, flags, masterId); - req->setContext(id); + req->setThreadContext(id, 0); outstandingAddrs.insert(paddr); diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc index 6ad26077c..79a563f28 100644 --- a/src/cpu/testers/networktest/networktest.cc +++ b/src/cpu/testers/networktest/networktest.cc @@ -243,7 +243,7 @@ NetworkTest::generatePkt() // generate packet for virtual network 1 requestType = MemCmd::ReadReq; flags.set(Request::INST_FETCH); - req = new Request(0, 0x0, access_size, flags, masterId, 0x0, 0); + req = new Request(0, 0x0, access_size, flags, masterId, 0x0, 0, 0); req->setPaddr(paddr); } else { // if (randomReqType == 2) // generate packet for virtual network 2 @@ -251,7 +251,7 @@ NetworkTest::generatePkt() req = new Request(paddr, access_size, flags, masterId); } - req->setContext(id); + req->setThreadContext(id,0); //No need to do functional simulation //We just do timing simulation of the network diff --git a/src/cpu/testers/rubytest/Check.cc b/src/cpu/testers/rubytest/Check.cc index c869bd728..c8e7816c3 100644 --- a/src/cpu/testers/rubytest/Check.cc +++ b/src/cpu/testers/rubytest/Check.cc @@ -107,7 +107,7 @@ Check::initiatePrefetch() // Prefetches are assumed to be 0 sized Request *req = new Request(m_address, 0, flags, m_tester_ptr->masterId(), curTick(), m_pc); - req->setContext(index); + req->setThreadContext(index, 0); PacketPtr pkt = new Packet(req, cmd); // despite the oddity of the 0 size (questionable if this should @@ -180,7 +180,7 @@ Check::initiateAction() Request *req = new Request(writeAddr, 1, flags, m_tester_ptr->masterId(), curTick(), m_pc); - req->setContext(index); + req->setThreadContext(index, 0); Packet::Command cmd; // 1 out of 8 chance, issue an atomic rather than a write @@ -245,7 +245,7 @@ Check::initiateCheck() Request *req = new Request(m_address, CHECK_SIZE, flags, m_tester_ptr->masterId(), curTick(), m_pc); - req->setContext(index); + req->setThreadContext(index, 0); PacketPtr pkt = new Packet(req, MemCmd::ReadReq); uint8_t *dataArray = new uint8_t[CHECK_SIZE]; pkt->dataDynamic(dataArray); diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index e81a79818..d6aa9aaeb 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -627,7 +627,7 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr) // Create a request and the packet containing request Request* req = new Request(node_ptr->physAddr, node_ptr->size, node_ptr->flags, masterID, node_ptr->seqNum, - ContextID(0)); + ContextID(0), ThreadID(0)); req->setPC(node_ptr->pc); // If virtual address is valid, set the asid and virtual address fields // of the request. @@ -1123,7 +1123,7 @@ TraceCPU::FixedRetryGen::send(Addr addr, unsigned size, const MemCmd& cmd, req->setPC(pc); // If this is not done it triggers assert in L1 cache for invalid contextId - req->setContext(ContextID(0)); + req->setThreadContext(ContextID(0), ThreadID(0)); // Embed it in a packet PacketPtr pkt = new Packet(req, cmd); diff --git a/src/doc/power_thermal_model.doxygen b/src/doc/power_thermal_model.doxygen deleted file mode 100644 index 8b636ab23..000000000 --- a/src/doc/power_thermal_model.doxygen +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (c) 2016 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. -# -# 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. -# -# Author: David Guillen Fandos - -/*! \page gem5PowerModel Gem5 Power & Thermal model - - \tableofcontents - - This document gives an overview of the power and thermal modelling - infrastructure in Gem5. The purpose is to give a high level view of - all the pieces involved and how they interact with each other and - the simulator. - - \section gem5_PM_CD Class overview - - Classes involved in the power model are: - - - PowerModel: Represents a power model for a hardware component. - - - PowerModelState: Represents a power model for a hardware component - in a certain power state. It is an abstract class that defines an - interface that must be implemented for each model. - - - MathExprPowerModel: Simple implementation of PowerModelState that - assumes that power can be modeled using a simple power - - Classes involved in the thermal model are: - - - ThermalModel: Contains the system thermal model logic and state. - It performs the power query and temperature update. It also enables - gem5 to query for temperature (for OS reporting). - - - ThermalDomain: Represents an entity that generates heat. It's - essentially a group of SimObjects grouped under a SubSystem component - that have its own thermal behaviour. - - - ThermalNode: Represents a node in the thermal circuital equivalent. - The node has a temperature and interacts with other nodes through - connections (thermal resistors and capacitors). - - - ThermalReference: Temperature reference for the thermal model - (essentially a thermal node with a fixed temperature), can be used - to model air or any other constant temperature domains. - - - ThermalEntity: A thermal component that connects two thermal nodes - and models a thermal impedance between them. This class is just an - abstract interface. - - - ThermalResistor: Implements ThermalEntity to model a thermal resistance - between the two nodes it connects. Thermal resistances model the - capacity of a material to transfer heat (units in K/W). - - - ThermalCapacitor. Implements ThermalEntity to model a thermal - capacitance. Thermal capacitors are used to model material's thermal - capacitance, this is, the ability to change a certain material - temperature (units in J/K). - - \section gem5_thermal Thermal model - - The thermal model works by creating a circuital equivalent of the - simulated platform. Each node in the circuit has a temperature (as - voltage equivalent) and power flows between nodes (as current in a - circuit). - - To build this equivalent temperature model the platform is required - to group the power actors (any component that has a power model) - under SubSystems and attach ThermalDomains to those subsystems. - Other components might also be created (like ThermalReferences) and - connected all together by creating thermal entities (capacitors and - resistors). - - Last step to conclude the thermal model is to create the ThermalModel - instance itself and attach all the instances used to it, so it can - properly update them at runtime. Only one thermal model instance is - supported right now and it will automatically report temperature when - appropriate (ie. platform sensor devices). - - \section gem5_power Power model - - Every ClockedObject has a power model associated. If this power model is - non-null power will be calculated at every stats dump (although it might - be possible to force power evaluation at any other point, if the power - model uses the stats, it is a good idea to keep both events in sync). - The definition of a power model is quite vague in the sense that it is - as flexible as users want it to be. The only enforced contraints so far - is the fact that a power model has several power state models, one for - each possible power state for that hardware block. When it comes to compute - power consumption the power is just the weighted average of each power model. - - A power state model is essentially an interface that allows us to define two - power functions for dynamic and static. As an example implementation a class - called MathExprPowerModel has been provided. This implementation allows the - user to define a power model as an equation involving several statistics. - There's also some automatic (or "magic") variables such as "temp", which - reports temperature. diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index 4bc75acd6..03ca3188f 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -122,7 +122,8 @@ QueuedPrefetcher::notify(const PacketPtr &pkt) pf_pkt->allocate(); if (pkt->req->hasContextId()) { - pf_req->setContext(pkt->req->contextId()); + pf_req->setThreadContext(pkt->req->contextId(), + pkt->req->threadId()); } if (tagPrefetch && pkt->req->hasPC()) { diff --git a/src/mem/request.hh b/src/mem/request.hh index 90363ea66..0d2750a16 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -257,13 +257,14 @@ class Request VALID_PC = 0x00000010, /** Whether or not the context ID is valid. */ VALID_CONTEXT_ID = 0x00000020, + VALID_THREAD_ID = 0x00000040, /** Whether or not the sc result is valid. */ VALID_EXTRA_DATA = 0x00000080, /** * These flags are *not* cleared when a Request object is reused * (assigned a new address). */ - STICKY_PRIVATE_FLAGS = VALID_CONTEXT_ID + STICKY_PRIVATE_FLAGS = VALID_CONTEXT_ID | VALID_THREAD_ID }; private: @@ -338,8 +339,10 @@ class Request * store conditional or the compare value for a CAS. */ uint64_t _extraData; - /** The context ID (for statistics, locks, and wakeups). */ + /** The context ID (for statistics, typically). */ ContextID _contextId; + /** The thread ID (id within this CPU) */ + ThreadID _threadId; /** program counter of initiating access; for tracing/debugging */ Addr _pc; @@ -360,21 +363,21 @@ class Request Request() : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(0), + _extraData(0), _contextId(0), _threadId(0), _pc(0), _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) {} Request(Addr paddr, unsigned size, Flags flags, MasterID mid, - InstSeqNum seq_num, ContextID cid) + InstSeqNum seq_num, ContextID cid, ThreadID tid) : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(0), + _extraData(0), _contextId(0), _threadId(0), _pc(0), _reqInstSeqNum(seq_num), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) { setPhys(paddr, size, flags, mid, curTick()); - setContext(cid); + setThreadContext(cid, tid); privateFlags.set(VALID_INST_SEQ_NUM); } @@ -386,7 +389,7 @@ class Request Request(Addr paddr, unsigned size, Flags flags, MasterID mid) : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(0), + _extraData(0), _contextId(0), _threadId(0), _pc(0), _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) { @@ -396,7 +399,7 @@ class Request Request(Addr paddr, unsigned size, Flags flags, MasterID mid, Tick time) : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(0), + _extraData(0), _contextId(0), _threadId(0), _pc(0), _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) { @@ -407,7 +410,7 @@ class Request Addr pc) : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(pc), + _extraData(0), _contextId(0), _threadId(0), _pc(pc), _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) { @@ -416,15 +419,15 @@ class Request } Request(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid, - Addr pc, ContextID cid) + Addr pc, ContextID cid, ThreadID tid) : _paddr(0), _size(0), _masterId(invldMasterId), _time(0), _taskId(ContextSwitchTaskId::Unknown), _asid(0), _vaddr(0), - _extraData(0), _contextId(0), _pc(0), + _extraData(0), _contextId(0), _threadId(0), _pc(0), _reqInstSeqNum(0), atomicOpFunctor(nullptr), translateDelta(0), accessDelta(0), depth(0) { setVirt(asid, vaddr, size, flags, mid, pc); - setContext(cid); + setThreadContext(cid, tid); } Request(int asid, Addr vaddr, int size, Flags flags, MasterID mid, Addr pc, @@ -432,7 +435,7 @@ class Request : atomicOpFunctor(atomic_op) { setVirt(asid, vaddr, size, flags, mid, pc); - setContext(cid); + setThreadContext(cid, tid); } ~Request() @@ -443,13 +446,14 @@ class Request } /** - * Set up Context numbers. + * Set up CPU and thread numbers. */ void - setContext(ContextID context_id) + setThreadContext(ContextID context_id, ThreadID tid) { _contextId = context_id; - privateFlags.set(VALID_CONTEXT_ID); + _threadId = tid; + privateFlags.set(VALID_CONTEXT_ID|VALID_THREAD_ID); } /** @@ -697,6 +701,14 @@ class Request return _contextId; } + /** Accessor function for thread ID. */ + ThreadID + threadId() const + { + assert(privateFlags.isSet(VALID_THREAD_ID)); + return _threadId; + } + void setPC(Addr pc) { diff --git a/src/sim/ClockedObject.py b/src/sim/ClockedObject.py index e393dc467..b933ea07a 100644 --- a/src/sim/ClockedObject.py +++ b/src/sim/ClockedObject.py @@ -66,9 +66,6 @@ class ClockedObject(SimObject): # parent's clock domain by default clk_domain = Param.ClockDomain(Parent.clk_domain, "Clock domain") - # Power model for this ClockedObject - power_model = Param.PowerModel(NULL, "Power model") - # Provide initial power state, should ideally get redefined in startup # routine default_p_state = Param.PwrState("UNDEFINED", "Default Power State") diff --git a/src/sim/SConscript b/src/sim/SConscript index 22b9ef5cd..e40c43f0c 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -70,7 +70,6 @@ Source('linear_solver.cc') Source('system.cc') Source('dvfs_handler.cc') Source('clocked_object.cc') -Source('mathexpr.cc') if env['TARGET_ISA'] != 'null': SimObject('InstTracer.py') diff --git a/src/sim/clocked_object.cc b/src/sim/clocked_object.cc index e679f03a0..9a682a4ce 100644 --- a/src/sim/clocked_object.cc +++ b/src/sim/clocked_object.cc @@ -41,17 +41,6 @@ #include "sim/clocked_object.hh" #include "base/misc.hh" -#include "sim/power/power_model.hh" - -ClockedObject::ClockedObject(const ClockedObjectParams *p) : - SimObject(p), Clocked(*p->clk_domain), - _currPwrState(p->default_p_state), - prvEvalTick(0) -{ - // Register the power_model with the object - if (p->power_model) - p->power_model->setClockedObject(this); -} void ClockedObject::serialize(CheckpointOut &cp) const diff --git a/src/sim/clocked_object.hh b/src/sim/clocked_object.hh index b88f2435d..1ba5ca617 100644 --- a/src/sim/clocked_object.hh +++ b/src/sim/clocked_object.hh @@ -236,7 +236,11 @@ class ClockedObject : public SimObject, public Clocked { public: - ClockedObject(const ClockedObjectParams *p); + ClockedObject(const ClockedObjectParams *p) + : SimObject(p), Clocked(*p->clk_domain), + _currPwrState(p->default_p_state), + prvEvalTick(0) + { } /** Parameters of ClockedObject */ typedef ClockedObjectParams Params; diff --git a/src/sim/mathexpr.cc b/src/sim/mathexpr.cc deleted file mode 100644 index 5654c80fa..000000000 --- a/src/sim/mathexpr.cc +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#include "sim/mathexpr.hh" - -#include <algorithm> -#include <regex> -#include <string> - -#include "base/misc.hh" - -MathExpr::MathExpr(std::string expr) - : ops( - std::array<OpSearch, uNeg + 1> { - OpSearch {true, bAdd, 0, '+', [] (double a, double b) { return a + b; } }, - OpSearch {true, bSub, 0, '-', [] (double a, double b) { return a - b; } }, - OpSearch {true, bMul, 1, '*', [] (double a, double b) { return a * b; } }, - OpSearch {true, bDiv, 1, '/', [] (double a, double b) { return a / b; } }, - OpSearch {false,uNeg, 2, '-', [] (double a, double b) { return -b; } }, - OpSearch {true, bPow, 3, '^', [] (double a, double b) { return std::pow(a,b); } }, - }) -{ - // Cleanup - expr.erase(remove_if(expr.begin(), expr.end(), isspace), expr.end()); - - root = MathExpr::parse(expr); - panic_if(!root, "Invalid expression\n"); -} - -/** - * This function parses a string expression into an expression tree. - * It will look for operators in priority order to recursively build the - * tree, respecting parenthesization. - * Constants can be expressed in any format accepted by std::stod, whereas - * variables are essentially [A-Za-z0-9\.$\\]+ - */ -MathExpr::Node * -MathExpr::parse(std::string expr) { - if (expr.size() == 0) - return NULL; - - // From low to high priority - int par = 0; - for (unsigned p = 0; p < MAX_PRIO; p++) { - for (int i = expr.size() - 1; i >= 0; i--) { - if (expr[i] == ')') - par++; - if (expr[i] == '(') - par--; - - if (par < 0) return NULL; - if (par > 0) continue; - - for (unsigned opt = 0; opt < ops.size(); opt++) { - if (ops[opt].priority != p) continue; - if (ops[opt].c == expr[i]) { - // Try to parse each side - Node *l = NULL; - if (ops[opt].binary) - l = parse(expr.substr(0, i)); - Node *r = parse(expr.substr(i + 1)); - if ((l && r) || (!ops[opt].binary && r)) { - // Match! - Node *n = new Node(); - n->op = ops[opt].op; - n->l = l; - n->r = r; - return n; - } - } - } - } - } - - // Remove trivial parenthesis - if (expr.size() >= 2 && expr[0] == '(' && expr[expr.size() - 1] == ')') - return parse(expr.substr(1, expr.size() - 2)); - - // Match a number - { - char *sptr; - double v = strtod(expr.c_str(), &sptr); - if (sptr != expr.c_str()) { - Node *n = new Node(); - n->op = sValue; - n->value = v; - return n; - } - } - - // Match a variable - { - bool contains_non_alpha = false; - for (auto & c: expr) - contains_non_alpha = contains_non_alpha or - !( (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '$' || c == '\\' || c == '.' || c == '_'); - - if (!contains_non_alpha) { - Node * n = new Node(); - n->op = sVariable; - n->variable = expr; - return n; - } - } - - return NULL; -} - -double -MathExpr::eval(const Node *n, EvalCallback fn) const { - if (!n) - return 0; - else if (n->op == sValue) - return n->value; - else if (n->op == sVariable) - return fn(n->variable); - - for (auto & opt : ops) - if (opt.op == n->op) - return opt.fn( eval(n->l, fn), eval(n->r, fn) ); - - panic("Invalid node!\n"); - return 0; -} - -std::string -MathExpr::toStr(Node *n, std::string prefix) const { - std::string ret; - ret += prefix + "|-- " + n->toStr() + "\n"; - if (n->r) - ret += toStr(n->r, prefix + "| "); - if (n->l) - ret += toStr(n->l, prefix + "| "); - return ret; -} - diff --git a/src/sim/mathexpr.hh b/src/sim/mathexpr.hh deleted file mode 100644 index 8f16cc851..000000000 --- a/src/sim/mathexpr.hh +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#ifndef __SIM_MATHEXPR_HH__ -#define __SIM_MATHEXPR_HH__ - -#include <algorithm> -#include <functional> -#include <string> - -class MathExpr { - public: - - MathExpr(std::string expr); - - typedef std::function<double(std::string)> EvalCallback; - - /** - * Prints an ASCII representation of the expression tree - * - * @return A string containing the ASCII representation of the expression - */ - std::string toStr() const { return toStr(root, ""); } - - /** - * Evaluates the expression - * - * @param fn A callback funcion to evaluate variables - * - * @return The value for this expression - */ - double eval(EvalCallback fn) const { return eval(root, fn); } - - private: - enum Operator { - bAdd, bSub, bMul, bDiv, bPow, uNeg, sValue, sVariable, nInvalid - }; - - // Match operators - const int MAX_PRIO = 4; - typedef double (*binOp)(double, double); - struct OpSearch { - bool binary; - Operator op; - int priority; - char c; - binOp fn; - }; - - /** Operator list */ - std::array<OpSearch, uNeg + 1> ops; - - class Node { - public: - Node() : op(nInvalid), l(0), r(0), value(0) {} - std::string toStr() const { - const char opStr[] = {'+', '-', '*', '/', '^', '-'}; - switch (op) { - case nInvalid: - return "INVALID"; - case sVariable: - return variable; - case sValue: - return std::to_string(value); - default: - return std::string(1, opStr[op]); - }; - } - - Operator op; - Node *l, *r; - double value; - std::string variable; - }; - - /** Root node */ - Node * root; - - /** Parse and create nodes from string */ - Node *parse(std::string expr); - - /** Print tree as string */ - std::string toStr(Node *n, std::string prefix) const; - - /** Eval a node */ - double eval(const Node *n, EvalCallback fn) const; -}; - -#endif - - diff --git a/src/sim/power/MathExprPowerModel.py b/src/sim/power/MathExprPowerModel.py deleted file mode 100644 index 061f7e767..000000000 --- a/src/sim/power/MathExprPowerModel.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) 2015 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. -# -# 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: David Guillen Fandos - -from m5.SimObject import SimObject -from m5.params import * -from PowerModelState import PowerModelState - -# Represents a power model for a simobj -class MathExprPowerModel(PowerModelState): - type = 'MathExprPowerModel' - cxx_header = "sim/power/mathexpr_powermodel.hh" - - # Equations for dynamic and static power - # Equations may use gem5 stats ie. "1.1*ipc + 2.3*l2_cache.overall_misses" - # It is possible to use automatic variables such as "temp" - # You may also use stat names (relative path to the simobject) - dyn = Param.String("", "Expression for the dynamic power") - st = Param.String("", "Expression for the static power") diff --git a/src/sim/power/PowerModel.py b/src/sim/power/PowerModel.py deleted file mode 100644 index 4e6d496c4..000000000 --- a/src/sim/power/PowerModel.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2015 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. -# -# 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: David Guillen Fandos - -from m5.SimObject import SimObject -from m5.params import * -from m5.proxy import Parent - -# Represents a power model for a simobj -# The model itself is also a SimObject so we can make use some -# nice features available such as Parent.any -class PowerModel(SimObject): - type = 'PowerModel' - cxx_header = "sim/power/power_model.hh" - - @classmethod - def export_methods(cls, code): - code(''' - double getDynamicPower() const; - double getStaticPower() const; -''') - - # Keep a list of every model for every power state - pm = VectorParam.PowerModelState([], "List of per-state power models.") - - # Need a reference to the system so we can query the thermal domain - # about temperature (temperature is needed for leakage calculation) - subsystem = Param.SubSystem(Parent.any, "subsystem") diff --git a/src/sim/power/PowerModelState.py b/src/sim/power/PowerModelState.py deleted file mode 100644 index 10b3141d0..000000000 --- a/src/sim/power/PowerModelState.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2015 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. -# -# 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: David Guillen Fandos - -from m5.SimObject import SimObject -from m5.params import * - -# Represents a power model for a simobj -class PowerModelState(SimObject): - type = 'PowerModelState' - cxx_header = "sim/power/power_model.hh" - abstract = True - cxx_class = 'PowerModelState' - - @classmethod - def export_methods(cls, code): - code(''' - double getDynamicPower() const; - double getStaticPower() const; -''') - - diff --git a/src/sim/power/SConscript b/src/sim/power/SConscript index 2f0eb4fc1..8ec65519c 100644 --- a/src/sim/power/SConscript +++ b/src/sim/power/SConscript @@ -30,14 +30,9 @@ Import('*') -SimObject('MathExprPowerModel.py') -SimObject('PowerModel.py') -SimObject('PowerModelState.py') SimObject('ThermalDomain.py') SimObject('ThermalModel.py') -Source('power_model.cc') -Source('mathexpr_powermodel.cc') Source('thermal_domain.cc') Source('thermal_model.cc') diff --git a/src/sim/power/mathexpr_powermodel.cc b/src/sim/power/mathexpr_powermodel.cc deleted file mode 100644 index 000bcf22d..000000000 --- a/src/sim/power/mathexpr_powermodel.cc +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#include "sim/power/mathexpr_powermodel.hh" - -#include "base/statistics.hh" -#include "params/MathExprPowerModel.hh" -#include "sim/mathexpr.hh" -#include "sim/power/thermal_model.hh" -#include "sim/sim_object.hh" - -MathExprPowerModel::MathExprPowerModel(const Params *p) - : PowerModelState(p), dyn_expr(p->dyn), st_expr(p->st) -{ - // Calculate the name of the object we belong to - std::vector<std::string> path; - tokenize(path, name(), '.', true); - // It's something like xyz.power_model.pm2 - assert(path.size() > 2); - for (unsigned i = 0; i < path.size() - 2; i++) - basename += path[i] + "."; -} - -void -MathExprPowerModel::startup() -{ - // Create a map with stats and pointers for quick access - // Has to be done here, since we need access to the statsList - for (auto & i: Stats::statsList()) - if (i->name.find(basename) == 0) - stats_map[i->name.substr(basename.size())] = i; -} - -double -MathExprPowerModel::getStatValue(const std::string &name) const -{ - using namespace Stats; - - // Automatic variables: - if (name == "temp") - return _temp; - - // Try to cast the stat, only these are supported right now - Info *info = stats_map.at(name); - - ScalarInfo *si = dynamic_cast<ScalarInfo*>(info); - if (si) - return si->value(); - FormulaInfo *fi = dynamic_cast<FormulaInfo*>(info); - if (fi) - return fi->total(); - - panic("Unknown stat type!\n"); -} - -void -MathExprPowerModel::regStats() -{ - PowerModelState::regStats(); -} - -MathExprPowerModel* -MathExprPowerModelParams::create() -{ - return new MathExprPowerModel(this); -} diff --git a/src/sim/power/mathexpr_powermodel.hh b/src/sim/power/mathexpr_powermodel.hh deleted file mode 100644 index 43584fbd8..000000000 --- a/src/sim/power/mathexpr_powermodel.hh +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#ifndef __SIM_MATHEXPR_POWERMODEL_PM_HH__ -#define __SIM_MATHEXPR_POWERMODEL_PM_HH__ - -#include <unordered_map> - -#include "base/statistics.hh" -#include "params/MathExprPowerModel.hh" -#include "sim/mathexpr.hh" -#include "sim/power/power_model.hh" -#include "sim/sim_object.hh" - -/** - * A Equation power model. The power is represented as a combination - * of some stats and automatic variables (like temperature). - */ -class MathExprPowerModel : public PowerModelState -{ - public: - - typedef MathExprPowerModelParams Params; - MathExprPowerModel(const Params *p); - - /** - * Get the dynamic power consumption. - * - * @return Power (Watts) consumed by this object (dynamic component) - */ - double getDynamicPower() const { - return dyn_expr.eval( - std::bind(&MathExprPowerModel::getStatValue, - this, std::placeholders::_1) - ); - } - - /** - * Get the static power consumption. - * - * @return Power (Watts) consumed by this object (static component) - */ - double getStaticPower() const { - return st_expr.eval( - std::bind(&MathExprPowerModel::getStatValue, - this, std::placeholders::_1) - ); - } - - /** - * Get the value for a variable (maps to a stat) - * - * @param name Name of the variable to retrieve the value from - * - * @return Power (Watts) consumed by this object (static component) - */ - double getStatValue(const std::string & name) const; - - void startup(); - - void regStats(); - - private: - - // Math expressions for dynamic and static power - MathExpr dyn_expr, st_expr; - - // Basename of the object in the gem5 stats hierachy - std::string basename; - - // Map that contains relevant stats for this power model - std::unordered_map<std::string, Stats::Info*> stats_map; -}; - -#endif diff --git a/src/sim/power/power_model.cc b/src/sim/power/power_model.cc deleted file mode 100644 index d01084b34..000000000 --- a/src/sim/power/power_model.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#include "sim/power/power_model.hh" - -#include "base/statistics.hh" -#include "params/PowerModel.hh" -#include "params/PowerModelState.hh" -#include "sim/sim_object.hh" -#include "sim/sub_system.hh" - -PowerModelState::PowerModelState(const Params *p) - : SimObject(p), _temp(0), clocked_object(NULL) -{ -} - -PowerModel::PowerModel(const Params *p) - : SimObject(p), states_pm(p->pm), subsystem(p->subsystem), - clocked_object(NULL) -{ - panic_if(subsystem == NULL, - "Subsystem is NULL! This is not acceptable for a PowerModel!\n"); - subsystem->registerPowerProducer(this); -} - -void -PowerModel::setClockedObject(ClockedObject * clkobj) -{ - this->clocked_object = clkobj; - - for (auto & pms: states_pm) - pms->setClockedObject(clkobj); -} - -void -PowerModel::thermalUpdateCallback(const double & temp) -{ - for (auto & pms: states_pm) - pms->setTemperature(temp); -} - -void -PowerModel::regProbePoints() -{ - thermalListener.reset(new ThermalProbeListener ( - *this, this->subsystem->getProbeManager(), "thermalUpdate" - )); -} - -PowerModel* -PowerModelParams::create() -{ - return new PowerModel(this); -} - -double -PowerModel::getDynamicPower() const -{ - assert(clocked_object); - - std::vector<double> w = clocked_object->pwrStateWeights(); - - // Same number of states (excluding UNDEFINED) - assert(w.size() - 1 == states_pm.size()); - - // Make sure we have no UNDEFINED state - warn_if(w[Enums::PwrState::UNDEFINED] > 0, - "SimObject in UNDEFINED power state! Power figures might be wrong!\n"); - - double power = 0; - for (unsigned i = 0; i < states_pm.size(); i++) - if (w[i + 1] > 0.0f) - power += states_pm[i]->getDynamicPower() * w[i + 1]; - - return power; -} - -double -PowerModel::getStaticPower() const -{ - assert(clocked_object); - - std::vector<double> w = clocked_object->pwrStateWeights(); - - // Same number of states (excluding UNDEFINED) - assert(w.size() - 1 == states_pm.size()); - - // Make sure we have no UNDEFINED state - if (w[0] > 0) - warn("SimObject in UNDEFINED power state! " - "Power figures might be wrong!\n"); - - // We have N+1 states, being state #0 the default 'UNDEFINED' state - double power = 0; - for (unsigned i = 0; i < states_pm.size(); i++) - // Don't evaluate power if the object hasn't been in that state - // This fixes issues with NaNs and similar. - if (w[i + 1] > 0.0f) - power += states_pm[i]->getStaticPower() * w[i + 1]; - - return power; -} diff --git a/src/sim/power/power_model.hh b/src/sim/power/power_model.hh deleted file mode 100644 index f907597b4..000000000 --- a/src/sim/power/power_model.hh +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2015 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. - * - * 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: David Guillen Fandos - */ - -#ifndef __SIM_POWER_POWER_MODEL_HH__ -#define __SIM_POWER_POWER_MODEL_HH__ - -#include "base/statistics.hh" -#include "params/PowerModel.hh" -#include "params/PowerModelState.hh" -#include "sim/power/thermal_model.hh" -#include "sim/probe/probe.hh" -#include "sim/sim_object.hh" - -/** - * A PowerModelState is an abstract class used as interface to get power - * figures out of SimObjects - */ -class PowerModelState : public SimObject -{ - public: - - typedef PowerModelStateParams Params; - PowerModelState(const Params *p); - - /** - * Get the dynamic power consumption. - * - * @return Power (Watts) consumed by this object (dynamic component) - */ - virtual double getDynamicPower() const = 0; - - /** - * Get the static power consumption. - * - * @return Power (Watts) consumed by this object (static component) - */ - virtual double getStaticPower() const = 0; - - /** - * Temperature update. - * - * @param temp Current temperature of the HW part (Celsius) - */ - virtual void setTemperature(double temp) { _temp = temp; } - - void setClockedObject(ClockedObject * clkobj) { - clocked_object = clkobj; - } - - void regStats() { - dynamicPower - .method(this, &PowerModelState::getDynamicPower) - .name(params()->name + ".dynamic_power") - .desc("Dynamic power for this object (Watts)") - ; - - staticPower - .method(this, &PowerModelState::getStaticPower) - .name(params()->name + ".static_power") - .desc("Static power for this object (Watts)") - ; - } - - protected: - Stats::Value dynamicPower, staticPower; - - /** Current temperature */ - double _temp; - - /** The clocked object we belong to */ - ClockedObject * clocked_object; -}; - -/** - * A PowerModel is a class containing a power model for a SimObject. - * The PM describes the power consumption for every power state. - */ -class PowerModel : public SimObject -{ - public: - - typedef PowerModelParams Params; - PowerModel(const Params *p); - - /** - * Get the dynamic power consumption. - * - * @return Power (Watts) consumed by this object (dynamic component) - */ - double getDynamicPower() const; - - /** - * Get the static power consumption. - * - * @return Power (Watts) consumed by this object (static component) - */ - double getStaticPower() const; - - void regStats() { - dynamicPower - .method(this, &PowerModel::getDynamicPower) - .name(params()->name + ".dynamic_power") - .desc("Dynamic power for this power state") - ; - - staticPower - .method(this, &PowerModel::getStaticPower) - .name(params()->name + ".static_power") - .desc("Static power for this power state") - ; - } - - void setClockedObject(ClockedObject *clkobj); - - virtual void regProbePoints(); - - void thermalUpdateCallback(const double & temp); - - protected: - /** Listener class to catch thermal events */ - class ThermalProbeListener : public ProbeListenerArgBase<double> - { - public: - ThermalProbeListener(PowerModel &_pm, ProbeManager *pm, - const std::string &name) - : ProbeListenerArgBase(pm, name), pm(_pm) {} - - void notify(const double &temp) - { - pm.thermalUpdateCallback(temp); - } - - protected: - PowerModel ± - }; - - Stats::Value dynamicPower, staticPower; - - /** Actual power models (one per power state) */ - std::vector<PowerModelState*> states_pm; - - /** Listener to catch temperature changes in the SubSystem */ - std::unique_ptr<ThermalProbeListener> thermalListener; - - /** The subsystem this power model belongs to */ - SubSystem * subsystem; - - /** The clocked object we belong to */ - ClockedObject * clocked_object; -}; - -#endif diff --git a/src/sim/power/thermal_domain.cc b/src/sim/power/thermal_domain.cc index 62a0c23f8..4b840670d 100644 --- a/src/sim/power/thermal_domain.cc +++ b/src/sim/power/thermal_domain.cc @@ -108,8 +108,7 @@ LinearEquation ThermalDomain::getEquation(ThermalNode * tn, unsigned n, double step) const { LinearEquation eq(n); - double power = subsystem->getDynamicPower() + subsystem->getStaticPower(); if (tn == node) - eq[eq.cnt()] = power; + eq[eq.cnt()] = 1.75f; // Fake 1.75 Watts for now, to be changed to PM return eq; } diff --git a/src/sim/sub_system.cc b/src/sim/sub_system.cc index f5c0cc3f8..771590cf7 100644 --- a/src/sim/sub_system.cc +++ b/src/sim/sub_system.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 ARM Limited + * Copyright (c) 2014 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -37,11 +37,8 @@ * Authors: Geoffrey Blake */ -#include "sim/sub_system.hh" - #include "params/SubSystem.hh" #include "sim/sub_system.hh" -#include "sim/power/power_model.hh" #include "sim/power/thermal_domain.hh" SubSystem::SubSystem(const Params *p) @@ -52,24 +49,6 @@ SubSystem::SubSystem(const Params *p) p->thermal_domain->setSubSystem(this); } -double -SubSystem::getDynamicPower() const -{ - double ret = 0.0f; - for (auto &obj: powerProducers) - ret += obj->getDynamicPower(); - return ret; -} - -double -SubSystem::getStaticPower() const -{ - double ret = 0.0f; - for (auto &obj: powerProducers) - ret += obj->getStaticPower(); - return ret; -} - SubSystem * SubSystemParams::create() { diff --git a/src/sim/sub_system.hh b/src/sim/sub_system.hh index ec25d7056..6e35be676 100644 --- a/src/sim/sub_system.hh +++ b/src/sim/sub_system.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 ARM Limited + * Copyright (c) 2014 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -45,14 +45,10 @@ #ifndef __SIM_SUB_SYSTEM_HH__ #define __SIM_SUB_SYSTEM_HH__ -#include <vector> - #include "params/SubSystem.hh" #include "sim/power/thermal_domain.hh" #include "sim/sim_object.hh" -class PowerModel; - /** * The SubSystem simobject does nothing, it is just a container for * other simobjects used by the configuration system @@ -62,17 +58,6 @@ class SubSystem : public SimObject public: typedef SubSystemParams Params; SubSystem(const Params *p); - - double getDynamicPower() const; - - double getStaticPower() const; - - void registerPowerProducer(PowerModel *pm) { - powerProducers.push_back(pm); - } - - protected: - std::vector<PowerModel*> powerProducers; }; #endif |