From e681c0f7b30f521805ebec04271435306f4c56ed Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 7 Dec 2010 16:19:57 -0800 Subject: [PATCH] O3: Support squashing all state after special instruction For SPARC ASIs are added to the ExtMachInst. If the ASI is changed simply marking the instruction as Serializing isn't enough beacuse that only stops rename. This provides a mechanism to squash all the instructions and refetch them --- src/arch/sparc/isa/decoder.isa | 3 ++- src/cpu/base_dyn_inst.hh | 1 + src/cpu/o3/commit.hh | 7 +++++++ src/cpu/o3/commit_impl.hh | 32 ++++++++++++++++++++++++++++++++ src/cpu/static_inst.hh | 3 ++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index e0a34a1b1..b62b8400d 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -490,7 +490,8 @@ decode OP default Unknown::unknown() 0x00: NoPriv::wry({{Y = (Rs1 ^ Rs2_or_imm13)<31:0>;}}); // 0x01 should cause an illegal instruction exception 0x02: NoPriv::wrccr({{Ccr = Rs1 ^ Rs2_or_imm13;}}); - 0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}}); + 0x03: NoPriv::wrasi({{Asi = Rs1 ^ Rs2_or_imm13;}}, false, + IsSquashAfter); // 0x04-0x05 should cause an illegal instruction exception 0x06: NoPriv::wrfprs({{Fprs = Rs1 ^ Rs2_or_imm13;}}); // 0x07-0x0E should cause an illegal instruction exception diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index bd2d9fa95..0c566ec65 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -478,6 +478,7 @@ class BaseDynInst : public FastAlloc, public RefCounted { return staticInst->isSerializeBefore() || status[SerializeBefore]; } bool isSerializeAfter() const { return staticInst->isSerializeAfter() || status[SerializeAfter]; } + bool isSquashAfter() const { return staticInst->isSquashAfter(); } bool isMemBarrier() const { return staticInst->isMemBarrier(); } bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 326f3a1d3..468153dc7 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -245,6 +245,13 @@ class DefaultCommit /** Handles squashing due to an TC write. */ void squashFromTC(ThreadID tid); + /** Handles squashing from instruction with SquashAfter set. + * This differs from the other squashes as it squashes following + * 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); + #if FULL_SYSTEM /** Handles processing an interrupt. */ void handleInterrupt(); diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 1a44c64ee..2895de293 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -559,6 +559,33 @@ DefaultCommit::squashFromTC(ThreadID tid) tcSquash[tid] = false; } +template +void +DefaultCommit::squashAfter(ThreadID tid, uint64_t squash_after_seq_num) +{ + youngestSeqNum[tid] = squash_after_seq_num; + + rob->squash(squash_after_seq_num, tid); + changedROBNumEntries[tid] = true; + + // Send back the sequence number of the squashed instruction. + toIEW->commitInfo[tid].doneSeqNum = squash_after_seq_num; + + // Send back the squash signal to tell stages that they should squash. + toIEW->commitInfo[tid].squash = true; + + // Send back the rob squashing signal so other stages know that + // the ROB is in the process of squashing. + toIEW->commitInfo[tid].robSquashing = true; + + toIEW->commitInfo[tid].branchMispredict = false; + + toIEW->commitInfo[tid].pc = pc[tid]; + DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n", + tid, squash_after_seq_num); + commitStatus[tid] = ROBSquashing; +} + template void DefaultCommit::tick() @@ -917,6 +944,11 @@ DefaultCommit::commitInsts() TheISA::advancePC(pc[tid], head_inst->staticInst); + // 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); + int count = 0; Addr oldpc; // Debug statement. Checks to make sure we're not diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index e08cbcdb6..15ac444ae 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -158,7 +158,7 @@ class StaticInstBase : public RefCounted //This flag doesn't do anything yet IsMicroBranch, ///< This microop branches within the microcode for a macroop IsDspOp, - + IsSquashAfter, ///< Squash all uncommitted state after executed NumFlags }; @@ -248,6 +248,7 @@ class StaticInstBase : public RefCounted flags[IsSerializeAfter]; } bool isSerializeBefore() const { return flags[IsSerializeBefore]; } bool isSerializeAfter() const { return flags[IsSerializeAfter]; } + bool isSquashAfter() const { return flags[IsSquashAfter]; } bool isMemBarrier() const { return flags[IsMemBarrier]; } bool isWriteBarrier() const { return flags[IsWriteBarrier]; } bool isNonSpeculative() const { return flags[IsNonSpeculative]; }