}
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();
// 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);
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);
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
#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"
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
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()
{
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) {}
/// 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
sreqHigh = savedSreqHigh;
} else {
req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(),
- thread->contextId());
+ thread->contextId(), threadNumber);
req->taskId(cpu->taskId());
sreqHigh = savedSreqHigh;
} else {
req = new Request(asid, addr, size, flags, masterId(), this->pc.instAddr(),
- thread->contextId());
+ thread->contextId(), threadNumber);
req->taskId(cpu->taskId());
// 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);
// 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);
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());
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
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
threads[thread_id]->activate();
wakeupOnEvent(Minor::Pipeline::CPUStageId);
pipeline->wakeupFetch();
-
- BaseCPU::activateContext(thread_id);
}
void
DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
threads[thread_id]->suspend();
-
- BaseCPU::suspendContext(thread_id);
}
void
"%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 */
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(),
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));
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 */
lastActivatedCycle = curTick();
_status = Running;
-
- BaseCPU::activateContext(tid);
}
}
}
DPRINTF(Quiesce, "Suspending Context\n");
-
- BaseCPU::suspendContext(tid);
}
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());
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());
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());
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);
}
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);
}
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
}
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.
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;
}
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;
}
void
-LocalBP::uncondBranch(ThreadID tid, Addr pc, void *&bp_history)
+LocalBP::uncondBranch(Addr pc, void *&bp_history)
{
}
*/
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
* @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
* @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();
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'
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')
BiModeBP::BiModeBP(const BiModeBPParams *params)
: BPredUnit(params),
- globalHistoryReg(params->numThreads, 0),
+ globalHistoryReg(0),
globalHistoryBits(ceilLog2(params->globalPredictorSize)),
choicePredictorSize(params->choicePredictorSize),
choiceCtrBits(params->choiceCtrBits),
* 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;
}
* 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);
bool finalPrediction;
BPHistory *history = new BPHistory;
- history->globalHistoryReg = globalHistoryReg[tid];
+ history->globalHistoryReg = globalHistoryReg;
history->takenUsed = choicePrediction;
history->takenPred = takenGHBPrediction;
history->notTakenPred = notTakenGHBPrediction;
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
* 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);
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;
}
}
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*
{
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;
// not-taken direction predictors
std::vector<SatCounter> notTakenCounters;
- std::vector<unsigned> globalHistoryReg;
+ unsigned globalHistoryReg;
unsigned globalHistoryBits;
unsigned historyRegisterMask;
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)
.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
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);
tid, pc, pc, RAS[tid].topIdx());
}
- if (inst->isDirectCtrl() || !useIndirect) {
- // Check BTB on direct branches
- if (BTB.valid(pc.instAddr(), tid)) {
- ++BTBHits;
-
- // If it's not a return, use the BTB to get target addr.
- target = BTB.lookup(pc.instAddr(), tid);
-
- DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
- " target is %s.\n", tid, pc, target);
-
- } else {
- DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
- "valid entry.\n",tid);
- pred_taken = false;
- // The Direction of the branch predictor is altered
- // because the BTB did not have an entry
- // The predictor needs to be updated accordingly
- if (!inst->isCall() && !inst->isReturn()) {
- btbUpdate(tid, pc.instAddr(), bp_history);
- DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
- " called for %s\n", tid, seqNum, pc);
- } else if (inst->isCall() && !inst->isUncondCtrl()) {
- RAS[tid].pop();
- predict_record.pushedRAS = false;
- }
- TheISA::advancePC(target, inst);
- }
+ if (BTB.valid(pc.instAddr(), tid)) {
+ ++BTBHits;
+
+ // If it's not a return, use the BTB to get the target addr.
+ target = BTB.lookup(pc.instAddr(), tid);
+
+ DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
+ " target is %s.\n", tid, pc, target);
+
} else {
- predict_record.wasIndirect = true;
- ++indirectLookups;
- //Consult indirect predictor on indirect control
- if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history),
- target, tid)) {
- // Indirect predictor hit
- ++indirectHits;
- DPRINTF(Branch, "[tid:%i]: Instruction %s predicted "
- "indirect target is %s.\n", tid, pc, target);
- } else {
- ++indirectMisses;
- pred_taken = false;
- DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect "
- "target.\n", tid, pc);
- if (!inst->isCall() && !inst->isReturn()) {
-
- } else if (inst->isCall() && !inst->isUncondCtrl()) {
- RAS[tid].pop();
- predict_record.pushedRAS = false;
- }
- TheISA::advancePC(target, inst);
+ DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
+ "valid entry.\n",tid);
+ pred_taken = false;
+ // The Direction of the branch predictor is altered because the
+ // BTB did not have an entry
+ // The predictor needs to be updated accordingly
+ if (!inst->isCall() && !inst->isReturn()) {
+ btbUpdate(pc.instAddr(), bp_history);
+ DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
+ " called for %s\n", tid, seqNum, pc);
+ } else if (inst->isCall() && !inst->isUncondCtrl()) {
+ RAS[tid].pop();
+ predict_record.pushedRAS = false;
}
- iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum,
- tid);
+ TheISA::advancePC(target, inst);
}
}
} else {
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 "
} 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,
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();
{
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) {
}
// 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,
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;
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) {
#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"
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
* @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.
* 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,
* @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.
* 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.
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:
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 {
/** Whether this instruction has already mispredicted/updated bp */
bool wasSquashed;
-
- /** Wether this instruction was an indirect branch */
- bool wasIndirect;
};
typedef std::deque<PredictorHistory> History;
/** 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. */
/** 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;
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");
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
bool
DefaultBTB::valid(Addr instPC, ThreadID tid)
{
- unsigned btb_idx = getIndex(instPC, tid);
+ unsigned btb_idx = getIndex(instPC);
Addr inst_tag = getTag(instPC);
TheISA::PCState
DefaultBTB::lookup(Addr instPC, ThreadID tid)
{
- unsigned btb_idx = getIndex(instPC, tid);
+ unsigned btb_idx = getIndex(instPC);
Addr inst_tag = getTag(instPC);
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);
* @param instShiftAmt Offset amount for instructions to ignore alignment.
*/
DefaultBTB(unsigned numEntries, unsigned tagBits,
- unsigned instShiftAmt, unsigned numThreads);
+ unsigned instShiftAmt);
void reset();
* @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.
/** Number of bits to shift PC when calculating tag. */
unsigned tagShiftAmt;
-
- /** Log2 NumThreads used for hashing threadid */
- unsigned log2NumThreads;
};
#endif // __CPU_PRED_BTB_HH__
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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__
localHistoryBits(ceilLog2(params->localPredictorSize)),
globalPredictorSize(params->globalPredictorSize),
globalCtrBits(params->globalCtrBits),
- globalHistory(params->numThreads, 0),
globalHistoryBits(
ceilLog2(params->globalPredictorSize) >
ceilLog2(params->choicePredictorSize) ?
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;
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
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;
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;
// 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;
}
}
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;
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;
}
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;
}
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) {
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;
* @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
* 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.
* @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 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:
/**
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.
/** 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. */
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)
== activeThreads.end()) {
activeThreads.push_back(thread_num);
}
-
- BaseCPU::activateContext(thread_num);
}
}
}
- BaseCPU::suspendContext(thread_num);
}
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];
== activeThreads.end()) {
activeThreads.push_back(thread_num);
}
-
- BaseCPU::activateContext(thread_num);
}
deschedule(fetchEvent);
}
}
-
- BaseCPU::suspendContext(thread_num);
}
bool
Fault fault;
const int asid = 0;
+ const ThreadID tid = curThread;
const Addr pc = thread->instAddr();
unsigned block_size = cacheLineSize();
BaseTLB::Mode mode = BaseTLB::Read;
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());
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;
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());
_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(),
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);
// 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
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
// 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
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
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);
// 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.
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);
+++ /dev/null
-# 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.
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()) {
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:
* 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;
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);
}
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)
{
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)
{
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)
{
}
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,
: atomicOpFunctor(atomic_op)
{
setVirt(asid, vaddr, size, flags, mid, pc);
- setContext(cid);
+ setThreadContext(cid, tid);
}
~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);
}
/**
return _contextId;
}
+ /** Accessor function for thread ID. */
+ ThreadID
+ threadId() const
+ {
+ assert(privateFlags.isSet(VALID_THREAD_ID));
+ return _threadId;
+ }
+
void
setPC(Addr pc)
{
# 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")
Source('system.cc')
Source('dvfs_handler.cc')
Source('clocked_object.cc')
-Source('mathexpr.cc')
if env['TARGET_ISA'] != 'null':
SimObject('InstTracer.py')
#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
: 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;
+++ /dev/null
-/*
- * 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;
-}
-
+++ /dev/null
-/*
- * 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
-
-
+++ /dev/null
-# 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")
+++ /dev/null
-# 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")
+++ /dev/null
-# 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;
-''')
-
-
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')
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 ARM Limited
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder. You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: David Guillen Fandos
- */
-
-#ifndef __SIM_POWER_POWER_MODEL_HH__
-#define __SIM_POWER_POWER_MODEL_HH__
-
-#include "base/statistics.hh"
-#include "params/PowerModel.hh"
-#include "params/PowerModelState.hh"
-#include "sim/power/thermal_model.hh"
-#include "sim/probe/probe.hh"
-#include "sim/sim_object.hh"
-
-/**
- * A PowerModelState is an abstract class used as interface to get power
- * figures out of SimObjects
- */
-class PowerModelState : public SimObject
-{
- public:
-
- typedef PowerModelStateParams Params;
- PowerModelState(const Params *p);
-
- /**
- * Get the dynamic power consumption.
- *
- * @return Power (Watts) consumed by this object (dynamic component)
- */
- virtual double getDynamicPower() const = 0;
-
- /**
- * Get the static power consumption.
- *
- * @return Power (Watts) consumed by this object (static component)
- */
- virtual double getStaticPower() const = 0;
-
- /**
- * Temperature update.
- *
- * @param temp Current temperature of the HW part (Celsius)
- */
- virtual void setTemperature(double temp) { _temp = temp; }
-
- void setClockedObject(ClockedObject * clkobj) {
- clocked_object = clkobj;
- }
-
- void regStats() {
- dynamicPower
- .method(this, &PowerModelState::getDynamicPower)
- .name(params()->name + ".dynamic_power")
- .desc("Dynamic power for this object (Watts)")
- ;
-
- staticPower
- .method(this, &PowerModelState::getStaticPower)
- .name(params()->name + ".static_power")
- .desc("Static power for this object (Watts)")
- ;
- }
-
- protected:
- Stats::Value dynamicPower, staticPower;
-
- /** Current temperature */
- double _temp;
-
- /** The clocked object we belong to */
- ClockedObject * clocked_object;
-};
-
-/**
- * A PowerModel is a class containing a power model for a SimObject.
- * The PM describes the power consumption for every power state.
- */
-class PowerModel : public SimObject
-{
- public:
-
- typedef PowerModelParams Params;
- PowerModel(const Params *p);
-
- /**
- * Get the dynamic power consumption.
- *
- * @return Power (Watts) consumed by this object (dynamic component)
- */
- double getDynamicPower() const;
-
- /**
- * Get the static power consumption.
- *
- * @return Power (Watts) consumed by this object (static component)
- */
- double getStaticPower() const;
-
- void regStats() {
- dynamicPower
- .method(this, &PowerModel::getDynamicPower)
- .name(params()->name + ".dynamic_power")
- .desc("Dynamic power for this power state")
- ;
-
- staticPower
- .method(this, &PowerModel::getStaticPower)
- .name(params()->name + ".static_power")
- .desc("Static power for this power state")
- ;
- }
-
- void setClockedObject(ClockedObject *clkobj);
-
- virtual void regProbePoints();
-
- void thermalUpdateCallback(const double & temp);
-
- protected:
- /** Listener class to catch thermal events */
- class ThermalProbeListener : public ProbeListenerArgBase<double>
- {
- public:
- ThermalProbeListener(PowerModel &_pm, ProbeManager *pm,
- const std::string &name)
- : ProbeListenerArgBase(pm, name), pm(_pm) {}
-
- void notify(const double &temp)
- {
- pm.thermalUpdateCallback(temp);
- }
-
- protected:
- PowerModel ±
- };
-
- Stats::Value dynamicPower, staticPower;
-
- /** Actual power models (one per power state) */
- std::vector<PowerModelState*> states_pm;
-
- /** Listener to catch temperature changes in the SubSystem */
- std::unique_ptr<ThermalProbeListener> thermalListener;
-
- /** The subsystem this power model belongs to */
- SubSystem * subsystem;
-
- /** The clocked object we belong to */
- ClockedObject * clocked_object;
-};
-
-#endif
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;
}
/*
- * 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
* 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)
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()
{
/*
- * 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
#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
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