Updates to Ozone model for quiesce, store conditionals.
--HG-- extra : convert_revision : 72ddd75ad0b5783aca9484e7d178c2915ee8e355
This commit is contained in:
parent
676afbe2c7
commit
e704960c80
9 changed files with 272 additions and 116 deletions
122
cpu/ozone/cpu.hh
122
cpu/ozone/cpu.hh
|
@ -42,7 +42,6 @@
|
|||
#include "cpu/pc_event.hh"
|
||||
#include "cpu/static_inst.hh"
|
||||
#include "mem/mem_interface.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
// forward declarations
|
||||
|
@ -59,7 +58,6 @@ class GDBListener;
|
|||
|
||||
#else
|
||||
|
||||
class PageTable;
|
||||
class Process;
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
@ -349,9 +347,8 @@ class OzoneCPU : public BaseCPU
|
|||
// L1 data cache
|
||||
MemInterface *dcacheInterface;
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
PageTable *pTable;
|
||||
#endif
|
||||
/** Pointer to memory. */
|
||||
FunctionalMemory *mem;
|
||||
|
||||
FrontEnd *frontEnd;
|
||||
|
||||
|
@ -428,24 +425,62 @@ class OzoneCPU : public BaseCPU
|
|||
int getInstAsid() { return thread.asid; }
|
||||
int getDataAsid() { return thread.asid; }
|
||||
|
||||
Fault dummyTranslation(MemReqPtr &req)
|
||||
{
|
||||
#if 0
|
||||
assert((req->vaddr >> 48 & 0xffff) == 0);
|
||||
#endif
|
||||
|
||||
// put the asid in the upper 16 bits of the paddr
|
||||
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
|
||||
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
/** Translates instruction requestion in syscall emulation mode. */
|
||||
Fault translateInstReq(MemReqPtr &req)
|
||||
{
|
||||
return this->pTable->translate(req);
|
||||
return dummyTranslation(req);
|
||||
}
|
||||
|
||||
/** Translates data read request in syscall emulation mode. */
|
||||
Fault translateDataReadReq(MemReqPtr &req)
|
||||
{
|
||||
return this->pTable->translate(req);
|
||||
return dummyTranslation(req);
|
||||
}
|
||||
|
||||
/** Translates data write request in syscall emulation mode. */
|
||||
Fault translateDataWriteReq(MemReqPtr &req)
|
||||
{
|
||||
return this->pTable->translate(req);
|
||||
return dummyTranslation(req);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Old CPU read from memory function. No longer used. */
|
||||
template <class T>
|
||||
Fault read(MemReqPtr &req, T &data)
|
||||
{
|
||||
// panic("CPU READ NOT IMPLEMENTED W/NEW MEMORY\n");
|
||||
#if 0
|
||||
#if FULL_SYSTEM && defined(TARGET_ALPHA)
|
||||
if (req->flags & LOCKED) {
|
||||
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
|
||||
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Fault error;
|
||||
if (req->flags & LOCKED) {
|
||||
// lockAddr = req->paddr;
|
||||
lockFlag = true;
|
||||
}
|
||||
|
||||
error = this->mem->read(req, data);
|
||||
data = gtoh(data);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/** CPU read function, forwards read to LSQ. */
|
||||
template <class T>
|
||||
Fault read(MemReqPtr &req, T &data, int load_idx)
|
||||
|
@ -453,6 +488,75 @@ class OzoneCPU : public BaseCPU
|
|||
return backEnd->read(req, data, load_idx);
|
||||
}
|
||||
|
||||
/** Old CPU write to memory function. No longer used. */
|
||||
template <class T>
|
||||
Fault write(MemReqPtr &req, T &data)
|
||||
{
|
||||
#if 0
|
||||
#if FULL_SYSTEM && defined(TARGET_ALPHA)
|
||||
ExecContext *xc;
|
||||
|
||||
// If this is a store conditional, act appropriately
|
||||
if (req->flags & LOCKED) {
|
||||
xc = req->xc;
|
||||
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
req->result = 2;
|
||||
xc->setStCondFailures(0);//Needed? [RGD]
|
||||
} else {
|
||||
bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
|
||||
Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
|
||||
req->result = lock_flag;
|
||||
if (!lock_flag ||
|
||||
((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
|
||||
xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
|
||||
xc->setStCondFailures(xc->readStCondFailures() + 1);
|
||||
if (((xc->readStCondFailures()) % 100000) == 0) {
|
||||
std::cerr << "Warning: "
|
||||
<< xc->readStCondFailures()
|
||||
<< " consecutive store conditional failures "
|
||||
<< "on cpu " << req->xc->readCpuId()
|
||||
<< std::endl;
|
||||
}
|
||||
return NoFault;
|
||||
}
|
||||
else xc->setStCondFailures(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Need to clear any locked flags on other proccessors for
|
||||
// this address. Only do this for succsful Store Conditionals
|
||||
// and all other stores (WH64?). Unsuccessful Store
|
||||
// Conditionals would have returned above, and wouldn't fall
|
||||
// through.
|
||||
for (int i = 0; i < this->system->execContexts.size(); i++){
|
||||
xc = this->system->execContexts[i];
|
||||
if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
|
||||
(req->paddr & ~0xf)) {
|
||||
xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
req->result = 2;
|
||||
} else {
|
||||
if (this->lockFlag/* && this->lockAddr == req->paddr*/) {
|
||||
req->result = 1;
|
||||
} else {
|
||||
req->result = 0;
|
||||
return NoFault;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this->mem->write(req, (T)htog(data));
|
||||
}
|
||||
|
||||
/** CPU write function, forwards write to LSQ. */
|
||||
template <class T>
|
||||
Fault write(MemReqPtr &req, T &data, int store_idx)
|
||||
|
@ -507,6 +611,8 @@ class OzoneCPU : public BaseCPU
|
|||
bool stall;
|
||||
};
|
||||
TimeBuffer<CommStruct> comm;
|
||||
|
||||
bool lockFlag;
|
||||
};
|
||||
|
||||
#endif // __CPU_OZONE_CPU_HH__
|
||||
|
|
|
@ -149,12 +149,14 @@ OzoneCPU<Impl>::DCacheCompletionEvent::description()
|
|||
template <class Impl>
|
||||
OzoneCPU<Impl>::OzoneCPU(Params *p)
|
||||
#if FULL_SYSTEM
|
||||
: BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width),
|
||||
: BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width), mem(p->mem),
|
||||
#else
|
||||
: BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width),
|
||||
mem(p->workload[0]->getMemory()),
|
||||
#endif
|
||||
comm(5, 5)
|
||||
{
|
||||
|
||||
frontEnd = new FrontEnd(p);
|
||||
backEnd = new BackEnd(p);
|
||||
|
||||
|
@ -245,51 +247,7 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
|
|||
globalSeqNum = 1;
|
||||
|
||||
checkInterrupts = false;
|
||||
/*
|
||||
fetchRedirBranch = true;
|
||||
fetchRedirExcp = true;
|
||||
|
||||
// Need to initialize the rename maps, and the head and tail pointers.
|
||||
robHeadPtr = new DynInst(this);
|
||||
robTailPtr = new DynInst(this);
|
||||
|
||||
robHeadPtr->setNextInst(robTailPtr);
|
||||
// robHeadPtr->setPrevInst(NULL);
|
||||
// robTailPtr->setNextInst(NULL);
|
||||
robTailPtr->setPrevInst(robHeadPtr);
|
||||
|
||||
robHeadPtr->setCompleted();
|
||||
robTailPtr->setCompleted();
|
||||
|
||||
for (int i = 0; i < ISA::TotalNumRegs; ++i) {
|
||||
renameTable[i] = new DynInst(this);
|
||||
commitTable[i] = new DynInst(this);
|
||||
|
||||
renameTable[i]->setCompleted();
|
||||
commitTable[i]->setCompleted();
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
for (int i = 0; i < ISA::NumIntRegs; ++i) {
|
||||
palShadowTable[i] = new DynInst(this);
|
||||
palShadowTable[i]->setCompleted();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Size of cache block.
|
||||
cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
|
||||
|
||||
// Create mask to get rid of offset bits.
|
||||
cacheBlkMask = (cacheBlkSize - 1);
|
||||
|
||||
// Get the size of an instruction.
|
||||
instSize = sizeof(MachInst);
|
||||
|
||||
// Create space to store a cache line.
|
||||
cacheData = new uint8_t[cacheBlkSize];
|
||||
|
||||
cacheBlkValid = false;
|
||||
*/
|
||||
for (int i = 0; i < TheISA::TotalNumRegs; ++i) {
|
||||
thread.renameTable[i] = new DynInst(this);
|
||||
thread.renameTable[i]->setCompleted();
|
||||
|
@ -299,9 +257,11 @@ OzoneCPU<Impl>::OzoneCPU(Params *p)
|
|||
backEnd->renameTable.copyFrom(thread.renameTable);
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
pTable = p->pTable;
|
||||
// pTable = p->pTable;
|
||||
#endif
|
||||
|
||||
lockFlag = 0;
|
||||
|
||||
DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n");
|
||||
}
|
||||
|
||||
|
@ -392,6 +352,7 @@ OzoneCPU<Impl>::activateContext(int thread_num, int delay)
|
|||
scheduleTickEvent(delay);
|
||||
_status = Running;
|
||||
thread._status = ExecContext::Active;
|
||||
frontEnd->wakeFromQuiesce();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
@ -401,8 +362,8 @@ OzoneCPU<Impl>::suspendContext(int thread_num)
|
|||
// Eventually change this in SMT.
|
||||
assert(thread_num == 0);
|
||||
// assert(xcProxy);
|
||||
|
||||
assert(_status == Running);
|
||||
// @todo: Figure out how to initially set the status properly so this is running.
|
||||
// assert(_status == Running);
|
||||
notIdleFraction--;
|
||||
unscheduleTickEvent();
|
||||
_status = Idle;
|
||||
|
@ -665,6 +626,7 @@ OzoneCPU<Impl>::tick()
|
|||
{
|
||||
DPRINTF(OzoneCPU, "\n\nOzoneCPU: Ticking cpu.\n");
|
||||
|
||||
_status = Running;
|
||||
thread.renameTable[ZeroReg]->setIntResult(0);
|
||||
thread.renameTable[ZeroReg+TheISA::FP_Base_DepTag]->
|
||||
setDoubleResult(0.0);
|
||||
|
@ -756,7 +718,7 @@ OzoneCPU<Impl>::tick()
|
|||
// check for instruction-count-based events
|
||||
comInstEventQueue[0]->serviceEvents(numInst);
|
||||
|
||||
if (!tickEvent.scheduled())
|
||||
if (!tickEvent.scheduled() && _status == Running)
|
||||
tickEvent.schedule(curTick + 1);
|
||||
}
|
||||
|
||||
|
@ -821,6 +783,8 @@ OzoneCPU<Impl>::hwrei()
|
|||
|
||||
thread.setNextPC(thread.readMiscReg(AlphaISA::IPR_EXC_ADDR));
|
||||
|
||||
lockFlag = false;
|
||||
|
||||
// Not sure how to make a similar check in the Ozone model
|
||||
// if (!misspeculating()) {
|
||||
kernelStats->hwrei();
|
||||
|
|
|
@ -237,6 +237,7 @@ OzoneDynInst<Impl>::hwrei()
|
|||
this->cpu->kernelStats->hwrei();
|
||||
|
||||
this->cpu->checkInterrupts = true;
|
||||
this->cpu->lockFlag = false;
|
||||
|
||||
// FIXME: XXX check for interrupts? XXX
|
||||
return NoFault;
|
||||
|
|
|
@ -60,7 +60,7 @@ class FrontEnd
|
|||
const bool is_branch = false, const bool branch_taken = false);
|
||||
DynInstPtr getInst();
|
||||
|
||||
void processCacheCompletion();
|
||||
void processCacheCompletion(MemReqPtr &req);
|
||||
|
||||
void addFreeRegs(int num_freed);
|
||||
|
||||
|
@ -109,6 +109,7 @@ class FrontEnd
|
|||
SerializeBlocked,
|
||||
SerializeComplete,
|
||||
RenameBlocked,
|
||||
QuiescePending,
|
||||
BEBlocked
|
||||
};
|
||||
|
||||
|
@ -130,17 +131,16 @@ class FrontEnd
|
|||
class ICacheCompletionEvent : public Event
|
||||
{
|
||||
private:
|
||||
MemReqPtr req;
|
||||
FrontEnd *frontEnd;
|
||||
|
||||
public:
|
||||
ICacheCompletionEvent(FrontEnd *_fe);
|
||||
ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *_fe);
|
||||
|
||||
virtual void process();
|
||||
virtual const char *description();
|
||||
};
|
||||
|
||||
ICacheCompletionEvent cacheCompletionEvent;
|
||||
|
||||
MemInterface *icacheInterface;
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
@ -174,6 +174,8 @@ class FrontEnd
|
|||
void setPC(Addr val) { PC = val; }
|
||||
void setNextPC(Addr val) { nextPC = val; }
|
||||
|
||||
void wakeFromQuiesce();
|
||||
|
||||
void dumpInsts();
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include "arch/faults.hh"
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "cpu/exec_context.hh"
|
||||
|
@ -12,7 +13,6 @@ using namespace TheISA;
|
|||
template <class Impl>
|
||||
FrontEnd<Impl>::FrontEnd(Params *params)
|
||||
: branchPred(params),
|
||||
cacheCompletionEvent(this),
|
||||
icacheInterface(params->icacheInterface),
|
||||
instBufferSize(0),
|
||||
maxInstBufferSize(params->maxInstBufferSize),
|
||||
|
@ -26,10 +26,12 @@ FrontEnd<Impl>::FrontEnd(Params *params)
|
|||
// Setup branch predictor.
|
||||
|
||||
// Setup Memory Request
|
||||
/*
|
||||
memReq = new MemReq();
|
||||
memReq->asid = 0;
|
||||
memReq->data = new uint8_t[64];
|
||||
|
||||
*/
|
||||
memReq = NULL;
|
||||
// Size of cache block.
|
||||
cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
|
||||
|
||||
|
@ -46,7 +48,7 @@ FrontEnd<Impl>::FrontEnd(Params *params)
|
|||
cacheBlkValid = false;
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
pTable = params->pTable;
|
||||
// pTable = params->pTable;
|
||||
#endif
|
||||
fetchFault = NoFault;
|
||||
}
|
||||
|
@ -72,7 +74,7 @@ void
|
|||
FrontEnd<Impl>::setXC(ExecContext *xc_ptr)
|
||||
{
|
||||
xc = xc_ptr;
|
||||
memReq->xc = xc;
|
||||
// memReq->xc = xc;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
@ -269,6 +271,9 @@ FrontEnd<Impl>::tick()
|
|||
}
|
||||
updateStatus();
|
||||
return;
|
||||
} else if (status == QuiescePending) {
|
||||
DPRINTF(FE, "Waiting for quiesce to execute or get squashed.\n");
|
||||
return;
|
||||
} else if (status != IcacheMissComplete) {
|
||||
if (fetchCacheLineNextCycle) {
|
||||
Fault fault = fetchCacheLine();
|
||||
|
@ -325,6 +330,14 @@ FrontEnd<Impl>::tick()
|
|||
// rename(num_inst);
|
||||
// }
|
||||
|
||||
#if FULL_SYSTEM
|
||||
if (inst->isQuiesce()) {
|
||||
warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
|
||||
status = QuiescePending;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inst->predTaken()) {
|
||||
// Start over with tick?
|
||||
break;
|
||||
|
@ -364,6 +377,12 @@ FrontEnd<Impl>::fetchCacheLine()
|
|||
|
||||
// Setup the memReq to do a read of the first isntruction's address.
|
||||
// Set the appropriate read size and flags as well.
|
||||
memReq = new MemReq();
|
||||
|
||||
memReq->asid = 0;
|
||||
memReq->thread_num = 0;
|
||||
memReq->data = new uint8_t[64];
|
||||
memReq->xc = xc;
|
||||
memReq->cmd = Read;
|
||||
memReq->reset(fetch_PC, cacheBlkSize, flags);
|
||||
|
||||
|
@ -377,16 +396,26 @@ FrontEnd<Impl>::fetchCacheLine()
|
|||
// Now do the timing access to see whether or not the instruction
|
||||
// exists within the cache.
|
||||
if (icacheInterface && fault == NoFault) {
|
||||
#if FULL_SYSTEM
|
||||
if (cpu->system->memctrl->badaddr(memReq->paddr)) {
|
||||
DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
|
||||
"misspeculating path!",
|
||||
memReq->paddr);
|
||||
return TheISA::genMachineCheckFault();
|
||||
}
|
||||
#endif
|
||||
|
||||
memReq->completionEvent = NULL;
|
||||
|
||||
memReq->time = curTick;
|
||||
fault = cpu->mem->read(memReq, cacheData);
|
||||
|
||||
MemAccessResult res = icacheInterface->access(memReq);
|
||||
|
||||
// If the cache missed then schedule an event to wake
|
||||
// up this stage once the cache miss completes.
|
||||
if (icacheInterface->doEvents() && res != MA_HIT) {
|
||||
memReq->completionEvent = new ICacheCompletionEvent(this);
|
||||
memReq->completionEvent = new ICacheCompletionEvent(memReq, this);
|
||||
|
||||
status = IcacheMissStall;
|
||||
|
||||
|
@ -398,7 +427,7 @@ FrontEnd<Impl>::fetchCacheLine()
|
|||
|
||||
cacheBlkValid = true;
|
||||
|
||||
memcpy(cacheData, memReq->data, memReq->size);
|
||||
// memcpy(cacheData, memReq->data, memReq->size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +570,8 @@ FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC,
|
|||
// Clear the icache miss if it's outstanding.
|
||||
if (status == IcacheMissStall && icacheInterface) {
|
||||
DPRINTF(FE, "Squashing outstanding Icache miss.\n");
|
||||
icacheInterface->squash(0);
|
||||
// icacheInterface->squash(0);
|
||||
memReq = NULL;
|
||||
}
|
||||
|
||||
if (status == SerializeBlocked) {
|
||||
|
@ -577,12 +607,13 @@ FrontEnd<Impl>::getInst()
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::processCacheCompletion()
|
||||
FrontEnd<Impl>::processCacheCompletion(MemReqPtr &req)
|
||||
{
|
||||
DPRINTF(FE, "Processing cache completion\n");
|
||||
|
||||
// Do something here.
|
||||
if (status != IcacheMissStall) {
|
||||
if (status != IcacheMissStall ||
|
||||
req != memReq) {
|
||||
DPRINTF(FE, "Previous fetch was squashed.\n");
|
||||
return;
|
||||
}
|
||||
|
@ -595,10 +626,11 @@ FrontEnd<Impl>::processCacheCompletion()
|
|||
fetchStatus[tid] = IcacheMissComplete;
|
||||
}
|
||||
*/
|
||||
memcpy(cacheData, memReq->data, memReq->size);
|
||||
// memcpy(cacheData, memReq->data, memReq->size);
|
||||
|
||||
// Reset the completion event to NULL.
|
||||
memReq->completionEvent = NULL;
|
||||
// memReq->completionEvent = NULL;
|
||||
memReq = NULL;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
@ -766,6 +798,15 @@ FrontEnd<Impl>::renameInst(DynInstPtr &inst)
|
|||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::wakeFromQuiesce()
|
||||
{
|
||||
DPRINTF(FE, "Waking up from quiesce\n");
|
||||
// Hopefully this is safe
|
||||
status = Running;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::dumpInsts()
|
||||
|
@ -786,8 +827,8 @@ FrontEnd<Impl>::dumpInsts()
|
|||
}
|
||||
|
||||
template <class Impl>
|
||||
FrontEnd<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(FrontEnd *fe)
|
||||
: Event(&mainEventQueue, Delayed_Writeback_Pri), frontEnd(fe)
|
||||
FrontEnd<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *fe)
|
||||
: Event(&mainEventQueue, Delayed_Writeback_Pri), req(_req), frontEnd(fe)
|
||||
{
|
||||
this->setFlags(Event::AutoDelete);
|
||||
}
|
||||
|
@ -796,7 +837,7 @@ template <class Impl>
|
|||
void
|
||||
FrontEnd<Impl>::ICacheCompletionEvent::process()
|
||||
{
|
||||
frontEnd->processCacheCompletion();
|
||||
frontEnd->processCacheCompletion(req);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
|
|
@ -94,8 +94,7 @@ class LWBackEnd
|
|||
|
||||
void regStats();
|
||||
|
||||
void setCPU(FullCPU *cpu_ptr)
|
||||
{ cpu = cpu_ptr; }
|
||||
void setCPU(FullCPU *cpu_ptr);
|
||||
|
||||
void setFrontEnd(FrontEnd *front_end_ptr)
|
||||
{ frontEnd = front_end_ptr; }
|
||||
|
@ -404,6 +403,9 @@ class LWBackEnd
|
|||
Stats::Scalar<> commit_eligible_samples;
|
||||
Stats::Vector<> commit_eligible;
|
||||
|
||||
Stats::Vector<> squashedInsts;
|
||||
Stats::Vector<> ROBSquashedInsts;
|
||||
|
||||
Stats::Scalar<> ROB_fcount;
|
||||
Stats::Formula ROB_full_rate;
|
||||
|
||||
|
|
|
@ -480,6 +480,18 @@ LWBackEnd<Impl>::regStats()
|
|||
.desc("number cycles where commit BW limit reached")
|
||||
;
|
||||
|
||||
squashedInsts
|
||||
.init(cpu->number_of_threads)
|
||||
.name(name() + ".COM:squashed_insts")
|
||||
.desc("Number of instructions removed from inst list")
|
||||
;
|
||||
|
||||
ROBSquashedInsts
|
||||
.init(cpu->number_of_threads)
|
||||
.name(name() + ".COM:rob_squashed_insts")
|
||||
.desc("Number of instructions removed from inst list when they reached the head of the ROB")
|
||||
;
|
||||
|
||||
ROB_fcount
|
||||
.name(name() + ".ROB:full_count")
|
||||
.desc("number of cycles where ROB was full")
|
||||
|
@ -515,6 +527,14 @@ LWBackEnd<Impl>::regStats()
|
|||
// IQ.regStats();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LWBackEnd<Impl>::setCPU(FullCPU *cpu_ptr)
|
||||
{
|
||||
cpu = cpu_ptr;
|
||||
LSQ.setCPU(cpu_ptr);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LWBackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
|
||||
|
@ -1044,19 +1064,13 @@ LWBackEnd<Impl>::commitInst(int inst_num)
|
|||
}
|
||||
}
|
||||
|
||||
// Now check if it's one of the special trap or barrier or
|
||||
// serializing instructions.
|
||||
if (inst->isThreadSync())
|
||||
{
|
||||
// Not handled for now.
|
||||
panic("Thread sync instructions are not handled yet.\n");
|
||||
}
|
||||
assert(!inst->isThreadSync());
|
||||
|
||||
// Check if the instruction caused a fault. If so, trap.
|
||||
Fault inst_fault = inst->getFault();
|
||||
|
||||
if (inst_fault != NoFault) {
|
||||
if (!inst->isNop()) {
|
||||
DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
|
||||
inst->seqNum, inst->readPC());
|
||||
thread->setInst(
|
||||
|
@ -1069,11 +1083,6 @@ LWBackEnd<Impl>::commitInst(int inst_num)
|
|||
inst->PC);
|
||||
#endif // FULL_SYSTEM
|
||||
}
|
||||
}
|
||||
|
||||
if (inst->isControl()) {
|
||||
// ++commitCommittedBranches;
|
||||
}
|
||||
|
||||
int freed_regs = 0;
|
||||
|
||||
|
@ -1096,7 +1105,6 @@ LWBackEnd<Impl>::commitInst(int inst_num)
|
|||
instList.pop_back();
|
||||
|
||||
--numInsts;
|
||||
cpu->numInst++;
|
||||
thread->numInsts++;
|
||||
++thread->funcExeInst;
|
||||
// Maybe move this to where teh fault is handled; if the fault is handled,
|
||||
|
@ -1134,15 +1142,14 @@ template <class Impl>
|
|||
void
|
||||
LWBackEnd<Impl>::commitInsts()
|
||||
{
|
||||
int commit_width = commitWidth ? commitWidth : width;
|
||||
|
||||
// Not sure this should be a loop or not.
|
||||
int inst_num = 0;
|
||||
while (!instList.empty() && inst_num < commit_width) {
|
||||
while (!instList.empty() && inst_num < commitWidth) {
|
||||
if (instList.back()->isSquashed()) {
|
||||
instList.back()->clearDependents();
|
||||
instList.pop_back();
|
||||
--numInsts;
|
||||
ROBSquashedInsts[instList.back()->threadNumber]++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1150,6 +1157,7 @@ LWBackEnd<Impl>::commitInsts()
|
|||
DPRINTF(BE, "Can't commit, Instruction [sn:%lli] PC "
|
||||
"%#x is head of ROB and not ready\n",
|
||||
instList.back()->seqNum, instList.back()->readPC());
|
||||
--inst_num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1217,6 +1225,8 @@ LWBackEnd<Impl>::squash(const InstSeqNum &sn)
|
|||
|
||||
(*insts_it)->clearDependents();
|
||||
|
||||
squashedInsts[(*insts_it)->threadNumber]++;
|
||||
|
||||
instList.erase(insts_it++);
|
||||
--numInsts;
|
||||
}
|
||||
|
@ -1350,6 +1360,7 @@ LWBackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
|
|||
{
|
||||
unsigned thread = inst->threadNumber;
|
||||
|
||||
cpu->numInst++;
|
||||
//
|
||||
// Pick off the software prefetches
|
||||
//
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
//#include "mem/page_table.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class PageTable;
|
||||
//class PageTable;
|
||||
|
||||
/**
|
||||
* Class that implements the actual LQ and SQ for each specific thread.
|
||||
|
@ -115,7 +115,7 @@ class OzoneLWLSQ {
|
|||
{ be = be_ptr; }
|
||||
|
||||
/** Sets the page table pointer. */
|
||||
void setPageTable(PageTable *pt_ptr);
|
||||
// void setPageTable(PageTable *pt_ptr);
|
||||
|
||||
/** Ticks the LSQ unit, which in this case only resets the number of
|
||||
* used cache ports.
|
||||
|
@ -243,7 +243,7 @@ class OzoneLWLSQ {
|
|||
MemInterface *dcacheInterface;
|
||||
|
||||
/** Pointer to the page table. */
|
||||
PageTable *pTable;
|
||||
// PageTable *pTable;
|
||||
|
||||
public:
|
||||
struct SQEntry {
|
||||
|
@ -562,6 +562,19 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
|
|||
|
||||
|
||||
// If there's no forwarding case, then go access memory
|
||||
DPRINTF(OzoneLSQ, "Doing functional access for inst PC %#x\n",
|
||||
inst->readPC());
|
||||
|
||||
|
||||
// Setup MemReq pointer
|
||||
req->cmd = Read;
|
||||
req->completionEvent = NULL;
|
||||
req->time = curTick;
|
||||
assert(!req->data);
|
||||
req->data = new uint8_t[64];
|
||||
Fault fault = cpu->read(req, data);
|
||||
memcpy(req->data, &data, sizeof(T));
|
||||
|
||||
++usedPorts;
|
||||
|
||||
// if we have a cache, do cache access too
|
||||
|
@ -582,12 +595,6 @@ OzoneLWLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
|
|||
"vaddr:%#x flags:%i\n",
|
||||
inst->readPC(), req->paddr, req->vaddr, req->flags);
|
||||
|
||||
// Setup MemReq pointer
|
||||
req->cmd = Read;
|
||||
req->completionEvent = NULL;
|
||||
req->time = curTick;
|
||||
assert(!req->data);
|
||||
req->data = new uint8_t[64];
|
||||
|
||||
assert(!req->completionEvent);
|
||||
req->completionEvent =
|
||||
|
|
|
@ -131,7 +131,7 @@ OzoneLWLSQ<Impl>::clearSQ()
|
|||
{
|
||||
storeQueue.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
template<class Impl>
|
||||
void
|
||||
OzoneLWLSQ<Impl>::setPageTable(PageTable *pt_ptr)
|
||||
|
@ -139,7 +139,7 @@ OzoneLWLSQ<Impl>::setPageTable(PageTable *pt_ptr)
|
|||
DPRINTF(OzoneLSQ, "Setting the page table pointer.\n");
|
||||
pTable = pt_ptr;
|
||||
}
|
||||
|
||||
*/
|
||||
template<class Impl>
|
||||
void
|
||||
OzoneLWLSQ<Impl>::resizeLQ(unsigned size)
|
||||
|
@ -519,6 +519,23 @@ OzoneLWLSQ<Impl>::writebackStores()
|
|||
req->paddr, *(req->data),
|
||||
inst->seqNum);
|
||||
|
||||
switch((*sq_it).size) {
|
||||
case 1:
|
||||
cpu->write(req, (uint8_t &)(*sq_it).data);
|
||||
break;
|
||||
case 2:
|
||||
cpu->write(req, (uint16_t &)(*sq_it).data);
|
||||
break;
|
||||
case 4:
|
||||
cpu->write(req, (uint32_t &)(*sq_it).data);
|
||||
break;
|
||||
case 8:
|
||||
cpu->write(req, (uint64_t &)(*sq_it).data);
|
||||
break;
|
||||
default:
|
||||
panic("Unexpected store size!\n");
|
||||
}
|
||||
|
||||
if (dcacheInterface) {
|
||||
MemAccessResult result = dcacheInterface->access(req);
|
||||
|
||||
|
@ -538,7 +555,7 @@ OzoneLWLSQ<Impl>::writebackStores()
|
|||
typename BackEnd::LdWritebackEvent *wb = NULL;
|
||||
if (req->flags & LOCKED) {
|
||||
// Stx_C does not generate a system port transaction.
|
||||
req->result=1;
|
||||
// req->result=1;
|
||||
wb = new typename BackEnd::LdWritebackEvent(inst,
|
||||
be);
|
||||
}
|
||||
|
@ -571,12 +588,12 @@ OzoneLWLSQ<Impl>::writebackStores()
|
|||
|
||||
if (req->flags & LOCKED) {
|
||||
// Stx_C does not generate a system port transaction.
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
/* if (req->flags & UNCACHEABLE) {
|
||||
req->result = 2;
|
||||
} else {
|
||||
req->result = 1;
|
||||
}
|
||||
|
||||
*/
|
||||
typename BackEnd::LdWritebackEvent *wb =
|
||||
new typename BackEnd::LdWritebackEvent(inst,
|
||||
be);
|
||||
|
@ -642,6 +659,11 @@ OzoneLWLSQ<Impl>::squash(const InstSeqNum &squashed_num)
|
|||
|
||||
while (stores != 0 && (*sq_it).inst->seqNum > squashed_num) {
|
||||
assert(!storeQueue.empty());
|
||||
|
||||
if ((*sq_it).canWB) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the smart pointer to make sure it is decremented.
|
||||
DPRINTF(OzoneLSQ,"Store Instruction PC %#x idx:%i squashed [sn:%lli]\n",
|
||||
(*sq_it).inst->readPC(), (*sq_it).inst->sqIdx,
|
||||
|
|
Loading…
Reference in a new issue