Sampler updates.
cpu/ozone/cpu.hh:
Updates for sampler.
cpu/ozone/cpu_impl.hh:
Updates for sampler, checker.
cpu/ozone/inorder_back_end.hh:
Sampler updates. Also support old memory system.
--HG--
extra : convert_revision : 33ebe38e4c08d49c6af84032b819533b784b4fe8
This commit is contained in:
@@ -64,6 +64,7 @@ class Process;
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
class Checkpoint;
|
||||
class EndQuiesceEvent;
|
||||
class MemInterface;
|
||||
|
||||
namespace Trace {
|
||||
@@ -149,7 +150,7 @@ class OzoneCPU : public BaseCPU
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Event *getQuiesceEvent();
|
||||
EndQuiesceEvent *getQuiesceEvent();
|
||||
|
||||
Tick readLastActivate();
|
||||
Tick readLastSuspend();
|
||||
@@ -330,8 +331,13 @@ class OzoneCPU : public BaseCPU
|
||||
int cpuId;
|
||||
|
||||
void switchOut(Sampler *sampler);
|
||||
void signalSwitched();
|
||||
void takeOverFrom(BaseCPU *oldCPU);
|
||||
|
||||
Sampler *sampler;
|
||||
|
||||
int switchCount;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
Addr dbg_vtophys(Addr addr);
|
||||
|
||||
|
||||
@@ -329,15 +329,30 @@ OzoneCPU<Impl>::copyToXC()
|
||||
*/
|
||||
template <class Impl>
|
||||
void
|
||||
OzoneCPU<Impl>::switchOut(Sampler *sampler)
|
||||
OzoneCPU<Impl>::switchOut(Sampler *_sampler)
|
||||
{
|
||||
sampler = _sampler;
|
||||
switchCount = 0;
|
||||
// Front end needs state from back end, so switch out the back end first.
|
||||
backEnd->switchOut();
|
||||
frontEnd->switchOut();
|
||||
_status = SwitchedOut;
|
||||
if (tickEvent.scheduled())
|
||||
tickEvent.squash();
|
||||
sampler->signalSwitched();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
OzoneCPU<Impl>::signalSwitched()
|
||||
{
|
||||
if (++switchCount == 2) {
|
||||
backEnd->doSwitchOut();
|
||||
frontEnd->doSwitchOut();
|
||||
if (checker)
|
||||
checker->switchOut(sampler);
|
||||
_status = SwitchedOut;
|
||||
if (tickEvent.scheduled())
|
||||
tickEvent.squash();
|
||||
sampler->signalSwitched();
|
||||
}
|
||||
assert(switchCount <= 2);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
@@ -366,6 +381,11 @@ OzoneCPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||
tickEvent.schedule(curTick);
|
||||
}
|
||||
}
|
||||
// Nothing running, change status to reflect that we're no longer
|
||||
// switched out.
|
||||
if (_status == SwitchedOut) {
|
||||
_status = Idle;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
@@ -666,83 +686,6 @@ OzoneCPU<Impl>::tick()
|
||||
thread.renameTable[ZeroReg+TheISA::FP_Base_DepTag]->
|
||||
setDoubleResult(0.0);
|
||||
|
||||
// General code flow:
|
||||
// Check for any interrupts. Handle them if I do have one.
|
||||
// Check if I have a need to fetch a new cache block. Either a bit could be
|
||||
// set by functions indicating that I need to fetch a new block, or I could
|
||||
// hang onto the last PC of the last cache block I fetched and compare the
|
||||
// current PC to that. Setting a bit seems nicer but may be more error
|
||||
// prone.
|
||||
// Scan through the IQ to figure out if there's anything I can issue/execute
|
||||
// Might need something close to the FU Pools to tell what instructions
|
||||
// I can issue. How to handle loads and stores vs other insts?
|
||||
// Extremely slow way: find first inst that can possibly issue; if it's a
|
||||
// load or a store, then iterate through load/store queue.
|
||||
// If I can't find instructions to execute and I've got room in the IQ
|
||||
// (which is just a counter), then grab a few instructions out of the cache
|
||||
// line buffer until I either run out or can execute up until my limit.
|
||||
|
||||
numCycles++;
|
||||
|
||||
traceData = NULL;
|
||||
|
||||
// Fault fault = NoFault;
|
||||
|
||||
#if 0 // FULL_SYSTEM
|
||||
if (checkInterrupts && check_interrupts() && !inPalMode() &&
|
||||
status() != IcacheMissComplete) {
|
||||
int ipl = 0;
|
||||
int summary = 0;
|
||||
checkInterrupts = false;
|
||||
|
||||
if (readMiscReg(IPR_SIRR)) {
|
||||
for (int i = INTLEVEL_SOFTWARE_MIN;
|
||||
i < INTLEVEL_SOFTWARE_MAX; i++) {
|
||||
if (readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
|
||||
// See table 4-19 of 21164 hardware reference
|
||||
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
|
||||
summary |= (ULL(1) << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Is this method so that if the interrupts are switched over from
|
||||
// another CPU they'll still be handled?
|
||||
// uint64_t interrupts = cpuXC->cpu->intr_status();
|
||||
uint64_t interrupts = intr_status();
|
||||
for (int i = INTLEVEL_EXTERNAL_MIN;
|
||||
i < INTLEVEL_EXTERNAL_MAX; i++) {
|
||||
if (interrupts & (ULL(1) << i)) {
|
||||
// See table 4-19 of 21164 hardware reference
|
||||
ipl = i;
|
||||
summary |= (ULL(1) << i);
|
||||
}
|
||||
}
|
||||
|
||||
if (readMiscReg(IPR_ASTRR))
|
||||
panic("asynchronous traps not implemented\n");
|
||||
|
||||
if (ipl && ipl > readMiscReg(IPR_IPLR)) {
|
||||
setMiscReg(IPR_ISR, summary);
|
||||
setMiscReg(IPR_INTID, ipl);
|
||||
|
||||
Fault(new InterruptFault)->invoke(xc);
|
||||
|
||||
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
|
||||
readMiscReg(IPR_IPLR), ipl, summary);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make call to ISA to ensure 0 register semantics...actually because the
|
||||
// DynInsts will generally be the register file, this should only have to
|
||||
// happen when the xc is actually written to (during a syscall or something)
|
||||
// maintain $r0 semantics
|
||||
// assert(renameTable[ZeroReg]->readIntResult() == 0);
|
||||
#ifdef TARGET_ALPHA
|
||||
// assert(renameTable[ZeroReg]->readDoubleResult() == 0);
|
||||
#endif // TARGET_ALPHA
|
||||
|
||||
comm.advance();
|
||||
frontEnd->tick();
|
||||
backEnd->tick();
|
||||
@@ -876,8 +819,8 @@ OzoneCPU<Impl>::processInterrupts()
|
||||
thread.setMiscReg(IPR_INTID, ipl);
|
||||
// @todo: Make this more transparent
|
||||
if (checker) {
|
||||
checkerXC->setMiscReg(IPR_ISR, summary);
|
||||
checkerXC->setMiscReg(IPR_INTID, ipl);
|
||||
checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
|
||||
checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
|
||||
}
|
||||
Fault fault = new InterruptFault;
|
||||
fault->invoke(thread.getXCProxy());
|
||||
@@ -993,6 +936,15 @@ OzoneCPU<Impl>::OzoneXC::takeOverFrom(ExecContext *old_context)
|
||||
setFuncExeInst(old_context->readFuncExeInst());
|
||||
#endif
|
||||
|
||||
EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
|
||||
if (other_quiesce) {
|
||||
// Point the quiesce event's XC at this XC so that it wakes up
|
||||
// the proper CPU.
|
||||
other_quiesce->xc = this;
|
||||
}
|
||||
if (thread->quiesceEvent) {
|
||||
thread->quiesceEvent->xc = this;
|
||||
}
|
||||
// storeCondFailures = 0;
|
||||
cpu->lockFlag = false;
|
||||
|
||||
@@ -1016,7 +968,7 @@ OzoneCPU<Impl>::OzoneXC::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
|
||||
#if FULL_SYSTEM
|
||||
template <class Impl>
|
||||
Event *
|
||||
EndQuiesceEvent *
|
||||
OzoneCPU<Impl>::OzoneXC::getQuiesceEvent()
|
||||
{
|
||||
return thread->quiesceEvent;
|
||||
|
||||
@@ -68,6 +68,8 @@ class FrontEnd
|
||||
|
||||
void switchOut();
|
||||
|
||||
void doSwitchOut();
|
||||
|
||||
void takeOverFrom(ExecContext *old_xc = NULL);
|
||||
|
||||
bool isSwitchedOut() { return switchedOut; }
|
||||
|
||||
@@ -240,6 +240,9 @@ template <class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::tick()
|
||||
{
|
||||
if (switchedOut)
|
||||
return;
|
||||
|
||||
// @todo: Maybe I want to just have direct communication...
|
||||
if (fromCommit->doneSeqNum) {
|
||||
branchPred.update(fromCommit->doneSeqNum, 0);
|
||||
@@ -828,6 +831,13 @@ void
|
||||
FrontEnd<Impl>::switchOut()
|
||||
{
|
||||
switchedOut = true;
|
||||
cpu->signalSwitched();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::doSwitchOut()
|
||||
{
|
||||
memReq = NULL;
|
||||
squash(0, 0);
|
||||
instBuffer.clear();
|
||||
|
||||
@@ -97,6 +97,10 @@ class InorderBackEnd
|
||||
|
||||
Addr commitPC;
|
||||
|
||||
void switchOut() { panic("Not implemented!"); }
|
||||
void doSwitchOut() { panic("Not implemented!"); }
|
||||
void takeOverFrom(ExecContext *old_xc = NULL) { panic("Not implemented!"); }
|
||||
|
||||
public:
|
||||
FullCPU *cpu;
|
||||
|
||||
@@ -330,14 +334,17 @@ InorderBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
|
||||
|
||||
// translate to physical address
|
||||
// Fault fault = cpu->translateDataReadReq(req);
|
||||
req->cmd = Read;
|
||||
req->completionEvent = NULL;
|
||||
req->time = curTick;
|
||||
assert(!req->data);
|
||||
req->data = new uint8_t[64];
|
||||
req->flags &= ~INST_READ;
|
||||
Fault fault = cpu->read(req, data);
|
||||
memcpy(req->data, &data, sizeof(T));
|
||||
|
||||
// if we have a cache, do cache access too
|
||||
if (dcacheInterface) {
|
||||
req->cmd = Read;
|
||||
req->completionEvent = NULL;
|
||||
req->data = new uint8_t[64];
|
||||
req->time = curTick;
|
||||
req->flags &= ~INST_READ;
|
||||
MemAccessResult result = dcacheInterface->access(req);
|
||||
|
||||
// Ugly hack to get an event scheduled *only* if the access is
|
||||
@@ -372,6 +379,30 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
|
||||
// translate to physical address
|
||||
// Fault fault = cpu->translateDataWriteReq(req);
|
||||
|
||||
req->cmd = Write;
|
||||
req->completionEvent = NULL;
|
||||
req->time = curTick;
|
||||
assert(!req->data);
|
||||
req->data = new uint8_t[64];
|
||||
memcpy(req->data, (uint8_t *)&data, req->size);
|
||||
|
||||
switch(req->size) {
|
||||
case 1:
|
||||
cpu->write(req, (uint8_t &)data);
|
||||
break;
|
||||
case 2:
|
||||
cpu->write(req, (uint16_t &)data);
|
||||
break;
|
||||
case 4:
|
||||
cpu->write(req, (uint32_t &)data);
|
||||
break;
|
||||
case 8:
|
||||
cpu->write(req, (uint64_t &)data);
|
||||
break;
|
||||
default:
|
||||
panic("Unexpected store size!\n");
|
||||
}
|
||||
|
||||
if (dcacheInterface) {
|
||||
req->cmd = Write;
|
||||
req->data = new uint8_t[64];
|
||||
@@ -395,7 +426,7 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
@@ -404,6 +435,7 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
|
||||
req->result = 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (res && (fault == NoFault))
|
||||
*res = req->result;
|
||||
|
||||
@@ -187,7 +187,7 @@ class LWBackEnd
|
||||
void instToCommit(DynInstPtr &inst);
|
||||
|
||||
void switchOut();
|
||||
|
||||
void doSwitchOut();
|
||||
void takeOverFrom(ExecContext *old_xc = NULL);
|
||||
|
||||
bool isSwitchedOut() { return switchedOut; }
|
||||
@@ -314,6 +314,7 @@ class LWBackEnd
|
||||
bool fetchHasFault;
|
||||
|
||||
bool switchedOut;
|
||||
bool switchPending;
|
||||
|
||||
DynInstPtr memBarrier;
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ LWBackEnd<Impl>::LWBackEnd(Params *params)
|
||||
numWaitingMemOps = 0;
|
||||
waitingInsts = 0;
|
||||
switchedOut = false;
|
||||
switchPending = false;
|
||||
|
||||
// IQ.setBE(this);
|
||||
LSQ.setBE(this);
|
||||
@@ -631,6 +632,11 @@ LWBackEnd<Impl>::tick()
|
||||
{
|
||||
DPRINTF(BE, "Ticking back end\n");
|
||||
|
||||
if (switchPending && robEmpty() && !LSQ.hasStoresToWB()) {
|
||||
cpu->signalSwitched();
|
||||
return;
|
||||
}
|
||||
|
||||
ROB_count[0]+= numInsts;
|
||||
|
||||
wbCycle = 0;
|
||||
@@ -682,6 +688,7 @@ LWBackEnd<Impl>::tick()
|
||||
assert(numInsts == instList.size());
|
||||
assert(waitingInsts == waitingList.size());
|
||||
assert(numWaitingMemOps == waitingMemOps.size());
|
||||
assert(!switchedOut);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1440,12 +1447,24 @@ LWBackEnd<Impl>::fetchFault(Fault &fault)
|
||||
template <class Impl>
|
||||
void
|
||||
LWBackEnd<Impl>::switchOut()
|
||||
{
|
||||
switchPending = true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LWBackEnd<Impl>::doSwitchOut()
|
||||
{
|
||||
switchedOut = true;
|
||||
switchPending = false;
|
||||
// Need to get rid of all committed, non-speculative state and write it
|
||||
// to memory/XC. In this case this is stores that have committed and not
|
||||
// yet written back.
|
||||
assert(robEmpty());
|
||||
assert(!LSQ.hasStoresToWB());
|
||||
|
||||
LSQ.switchOut();
|
||||
|
||||
squash(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -791,6 +791,8 @@ template <class Impl>
|
||||
void
|
||||
OzoneLWLSQ<Impl>::switchOut()
|
||||
{
|
||||
// assert(loads == 0);
|
||||
assert(storesToWB == 0);
|
||||
switchedOut = true;
|
||||
SQIt sq_it = --(storeQueue.end());
|
||||
while (storesToWB > 0 &&
|
||||
@@ -810,10 +812,13 @@ OzoneLWLSQ<Impl>::switchOut()
|
||||
// Store conditionals don't complete until *after* they have written
|
||||
// back. If it's here and not yet sent to memory, then don't bother
|
||||
// as it's not part of committed state.
|
||||
if (inst->isDataPrefetch() || (*sq_it).committed ||
|
||||
(*sq_it).req->flags & LOCKED) {
|
||||
if (inst->isDataPrefetch() || (*sq_it).committed) {
|
||||
sq_it--;
|
||||
continue;
|
||||
} else if ((*sq_it).req->flags & LOCKED) {
|
||||
sq_it--;
|
||||
assert(!(*sq_it).canWB || ((*sq_it).canWB && (*sq_it).req->flags & LOCKED));
|
||||
continue;
|
||||
}
|
||||
|
||||
assert((*sq_it).req);
|
||||
|
||||
Reference in New Issue
Block a user