timeBuffer(2 , 2),
removeInstsThisCycle(false),
activityRec(params->name, NumStages, 10, params->activity),
- stCondFails(0),
#if FULL_SYSTEM
system(params->system),
#endif // FULL_SYSTEM
endOfSkedIt = skedCache.end();
frontEndSked = createFrontEndSked();
-
+ faultSked = createFaultSked();
+
lastRunningCycle = curTick();
lockAddr = 0;
D.needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
- DPRINTF(SkedCache, "Resource Sked created for instruction \"front_end\"\n");
+ DPRINTF(SkedCache, "Resource Sked created for instruction Front End\n");
+
+ return res_sked;
+}
+RSkedPtr
+InOrderCPU::createFaultSked()
+{
+ RSkedPtr res_sked = new ResourceSked();
+ StageScheduler W(res_sked, NumStages - 1);
+ W.needs(Grad, GraduationUnit::CheckFault);
+ DPRINTF(SkedCache, "Resource Sked created for instruction Faults\n");
return res_sked;
}
SkedCacheIt endOfSkedIt;
ThePipeline::RSkedPtr frontEndSked;
+ ThePipeline::RSkedPtr faultSked;
/** Add a new instruction schedule to the schedule cache */
void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked)
}
ThePipeline::RSkedPtr createFrontEndSked();
+ ThePipeline::RSkedPtr createFaultSked();
ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst);
class StageScheduler {
virtual void wakeup();
#endif
- // LL/SC debug functionality
+ /* LL/SC debug functionality
unsigned stCondFails;
unsigned readStCondFailures()
unsigned setStCondFailures(unsigned st_fails)
{ return stCondFails = st_fails; }
+ */
/** Returns a pointer to a thread context. */
ThreadContext *tcBase(ThreadID tid = 0)
int InOrderDynInst::instcount = 0;
+int
+InOrderDynInst::cpuId()
+{
+ return cpu->cpuId();
+}
+
void
InOrderDynInst::setMachInst(ExtMachInst machInst)
{
squashSeqNum = seqNum;
#if ISA_HAS_DELAY_SLOT
- if (isControl()) {
+ if (staticInst && isControl()) {
TheISA::PCState nextPC = pc;
TheISA::advancePC(nextPC, staticInst);
/** Returns the fault type. */
Fault getFault() { return fault; }
+ /** Read this CPU's ID. */
+ int cpuId();
+
+ /** Read this context's system-wide ID **/
+ int contextId() { return thread->contextId(); }
+
////////////////////////////////////////////////////////////
//
// INSTRUCTION TYPES - Forward checks to StaticInst object.
curSkedEntry++;
if (inFrontEnd && curSkedEntry == frontSked_end) {
- DPRINTF(InOrderDynInst, "[sn:%i] Switching to "
+ DPRINTF(InOrderDynInst, "[sn:%i] Switching to "
"back end schedule.\n", seqNum);
assert(backSked != NULL);
- curSkedEntry.init(backSked);
- curSkedEntry = backSked->begin();
- inFrontEnd = false;
+ curSkedEntry.init(backSked);
+ curSkedEntry = backSked->begin();
+ inFrontEnd = false;
} else if (!inFrontEnd && curSkedEntry == backSked_end) {
return true;
}
virtual void setRegOtherThread(unsigned idx, const uint64_t &val,
ThreadID tid = InvalidThreadID);
+ /** Returns the number of consecutive store conditional failures. */
+ unsigned readStCondFailures()
+ { return thread->storeCondFailures; }
+
/** Sets the number of consecutive store conditional failures. */
void setStCondFailures(unsigned sc_failures)
{ thread->storeCondFailures = sc_failures; }
timeBuffer = tb_ptr;
// Setup wire to write information back to fetch.
+ // @todo: should this be writing to the next stage => -1 and reading from is (0)???
toPrevStages = timeBuffer->getWire(0);
// Create wires to get information from proper places in time buffer.
#endif
InstSeqNum seq_num = inst->seqNum;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderAGEN,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", tid, inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ agen_req->done();
+ return;
+ }
+
switch (agen_req->cmd)
{
case GenerateAddr:
{
ResourceRequest* bpred_req = reqs[slot_num];
DynInstPtr inst = bpred_req->inst;
- ThreadID tid = inst->readTid();
- InstSeqNum seq_num = inst->seqNum;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderBPred,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ bpred_req->done();
+ return;
+ }
if (!inst->isControl()) {
DPRINTF(Resource, "Ignoring %s, not a control inst.\n",
return;
}
-
+ ThreadID tid = inst->readTid();
+ InstSeqNum seq_num = inst->seqNum;
switch (bpred_req->cmd)
{
case PredictBranch:
inst->setBranchPred(predict_taken);
}
+ //@todo: Check to see how hw_rei is handled here...how does PC,NPC get
+ // updated to compare mispredict against???
inst->setPredTarg(pred_PC);
DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: %s Predicted PC is "
"%s.\n", tid, seq_num, inst->instName(), pred_PC);
if (cache_req->memReq == NULL) {
cache_req->memReq =
new Request(cpu->asid[tid], aligned_addr, acc_size, flags,
- inst->instAddr(), cpu->readCpuId(),
+ inst->instAddr(), cpu->readCpuId(), //@todo: use context id
tid);
DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n",
inst->seqNum, &cache_req->memReq, cache_req->memReq);
}
DynInstPtr inst = cache_req->inst;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+ inst->getMemAddr());
+ finishCacheUnitReq(inst, cache_req);
+ return;
+ }
+
#if TRACING_ON
ThreadID tid = inst->readTid();
std::string acc_type = "write";
"[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n",
tid, inst->seqNum);
- if (inst->fault != NoFault) {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
- "next stage.\n", tid, inst->seqNum, inst->fault->name(),
- inst->getMemAddr());
- finishCacheUnitReq(inst, cache_req);
- return;
- }
//@todo: timing translations need to check here...
assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes");
"[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n",
tid, inst->seqNum);
- if (inst->fault != NoFault) {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to ",
- "next stage.\n", tid, inst->seqNum, inst->fault->name(),
- inst->getMemAddr());
- finishCacheUnitReq(inst, cache_req);
- return;
- }
//@todo: check that timing translation is finished here
RequestPtr mem_req = cache_req->memReq;
if (mem_req->isLLSC()) {
assert(cache_req->inst->isStoreConditional());
DPRINTF(InOrderCachePort, "Evaluating Store Conditional access\n");
- do_access = TheISA::handleLockedWrite(cpu, mem_req);
+ do_access = TheISA::handleLockedWrite(inst.get(), mem_req);
}
}
DPRINTF(InOrderCachePort,
"[tid:%u]: Handling Load-Linked for [sn:%u]\n",
tid, inst->seqNum);
- TheISA::handleLockedRead(cpu, cache_pkt->req);
+ TheISA::handleLockedRead(inst.get(), cache_pkt->req);
}
DPRINTF(InOrderCachePort,
CacheUnit::squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid)
{
- if (tlbBlockSeqNum[tid] &&
+ if (tlbBlocked[tid] &&
tlbBlockSeqNum[tid] > squash_seq_num) {
DPRINTF(InOrderCachePort, "Releasing TLB Block due to "
" squash after [sn:%i].\n", squash_seq_num);
{
case DecodeInst:
{
- assert(!inst->staticInst->isMacroop());
- DPRINTF(Decode,"Decoded instruction [sn:%i]: %s : 0x%x\n",
- inst->seqNum, inst->instName(),
- inst->staticInst->machInst);
-
- inst->setBackSked(cpu->createBackEndSked(inst));
+ if (inst->fault != NoFault) {
+ inst->setBackSked(cpu->faultSked);
+ DPRINTF(Decode,"[tid:%i]: Fault found for instruction [sn:%i]\n",
+ inst->readTid(), inst->seqNum);
+ } else {
+ assert(!inst->staticInst->isMacroop());
+ inst->setBackSked(cpu->createBackEndSked(inst));
+ DPRINTF(Decode,"Decoded instruction [sn:%i]: %s : 0x%x\n",
+ inst->seqNum, inst->instName(),
+ inst->staticInst->machInst);
+ }
if (inst->backSked != NULL) {
DPRINTF(InOrderDecode,
{
ResourceRequest* exec_req = reqs[slot_num];
DynInstPtr inst = reqs[slot_num]->inst;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderExecute,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ exec_req->done();
+ return;
+ }
+
Fault fault = NoFault;
Tick cur_tick = curTick();
unsigned stage_num = exec_req->getStageNum();
ThreadID tid = inst->readTid();
int stage_num = fs_req->getStageNum();
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderFetchSeq,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", tid, inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ fs_req->done();
+ return;
+ }
+
switch (fs_req->cmd)
{
case AssignNextPC:
{
pcValid[tid] = true;
pc[tid] = cpu->pcState(tid);
- DPRINTF(Fault, "[tid:%i]: Trap updating to PC: "
- "%s.\n", tid, pc[tid]);
DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: "
"%s.\n", tid, pc[tid]);
}
Addr block_addr = cacheBlockAlign(inst->getMemAddr());
int asid = cpu->asid[tid];
- inst->fault = NoFault;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", tid, inst->seqNum, inst->fault->name(),
+ cacheBlockAlign(inst->getMemAddr()));
+ finishCacheUnitReq(inst, cache_req);
+ return;
+ }
switch (cache_req->cmd)
{
return;
}
- doTLBAccess(inst, cache_req, cacheBlkSize, 0, TheISA::TLB::Execute);
+ doTLBAccess(inst, cache_req, cacheBlkSize, Request::INST_FETCH, TheISA::TLB::Execute);
if (inst->fault == NoFault) {
DPRINTF(InOrderCachePort,
}
case CompleteFetch:
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", tid, inst->seqNum, inst->fault->name(),
+ inst->getMemAddr());
+ finishCacheUnitReq(inst, cache_req);
+ return;
+ }
+
if (cache_req->fetchBufferFill) {
// Block request if it's depending on a previous fetch, but it hasnt made it yet
std::list<FetchBlock*>::iterator fetch_it = findBlock(fetchBuffer, asid, block_addr);
GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width,
int res_latency, InOrderCPU *_cpu,
ThePipeline::Params *params)
- : Resource(res_name, res_id, res_width, res_latency, _cpu),
- lastNonSpecTick(0)
+ : Resource(res_name, res_id, res_width, res_latency, _cpu)
{
for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) {
nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid];
nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid];
+ lastNonSpecTick[tid] = 0;
+ lastFaultTick[tid] = 0;
}
}
DynInstPtr inst = reqs[slot_num]->inst;
ThreadID tid = inst->readTid();
int stage_num = inst->curSkedEntry->stageNum;
+ Tick cur_tick = curTick();
+
+ //@todo: not the common case, anyway we can move this
+ // check to the stage and just ignore instructions
+ // after?
+ if (lastNonSpecTick[tid] == cur_tick) {
+ DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. "
+ "Only 1 nonspec inst. per cycle can graduate.\n");
+ grad_req->done(false);
+ return;
+ }
+
+ if (lastFaultTick[tid] == cur_tick) {
+ DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. "
+ "Only 1 fault can be handled per tick.\n");
+ grad_req->done(false);
+ return;
+ }
+
switch (grad_req->cmd)
{
tid, inst->seqNum, inst->fault->name(),
inst->instName());
squashThenTrap(stage_num, inst);
+ lastFaultTick[tid] = cur_tick;
grad_req->done(false);
return;
}
case GraduateInst:
{
- if (lastNonSpecTick == curTick()) {
- DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. "
- "Only 1 nonspec inst. per cycle can graduate.\n");
- grad_req->done(false);
- return;
- }
-
DPRINTF(InOrderGraduation,
"[tid:%i]:[sn:%i]: Graduating instruction %s.\n",
tid, inst->seqNum, inst->staticInst->disassemble(inst->instAddr()));
// Release Non-Speculative "Block" on instructions that could not
// execute because there was a non-speculative inst. active.
// @TODO: Fix this functionality. Probably too conservative.
+ // Maybe it should be, non-spec. insts should block other
+ // non-spec insts because they can potentially be reading
+ // system state that will be changed by the 1st non-spec inst.
if (inst->isNonSpeculative()) {
*nonSpecInstActive[tid] = false;
DPRINTF(InOrderGraduation,
"[tid:%i] Non-speculative inst [sn:%i] graduated\n",
tid, inst->seqNum);
- lastNonSpecTick = curTick();
+ lastNonSpecTick[tid] = cur_tick;
}
if (inst->traceData) {
- inst->traceData->setStageCycle(stage_num, curTick());
+ inst->traceData->setStageCycle(stage_num, cur_tick);
}
// Tell CPU that instruction is finished processing
void execute(int slot_num);
protected:
- Tick lastNonSpecTick;
+ Tick lastNonSpecTick[ThePipeline::MaxThreads];
+ Tick lastFaultTick[ThePipeline::MaxThreads];
bool *nonSpecInstActive[ThePipeline::MaxThreads];
-
InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads];
};
{
ResourceRequest* mult_div_req = reqs[slot_num];
DynInstPtr inst = reqs[slot_num]->inst;
-
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderMDU,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ mult_div_req->done();
+ return;
+ }
+
DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num);
switch (mult_div_req->cmd)
.desc("Total Accesses (Read+Write) to the FP Register File");
floatRegFileAccs = floatRegFileReads + floatRegFileWrites;
+ //@todo: add miscreg reads/writes
+ // add forwarding by type???
+
regForwards
.name(name() + ".regForwards")
.desc("Number of Registers Read Through Forwarding Logic");
// for performance considerations
UseDefRequest* ud_req = dynamic_cast<UseDefRequest*>(reqs[slot_idx]);
assert(ud_req);
-
DynInstPtr inst = ud_req->inst;
+ if (inst->fault != NoFault) {
+ DPRINTF(InOrderUseDef,
+ "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+ "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+ inst->pcState());
+ ud_req->done();
+ return;
+ }
+
ThreadID tid = inst->readTid();
InstSeqNum seq_num = inst->seqNum;
int ud_idx = ud_req->useDefIdx;
-
// If there is a non-speculative instruction
// in the pipeline then stall instructions here
if (*nonSpecInstActive[tid] == true && seq_num > *nonSpecSeqNum[tid]) {