diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/o3/comm.hh | 57 | ||||
-rw-r--r-- | src/cpu/o3/commit.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/commit_impl.hh | 28 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 5 | ||||
-rw-r--r-- | src/cpu/o3/fetch.hh | 4 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 15 | ||||
-rw-r--r-- | src/cpu/o3/iew_impl.hh | 6 | ||||
-rw-r--r-- | src/cpu/o3/lsq_unit_impl.hh | 4 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 3 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 4 | ||||
-rw-r--r-- | src/cpu/static_inst.hh | 1 |
11 files changed, 87 insertions, 43 deletions
diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 897807fdb..840dde9ea 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 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. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -123,7 +135,6 @@ struct TimeBufStruct { bool branchTaken; Addr mispredPC; TheISA::PCState nextPC; - unsigned branchCount; }; @@ -151,29 +162,45 @@ struct TimeBufStruct { iewComm iewInfo[Impl::MaxThreads]; struct commitComm { - bool usedROB; - unsigned freeROBEntries; - bool emptyROB; + /////////////// For Decode, IEW, Rename, Fetch /////////// bool squash; bool robSquashing; - bool branchMispredict; - DynInstPtr mispredictInst; - bool branchTaken; - Addr mispredPC; - TheISA::PCState pc; - + ////////// For Fetch & IEW ///////////// // Represents the instruction that has either been retired or // squashed. Similar to having a single bus that broadcasts the // retired or squashed sequence number. InstSeqNum doneSeqNum; - //Just in case we want to do a commit/squash on a cycle - //(necessary for multiple ROBs?) - bool commitInsts; - InstSeqNum squashSeqNum; + ////////////// For Rename ///////////////// + // Rename should re-read number of free rob entries + bool usedROB; + // Notify Rename that the ROB is empty + bool emptyROB; + // Tell Rename how many free entries it has in the ROB + unsigned freeROBEntries; + + + ///////////// For Fetch ////////////////// + // Provide fetch the instruction that mispredicted, if this + // pointer is not-null a misprediction occured + DynInstPtr mispredictInst; + // Was the branch taken or not + bool branchTaken; + // The pc of the next instruction to execute. This is the next + // instruction for a branch mispredict, but the same instruction for + // order violation and the like + TheISA::PCState pc; + + // Instruction that caused the a non-mispredict squash + DynInstPtr squashInst; + // If an interrupt is pending and fetch should stall + bool interruptPending; + // If the interrupt ended up being cleared before being handled + bool clearInterrupt; + //////////// For IEW ////////////////// // Communication specifically to the IQ to tell the IQ that it can // schedule a non-speculative instruction. InstSeqNum nonSpecSeqNum; @@ -182,8 +209,6 @@ struct TimeBufStruct { bool uncached; DynInstPtr uncachedLoad; - bool interruptPending; - bool clearInterrupt; }; commitComm commitInfo[Impl::MaxThreads]; diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 047e29f5d..ff7b53440 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -262,7 +262,8 @@ class DefaultCommit * instructions instead of the current instruction and doesn't * clean up various status bits about traps/tc writes pending. */ - void squashAfter(ThreadID tid, uint64_t squash_after_seq_num); + void squashAfter(ThreadID tid, DynInstPtr &head_inst, + uint64_t squash_after_seq_num); #if FULL_SYSTEM /** Handles processing an interrupt. */ diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 104e7fb58..8c651e203 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -541,8 +541,8 @@ DefaultCommit<Impl>::squashAll(ThreadID tid) // the ROB is in the process of squashing. toIEW->commitInfo[tid].robSquashing = true; - toIEW->commitInfo[tid].branchMispredict = false; toIEW->commitInfo[tid].mispredictInst = NULL; + toIEW->commitInfo[tid].squashInst = NULL; toIEW->commitInfo[tid].pc = pc[tid]; } @@ -584,7 +584,8 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid) template <class Impl> void -DefaultCommit<Impl>::squashAfter(ThreadID tid, uint64_t squash_after_seq_num) +DefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst, + uint64_t squash_after_seq_num) { youngestSeqNum[tid] = squash_after_seq_num; @@ -594,6 +595,7 @@ DefaultCommit<Impl>::squashAfter(ThreadID tid, uint64_t squash_after_seq_num) // Send back the sequence number of the squashed instruction. toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num; + toIEW->commitInfo[tid].squashInst = head_inst; // Send back the squash signal to tell stages that they should squash. toIEW->commitInfo[tid].squash = true; @@ -601,7 +603,7 @@ DefaultCommit<Impl>::squashAfter(ThreadID tid, uint64_t squash_after_seq_num) // the ROB is in the process of squashing. toIEW->commitInfo[tid].robSquashing = true; - toIEW->commitInfo[tid].branchMispredict = false; + toIEW->commitInfo[tid].mispredictInst = NULL; toIEW->commitInfo[tid].pc = pc[tid]; DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n", @@ -801,10 +803,17 @@ DefaultCommit<Impl>::commit() commitStatus[tid] != TrapPending && fromIEW->squashedSeqNum[tid] <= youngestSeqNum[tid]) { - DPRINTF(Commit, "[tid:%i]: Squashing due to PC %#x [sn:%i]\n", + if (fromIEW->mispredictInst[tid]) { + DPRINTF(Commit, + "[tid:%i]: Squashing due to branch mispred PC:%#x [sn:%i]\n", tid, - fromIEW->mispredPC[tid], + fromIEW->mispredictInst[tid]->instAddr(), fromIEW->squashedSeqNum[tid]); + } else { + DPRINTF(Commit, + "[tid:%i]: Squashing due to order violation [sn:%i]\n", + tid, fromIEW->squashedSeqNum[tid]); + } DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n", tid, @@ -835,18 +844,15 @@ DefaultCommit<Impl>::commit() // the ROB is in the process of squashing. toIEW->commitInfo[tid].robSquashing = true; - toIEW->commitInfo[tid].branchMispredict = - fromIEW->branchMispredict[tid]; toIEW->commitInfo[tid].mispredictInst = fromIEW->mispredictInst[tid]; toIEW->commitInfo[tid].branchTaken = fromIEW->branchTaken[tid]; + toIEW->commitInfo[tid].squashInst = NULL; toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; - toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; - - if (toIEW->commitInfo[tid].branchMispredict) { + if (toIEW->commitInfo[tid].mispredictInst) { ++branchMispredicts; } } @@ -988,7 +994,7 @@ DefaultCommit<Impl>::commitInsts() // If this is an instruction that doesn't play nicely with // others squash everything and restart fetch if (head_inst->isSquashAfter()) - squashAfter(tid, head_inst->seqNum); + squashAfter(tid, head_inst, head_inst->seqNum); int count = 0; Addr oldpc; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 2d3bc3f72..4088f2399 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -808,8 +808,9 @@ FullO3CPU<Impl>::removeThread(ThreadID tid) } // Squash Throughout Pipeline - InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; - fetch.squash(0, squash_seq_num, tid); + DynInstPtr inst = commit.rob->readHeadInst(tid); + InstSeqNum squash_seq_num = inst->seqNum; + fetch.squash(0, squash_seq_num, inst, tid); decode.squash(tid); rename.squash(squash_seq_num, tid); iew.squash(tid); diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index c51658104..4a4ac0902 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -312,8 +312,8 @@ class DefaultFetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const TheISA::PCState &newPC, - const InstSeqNum &seq_num, ThreadID tid); + void squash(const TheISA::PCState &newPC, const InstSeqNum &seq_num, + DynInstPtr &squashInst, ThreadID tid); /** Ticks the fetch stage, processing all inputs signals and fetching * as many instructions as possible. diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index a2f2b4f8a..6c1ac456d 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -112,6 +112,9 @@ DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt) { DPRINTF(Fetch, "Received timing\n"); if (pkt->isResponse()) { + // We shouldn't ever get a block in ownership state + assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); + fetch->processCacheCompletion(pkt); } //else Snooped a coherence request, just return @@ -812,11 +815,14 @@ DefaultFetch<Impl>::updateFetchStatus() template <class Impl> void DefaultFetch<Impl>::squash(const TheISA::PCState &newPC, - const InstSeqNum &seq_num, ThreadID tid) + const InstSeqNum &seq_num, DynInstPtr &squashInst, + ThreadID tid) { DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid); doSquash(newPC, tid); + if (squashInst) + predecoder.reset(squashInst->staticInst->machInst); // Tell the CPU to remove any instructions that are not in the ROB. cpu->removeInstsNotInROB(tid); @@ -931,15 +937,12 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) // In any case, squash. squash(fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].doneSeqNum, - tid); + fromCommit->commitInfo[tid].squashInst, tid); // If it was a branch mispredict on a control instruction, update the // branch predictor with that instruction, otherwise just kill the // invalid state we generated in after sequence number - assert(!fromCommit->commitInfo[tid].branchMispredict || - fromCommit->commitInfo[tid].mispredictInst); - - if (fromCommit->commitInfo[tid].branchMispredict && + if (fromCommit->commitInfo[tid].mispredictInst && fromCommit->commitInfo[tid].mispredictInst->isControl()) { branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, fromCommit->commitInfo[tid].pc, diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index dff287ff5..8bf3c56f4 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -456,8 +456,6 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) inst->seqNum < toCommit->squashedSeqNum[tid]) { toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->mispredPC[tid] = inst->instAddr(); - toCommit->branchMispredict[tid] = true; toCommit->branchTaken[tid] = inst->pcState().branching(); TheISA::PCState pc = inst->pcState(); @@ -486,7 +484,7 @@ DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) TheISA::PCState pc = inst->pcState(); TheISA::advancePC(pc, inst->staticInst); toCommit->pc[tid] = pc; - toCommit->branchMispredict[tid] = false; + toCommit->mispredictInst[tid] = NULL; toCommit->includeSquashInst[tid] = false; @@ -506,7 +504,7 @@ DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->pc[tid] = inst->pcState(); - toCommit->branchMispredict[tid] = false; + toCommit->mispredictInst[tid] = NULL; // Must include the broadcasted SN in the squash. toCommit->includeSquashInst[tid] = true; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index b5d337935..1a4e686a3 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -1103,7 +1103,9 @@ LSQUnit<Impl>::recvRetry() dynamic_cast<LSQSenderState *>(retryPkt->senderState); // Don't finish the store unless this is the last packet. - if (!TheISA::HasUnalignedMemAcc || !state->pktToSend) { + if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || + state->pendingPacket == retryPkt) { + state->pktToSend = false; storePostSend(retryPkt); } retryPkt = NULL; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 27635d3ce..6aa0eb64e 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -641,6 +641,9 @@ AtomicSimpleCPU::tick() checkForInterrupts(); checkPcEventQueue(); + // We must have just got suspended by a PC event + if (_status == Idle) + return; Fault fault = NoFault; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 632e83356..aca48e5d4 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -714,6 +714,10 @@ TimingSimpleCPU::fetch() checkPcEventQueue(); + // We must have just got suspended by a PC event + if (_status == Idle) + return; + TheISA::PCState pcState = thread->pcState(); bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 933496864..d07b322df 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -267,6 +267,7 @@ class StaticInstBase : public RefCounted void setLastMicroop() { flags[IsLastMicroop] = true; } void setDelayedCommit() { flags[IsDelayedCommit] = true; } + void setFlag(Flags f) { flags[f] = true; } /// Operation class. Used to select appropriate function unit in issue. OpClass opClass() const { return _opClass; } |