diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2012-09-25 11:49:40 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2012-09-25 11:49:40 -0500 |
commit | 0c99d21ad748371e801508a8c3652e07e2e56f93 (patch) | |
tree | a2a52170a8a88ce919cecb4309428999e5380cfd | |
parent | 29acf859ebde2cf219ae636f60d8a46db7a1bb94 (diff) | |
download | gem5-0c99d21ad748371e801508a8c3652e07e2e56f93.tar.xz |
ARM: Squash outstanding walks when instructions are squashed.
-rw-r--r-- | src/arch/arm/ArmTLB.py | 2 | ||||
-rw-r--r-- | src/arch/arm/table_walker.cc | 44 | ||||
-rw-r--r-- | src/arch/arm/table_walker.hh | 4 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 8 | ||||
-rw-r--r-- | src/cpu/translation.hh | 6 | ||||
-rw-r--r-- | src/sim/tlb.hh | 7 |
6 files changed, 68 insertions, 3 deletions
diff --git a/src/arch/arm/ArmTLB.py b/src/arch/arm/ArmTLB.py index 9572d2091..0a931b7e5 100644 --- a/src/arch/arm/ArmTLB.py +++ b/src/arch/arm/ArmTLB.py @@ -47,6 +47,8 @@ class ArmTableWalker(MemObject): cxx_class = 'ArmISA::TableWalker' port = MasterPort("Port for TableWalker to do walk the translation with") sys = Param.System(Parent.any, "system object parameter") + num_squash_per_cycle = Param.Unsigned(2, + "Number of outstanding walks that can be squashed per cycle") class ArmTLB(SimObject): type = 'ArmTLB' diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 77cc662b3..dbd4211d5 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -54,6 +54,7 @@ TableWalker::TableWalker(const Params *p) : MemObject(p), port(this, params()->sys), drainEvent(NULL), tlb(NULL), currState(NULL), pending(false), masterId(p->sys->getMasterId(name())), + numSquashable(p->num_squash_per_cycle), doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this) { sctlr = 0; @@ -184,9 +185,46 @@ TableWalker::processWalkWrapper() assert(!currState); assert(pendingQueue.size()); currState = pendingQueue.front(); - pendingQueue.pop_front(); - pending = true; - processWalk(); + + + if (!currState->transState->squashed()) { + // We've got a valid request, lets process it + pending = true; + pendingQueue.pop_front(); + processWalk(); + return; + } + + + // If the instruction that we were translating for has been + // squashed we shouldn't bother. + unsigned num_squashed = 0; + ThreadContext *tc = currState->tc; + assert(currState->transState->squashed()); + while ((num_squashed < numSquashable) && currState && + currState->transState->squashed()) { + pendingQueue.pop_front(); + num_squashed++; + + DPRINTF(TLB, "Squashing table walk for address %#x\n", currState->vaddr); + + // finish the translation which will delete the translation object + currState->transState->finish(new UnimpFault("Squashed Inst"), + currState->req, currState->tc, currState->mode); + + // delete the current request + delete currState; + + // peak at the next one + if (pendingQueue.size()) + currState = pendingQueue.front(); + else + currState = NULL; + } + + // if we've still got pending translations schedule more work + nextWalk(tc); + currState = NULL; } Fault diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index b6fee66ff..509b24339 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -380,6 +380,10 @@ class TableWalker : public MemObject /** Request id for requests generated by this walker */ MasterID masterId; + /** The number of walks belonging to squashed instructions that can be + * removed from the pendingQueue per cycle. */ + unsigned numSquashable; + public: typedef ArmTableWalkerParams Params; TableWalker(const Params *p); diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 19a4f818e..a2570abe6 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -269,6 +269,14 @@ class TimingSimpleCPU : public BaseSimpleCPU void completeDataAccess(PacketPtr pkt); void advanceInst(Fault fault); + /** This function is used by the page table walker to determine if it could + * translate the a pending request or if the underlying request has been + * squashed. This always returns false for the simple timing CPU as it never + * executes any instructions speculatively. + * @ return Is the current instruction squashed? + */ + bool isSquashed() const { return false; } + /** * Print state of address in memory system via PrintReq (for * debugging). diff --git a/src/cpu/translation.hh b/src/cpu/translation.hh index b6bc2182c..90fffa03d 100644 --- a/src/cpu/translation.hh +++ b/src/cpu/translation.hh @@ -259,6 +259,12 @@ class DataTranslation : public BaseTLB::Translation } delete this; } + + bool + squashed() const + { + return xc->isSquashed(); + } }; #endif // __CPU_TRANSLATION_HH__ diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh index 379cdd343..0b89c9bd0 100644 --- a/src/sim/tlb.hh +++ b/src/sim/tlb.hh @@ -94,6 +94,13 @@ class BaseTLB : public SimObject */ virtual void finish(Fault fault, RequestPtr req, ThreadContext *tc, Mode mode) = 0; + + /** This function is used by the page table walker to determine if it + * should translate the a pending request or if the underlying request + * has been squashed. + * @ return Is the instruction that requested this translation squashed? + */ + virtual bool squashed() const { return false; } }; }; |