ARM: Allow conditional quiesce instructions.
authorAli Saidi <Ali.Saidi@ARM.com>
Fri, 18 Mar 2011 00:20:20 +0000 (19:20 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Fri, 18 Mar 2011 00:20:20 +0000 (19:20 -0500)
This patch prevents not executed conditional instructions marked as
IsQuiesce from stalling the pipeline indefinitely. If the instruction
is not executed the quiesceSkip psuedoinst is called which schedules a
wakes up call to the fetch stage.

src/arch/arm/isa/insts/m5ops.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/templates/pred.isa
src/sim/pseudo_inst.cc
src/sim/pseudo_inst.hh

index da3609bbce38650c5800c828f2ccd8045fff0213..8521cbc979fb5c5947b36f9caac0d38f63bcfbb2 100644 (file)
@@ -66,7 +66,7 @@ let {{
                              ["IsNonSpeculative", "IsQuiesce"])
     header_output += BasicDeclare.subst(quiesceIop)
     decoder_output += BasicConstructor.subst(quiesceIop)
-    exec_output += PredOpExecute.subst(quiesceIop)
+    exec_output += QuiescePredOpExecute.subst(quiesceIop)
 
     quiesceNsCode = '''
 #if FULL_SYSTEM
@@ -80,7 +80,7 @@ let {{
                              ["IsNonSpeculative", "IsQuiesce"])
     header_output += BasicDeclare.subst(quiesceNsIop)
     decoder_output += BasicConstructor.subst(quiesceNsIop)
-    exec_output += PredOpExecute.subst(quiesceNsIop)
+    exec_output += QuiescePredOpExecute.subst(quiesceNsIop)
 
     quiesceCyclesCode = '''
 #if FULL_SYSTEM
@@ -94,7 +94,7 @@ let {{
                              ["IsNonSpeculative", "IsQuiesce", "IsUnverifiable"])
     header_output += BasicDeclare.subst(quiesceCyclesIop)
     decoder_output += BasicConstructor.subst(quiesceCyclesIop)
-    exec_output += PredOpExecute.subst(quiesceCyclesIop)
+    exec_output += QuiescePredOpExecute.subst(quiesceCyclesIop)
 
     quiesceTimeCode = '''
 #if FULL_SYSTEM
index be51d927dd63887739eb95d127d487b176a560ea..cf5c7b47ab5f84b8dca08eda59b8a8b0ed164f67 100644 (file)
@@ -491,10 +491,13 @@ let {{
 
     wfeCode = '''
 #if FULL_SYSTEM
-    if (SevMailbox)
+    if (SevMailbox) {
         SevMailbox = 0;
-    else
+        PseudoInst::quiesceSkip(xc->tcBase());
+    }
+    else {
         PseudoInst::quiesce(xc->tcBase());
+    }
 #endif
     '''
     wfeIop = InstObjParams("wfe", "WfeInst", "PredOp", \
@@ -502,7 +505,7 @@ let {{
             ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
     header_output += BasicDeclare.subst(wfeIop)
     decoder_output += BasicConstructor.subst(wfeIop)
-    exec_output += PredOpExecute.subst(wfeIop)
+    exec_output += QuiescePredOpExecute.subst(wfeIop)
 
     wfiCode = '''
 #if FULL_SYSTEM
@@ -511,22 +514,25 @@ let {{
     '''
     wfiIop = InstObjParams("wfi", "WfiInst", "PredOp", \
             { "code" : wfiCode, "predicate_test" : predicateTest },
-            ["IsNonSpeculative", "IsQuiesce"])
+            ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
     header_output += BasicDeclare.subst(wfiIop)
     decoder_output += BasicConstructor.subst(wfiIop)
-    exec_output += PredOpExecute.subst(wfiIop)
+    exec_output += QuiescePredOpExecute.subst(wfiIop)
 
     sevCode = '''
     // Need a way for O3 to not scoreboard these accesses as pipe flushes.
+    SevMailbox = 1;
     System *sys = xc->tcBase()->getSystemPtr();
     for (int x = 0; x < sys->numContexts(); x++) {
         ThreadContext *oc = sys->getThreadContext(x);
-        oc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
+        if (oc != xc->tcBase()) {
+            oc->setMiscReg(MISCREG_SEV_MAILBOX, 1);
+        }
     }
     '''
     sevIop = InstObjParams("sev", "SevInst", "PredOp", \
             { "code" : sevCode, "predicate_test" : predicateTest },
-            ["IsNonSpeculative", "IsQuiesce", "IsSerializeAfter"])
+            ["IsNonSpeculative", "IsSquashAfter"])
     header_output += BasicDeclare.subst(sevIop)
     decoder_output += BasicConstructor.subst(sevIop)
     exec_output += PredOpExecute.subst(sevIop)
index c9e7b18039f19b41f59be43683ff53da0f07817f..2a4bd9dab0ce25aaf0aa381c66e7541be1d4b6be 100644 (file)
@@ -170,6 +170,38 @@ def template PredOpExecute {{
     }
 }};
 
+def template QuiescePredOpExecute {{
+    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+    {
+        Fault fault = NoFault;
+        uint64_t resTemp = 0;
+        resTemp = resTemp;
+        %(op_decl)s;
+        %(op_rd)s;
+
+        if (%(predicate_test)s)
+        {
+            %(code)s;
+            if (fault == NoFault)
+            {
+                %(op_wb)s;
+            }
+        } else {
+            xc->setPredicate(false);
+#if FULL_SYSTEM
+            PseudoInst::quiesceSkip(xc->tcBase());
+#endif
+        }
+
+        if (fault == NoFault && machInst.itstateMask != 0&&
+                (!isMicroop() || isLastMicroop())) {
+            xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
+        }
+
+        return fault;
+    }
+}};
+
 def template DataDecode {{
     if (machInst.opcode4 == 0) {
         if (machInst.sField == 0)
index f3b10f6d2179032c4ad7e1411a8b03643f2a2eb8..bcff2f5c18e46d7249e38c473ff2471c4dffb9c3 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 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) 2003-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -85,6 +97,28 @@ quiesce(ThreadContext *tc)
         tc->getKernelStats()->quiesce();
 }
 
+void
+quiesceSkip(ThreadContext *tc)
+{
+    BaseCPU *cpu = tc->getCpuPtr();
+
+    if (!cpu->params()->do_quiesce)
+        return;
+
+    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
+
+    Tick resume = curTick() + 1;
+
+    cpu->reschedule(quiesceEvent, resume, true);
+
+    DPRINTF(Quiesce, "%s: quiesceSkip() until %d\n",
+            cpu->name(), resume);
+
+    tc->suspend();
+    if (tc->getKernelStats())
+        tc->getKernelStats()->quiesce();
+}
+
 void
 quiesceNs(ThreadContext *tc, uint64_t ns)
 {
index 296b1556b6122d0d53678a96abaae062edee8036..aec3b5d8ad2d378260f014662f5895d36f14502e 100644 (file)
@@ -45,6 +45,7 @@ extern bool doQuiesce;
 #if FULL_SYSTEM
 void arm(ThreadContext *tc);
 void quiesce(ThreadContext *tc);
+void quiesceSkip(ThreadContext *tc);
 void quiesceNs(ThreadContext *tc, uint64_t ns);
 void quiesceCycles(ThreadContext *tc, uint64_t cycles);
 uint64_t quiesceTime(ThreadContext *tc);