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:
Andreas Sandberg 2016-04-06 19:43:31 +01:00
parent 8615b27174
commit be28d96510
57 changed files with 221 additions and 1849 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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()
{

View file

@ -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

View file

@ -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());

View file

@ -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);

View file

@ -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());

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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>

View file

@ -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());

View file

@ -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);
}

View file

@ -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

View file

@ -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)
{
}

View file

@ -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();

View file

@ -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'

View file

@ -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')

View file

@ -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*

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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);

View file

@ -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__

View file

@ -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);
}

View file

@ -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__

View file

@ -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;

View file

@ -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. */

View file

@ -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];

View file

@ -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(),

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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.

View file

@ -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()) {

View file

@ -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)
{

View file

@ -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")

View file

@ -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')

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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")

View file

@ -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")

View file

@ -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;
''')

View file

@ -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')

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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 &pm;
};
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

View file

@ -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;
}

View file

@ -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()
{

View file

@ -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