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
This commit is contained in:
parent
8615b27174
commit
be28d96510
57 changed files with 221 additions and 1849 deletions
|
@ -177,7 +177,7 @@ ExtMaster::handleEvent(SST::Event* event)
|
|||
}
|
||||
|
||||
auto req = new Request(ev->getAddr(), ev->getSize(), flags, 0);
|
||||
req->setContext(ev->getGroupId());
|
||||
req->setThreadContext(ev->getGroupId(), 0);
|
||||
|
||||
auto pkt = new Packet(req, cmdO);
|
||||
pkt->allocate();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -478,27 +472,6 @@ BaseCPU::findContext(ThreadContext *tc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 (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);
|
||||
// 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);
|
||||
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);
|
||||
}
|
||||
} 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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
3
src/mem/cache/prefetch/queued.cc
vendored
3
src/mem/cache/prefetch/queued.cc
vendored
|
@ -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()) {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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")
|
|
@ -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")
|
|
@ -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;
|
||||
''')
|
||||
|
||||
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue