arch,cpu: Rearrange StaticInst flags for memory barriers.
authorGabe Black <gabeblack@google.com>
Sun, 30 Aug 2020 09:28:33 +0000 (02:28 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 16 Sep 2020 08:29:17 +0000 (08:29 +0000)
There were three different StaticInst flags for memory barriers,
IsMemBarrier, IsReadBarrier, and IsWriteBarrier. IsReadBarrier was never
used, and IsMemBarrier was for both loads and stores, so a composite of
IsReadBarrier and IsWriteBarrier.

This change gets rid of IsMemBarrier and replaces by setting
IsReadBarrier and IsWriteBarrier at the same time. An isMemBarrier
accessor is left, but is now implemented by checking if both of the
other flags are set, and renamed to isFullMemBarrier to make it clear
that it's checking both for both types of barrier, not one or the other.

Change-Id: I702633a047f4777be4b180b42d62438ca69f52ea
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/33743
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
26 files changed:
src/arch/arm/insts/mem64.cc
src/arch/arm/insts/tme64.cc
src/arch/arm/isa/insts/amo64.isa
src/arch/arm/isa/insts/ldr.isa
src/arch/arm/isa/insts/ldr64.isa
src/arch/arm/isa/insts/misc.isa
src/arch/arm/isa/insts/misc64.isa
src/arch/arm/isa/insts/str.isa
src/arch/arm/isa/insts/str64.isa
src/arch/arm/isa/templates/semihost.isa
src/arch/mips/isa/decoder.isa
src/arch/power/isa/decoder.isa
src/arch/riscv/isa/decoder.isa
src/arch/riscv/isa/formats/amo.isa
src/arch/sparc/isa/decoder.isa
src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/arch/x86/isa/microops/specop.isa
src/cpu/StaticInstFlags.py
src/cpu/base_dyn_inst.hh
src/cpu/minor/execute.cc
src/cpu/minor/lsq.cc
src/cpu/o3/commit_impl.hh
src/cpu/o3/iew_impl.hh
src/cpu/o3/inst_queue_impl.hh
src/cpu/o3/mem_dep_unit_impl.hh
src/cpu/static_inst.hh

index 0ddda956ee9ef1c2399eb518f3126b14ec5387b8..a12c33058238c5e5c8f5f1eb23bdcdf0d2033490 100644 (file)
@@ -79,7 +79,6 @@ Memory64::setExcAcRel(bool exclusive, bool acrel)
     else
         memAccessFlags |= ArmISA::TLB::AllowUnaligned;
     if (acrel) {
-        flags[IsMemBarrier] = true;
         flags[IsWriteBarrier] = true;
         flags[IsReadBarrier] = true;
     }
index 30aff208e6b050b38f54e3daa29ac2c24b26591d..f7096d0b27b797fe93fa9f5531fdb5569e599913 100644 (file)
@@ -83,7 +83,6 @@ MicroTfence64::MicroTfence64(ExtMachInst machInst)
     _numVecElemDestRegs = 0;
     _numIntDestRegs = 0;
     _numCCDestRegs = 0;
-    flags[IsMemBarrier] = true;
     flags[IsMicroop] = true;
     flags[IsReadBarrier] = true;
     flags[IsWriteBarrier] = true;
index 1fe9b7a1e3491c7904a18eb1b92ab28bbc0eaf37..51e1f38e53a2bf258e6d40c5dff944ff147f09f3 100644 (file)
@@ -91,7 +91,7 @@ let {{
                 self.instFlags.append("IsMicroop")
 
             if self.flavor in ("release", "acquire_release", "acquire"):
-                self.instFlags.append("IsMemBarrier")
+                self.instFlags.extend(["IsReadBarrier", "IsWriteBarrier"])
             if self.flavor in ("release", "acquire_release"):
                 self.instFlags.append("IsWriteBarrier")
             if self.flavor in ("acquire_release", "acquire"):
index d7e27a481ff06159f500281ffbdbfd17543ded55..3be0e3e90270ec8ed920802a6ce1bfa9549f7a6b 100644 (file)
@@ -179,9 +179,7 @@ let {{
                 self.memFlags.append("Request::LLSC")
 
             if self.flavor in ("acquire", "acex"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
-                                       "IsReadBarrier"])
+                self.instFlags.extend(["IsWriteBarrier", "IsReadBarrier"])
                 self.memFlags.append("Request::ACQUIRE")
 
             # Disambiguate the class name for different flavors of loads
@@ -260,9 +258,7 @@ let {{
                 self.Name = "%s_%s" % (self.name.upper(), self.Name)
 
             if self.flavor in ("acquire", "acex"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
-                                       "IsReadBarrier"])
+                self.instFlags.extend(["IsWriteBarrier", "IsReadBarrier"])
                 self.memFlags.append("Request::ACQUIRE")
 
         def emit(self):
index 51f53897bea07796c0a10c4a49bcfd5e8759da31..1ce34cdd0ceb7349ac20edbdf729b123b828cb76 100644 (file)
@@ -91,9 +91,7 @@ let {{
                 self.memFlags.append("ArmISA::TLB::AllowUnaligned")
 
             if self.flavor in ("acquire", "acex", "acexp"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
-                                       "IsReadBarrier"])
+                self.instFlags.extend(["IsWriteBarrier", "IsReadBarrier"])
                 self.memFlags.append("Request::ACQUIRE")
 
             if self.flavor in ("acex", "exclusive", "exp", "acexp"):
index 6a9b048041981d39ea0223e81f9e957e3cc69b95..b2543b3da3e150c67319a514fc73adc1c03de011 100644 (file)
@@ -1238,7 +1238,8 @@ let {{
     dsbIop = InstObjParams("dsb", "Dsb", "ImmOp",
                              {"code": dsbCode,
                                "predicate_test": predicateTest},
-                              ['IsMemBarrier', 'IsSerializeAfter'])
+                              ['IsReadBarrier', 'IsWriteBarrier',
+                               'IsSerializeAfter'])
     header_output += ImmOpDeclare.subst(dsbIop)
     decoder_output += ImmOpConstructor.subst(dsbIop)
     exec_output += PredOpExecute.subst(dsbIop)
@@ -1254,7 +1255,7 @@ let {{
     dmbIop = InstObjParams("dmb", "Dmb", "ImmOp",
                              {"code": dmbCode,
                                "predicate_test": predicateTest},
-                               ['IsMemBarrier'])
+                               ['IsReadBarrier', 'IsWriteBarrier'])
     header_output += ImmOpDeclare.subst(dmbIop)
     decoder_output += ImmOpConstructor.subst(dmbIop)
     exec_output += PredOpExecute.subst(dmbIop)
index 7911ec90d275ce3cc2ab3fb7b2371172c56c0bef..e8dc41cfcc8b65f0d789f39f0f3d8d164943fc13 100644 (file)
@@ -173,13 +173,14 @@ let {{
     exec_output += BasicExecute.subst(isbIop)
 
     dsbIop = InstObjParams("dsb", "Dsb64", "ArmStaticInst", "",
-                           ['IsMemBarrier', 'IsSerializeAfter'])
+                           ['IsReadBarrier', 'IsWriteBarrier',
+                            'IsSerializeAfter'])
     header_output += BasicDeclare.subst(dsbIop)
     decoder_output += BasicConstructor64.subst(dsbIop)
     exec_output += BasicExecute.subst(dsbIop)
 
     dmbIop = InstObjParams("dmb", "Dmb64", "ArmStaticInst", "",
-                           ['IsMemBarrier'])
+                           ['IsReadBarrier', 'IsWriteBarrier'])
     header_output += BasicDeclare.subst(dmbIop)
     decoder_output += BasicConstructor64.subst(dmbIop)
     exec_output += BasicExecute.subst(dmbIop)
index e99f6adc42489eb4addf0ad9f752207dc9c4371b..48bf153dd734902469725d2811d6ffbfd6fc5341 100644 (file)
@@ -187,8 +187,7 @@ let {{
                 self.memFlags.append("ArmISA::TLB::AllowUnaligned")
 
             if self.flavor in ("release", "relex"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
+                self.instFlags.extend(["IsWriteBarrier",
                                        "IsReadBarrier"])
                 self.memFlags.append("Request::RELEASE")
 
@@ -269,8 +268,7 @@ let {{
                 self.memFlags.append("ArmISA::TLB::AlignWord")
 
             if self.flavor in ("release", "relex"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
+                self.instFlags.extend(["IsWriteBarrier",
                                        "IsReadBarrier"])
                 self.memFlags.append("Request::RELEASE")
 
index ac845336a576cff84e9afd4961788306a27609f3..ed9906487c8fe277b91f1559dab8afa080f31324 100644 (file)
@@ -79,8 +79,7 @@ let {{
                 self.instFlags.append("IsMicroop")
 
             if self.flavor in ("release", "relex", "relexp"):
-                self.instFlags.extend(["IsMemBarrier",
-                                       "IsWriteBarrier",
+                self.instFlags.extend(["IsWriteBarrier",
                                        "IsReadBarrier"])
                 self.memFlags.append("Request::RELEASE")
 
index 0ad84c887f711a24ed3293c6fe0ed22a4072c097..c60db1752d368cc39e9abb663795e6cea7ff88ac 100644 (file)
@@ -38,8 +38,8 @@
 // A new class of Semihosting constructor templates has been added.
 // Their main purpose is to check if the Exception Generation
 // Instructions (HLT, SVC) are actually a semihosting command.
-// If that is the case, the IsMemBarrier flag is raised, so that
-// in the O3 model we perform a coherent memory access during
+// If that is the case, the IsReadBarrier and IsWriteBarrier flags are raised,
+// so that in the O3 model we perform a coherent memory access during
 // the semihosting operation.
 // Please note: since we don't have a thread context pointer in the
 // constructor we cannot check if semihosting is enabled in the
@@ -64,7 +64,8 @@ def template SemihostConstructor {{
         auto semihost_imm = machInst.thumb? %(thumb_semihost)s :
                                             %(arm_semihost)s;
         if (_imm == semihost_imm) {
-            flags[IsMemBarrier] = true;
+            flags[IsReadBarrier] = true;
+            flags[IsWriteBarrier] = true;
         }
     }
 }};
@@ -78,7 +79,8 @@ def template SemihostConstructor64 {{
         // In AArch64 there is only one instruction for issuing
         // semhosting commands: HLT #0xF000
         if (_imm == 0xF000) {
-            flags[IsMemBarrier] = true;
+            flags[IsReadBarrier] = true;
+            flags[IsWriteBarrier] = true;
         }
     }
 }};
index 73e2b5dc88269ea5615e923f05fce8847b00a141..3b2b0156ec4abc3f509564b1e84de113a647242a 100644 (file)
@@ -166,7 +166,7 @@ decode OPCODE_HI default Unknown::unknown() {
                             fault = std::make_shared<SystemCallFault>();
                         }});
                     }
-                    0x7: sync({{ ; }}, IsMemBarrier);
+                    0x7: sync({{ ; }}, IsReadBarrier, IsWriteBarrier);
                   0x5: break({{fault = std::make_shared<BreakpointFault>();}});
                 }
 
index b7b9afffc04523b966803882995e40ca43f30e5d..475ddcc009c4f97fdd5fe00b8ec87c794dd91a4f 100644 (file)
@@ -343,8 +343,8 @@ decode OPCODE default Unknown::unknown() {
         format MiscOp {
             278: dcbt({{ }});
             246: dcbtst({{ }});
-            598: sync({{ }}, [ IsMemBarrier ]);
-            854: eieio({{ }}, [ IsMemBarrier ]);
+            598: sync({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
+            854: eieio({{ }}, [ IsReadBarrier, IsWriteBarrier ]);
         }
     }
 
index 7b19464a67f125ecb3fe1b96201898fbe75a3068..b39005ff319a38480e8f6f33126d50401a40f17d 100644 (file)
@@ -421,7 +421,7 @@ decode QUADRANT default Unknown::unknown() {
         0x03: decode FUNCT3 {
             format FenceOp {
                 0x0: fence({{
-                }}, uint64_t, IsMemBarrier, No_OpClass);
+                }}, uint64_t, IsReadBarrier, IsWriteBarrier, No_OpClass);
                 0x1: fence_i({{
                 }}, uint64_t, IsNonSpeculative, IsSerializeAfter, No_OpClass);
             }
index 8c7a6a510220e5a11117fe502a8aba888cf6e2a6..7b151bd9cfa3352a66fa559cbe1fcbd9c73dcec8 100644 (file)
@@ -100,7 +100,8 @@ def template LRSCMacroConstructor {{
         if (RL) {
             rel_fence = new MemFenceMicro(machInst, No_OpClass);
             rel_fence->setFlag(IsFirstMicroop);
-            rel_fence->setFlag(IsMemBarrier);
+            rel_fence->setFlag(IsReadBarrier);
+            rel_fence->setFlag(IsWriteBarrier);
             rel_fence->setFlag(IsDelayedCommit);
         }
 
@@ -121,7 +122,8 @@ def template LRSCMacroConstructor {{
         if (AQ) {
             acq_fence = new MemFenceMicro(machInst, No_OpClass);
             acq_fence->setFlag(IsLastMicroop);
-            acq_fence->setFlag(IsMemBarrier);
+            acq_fence->setFlag(IsReadBarrier);
+            acq_fence->setFlag(IsWriteBarrier);
         }
 
         if (RL && AQ) {
@@ -159,7 +161,8 @@ def template AtomicMemOpMacroConstructor {{
         if (RL) {
             rel_fence = new MemFenceMicro(machInst, No_OpClass);
             rel_fence->setFlag(IsFirstMicroop);
-            rel_fence->setFlag(IsMemBarrier);
+            rel_fence->setFlag(IsReadBarrier);
+            rel_fence->setFlag(IsWriteBarrier);
             rel_fence->setFlag(IsDelayedCommit);
         }
 
@@ -180,7 +183,8 @@ def template AtomicMemOpMacroConstructor {{
         if (AQ) {
             acq_fence = new MemFenceMicro(machInst, No_OpClass);
             acq_fence->setFlag(IsLastMicroop);
-            acq_fence->setFlag(IsMemBarrier);
+            acq_fence->setFlag(IsReadBarrier);
+            acq_fence->setFlag(IsWriteBarrier);
         }
 
         if (RL && AQ) {
index 75a4d75785d7c2370ed98dbd619ac6f0a9d88612..c89a14132e0c3deb79db7ae908e55a51066ff58d 100644 (file)
@@ -335,7 +335,8 @@ decode OP default Unknown::unknown()
                 // 7-14 should cause an illegal instruction exception
                 0x0F: decode I {
                     0x0: Nop::stbar(IsWriteBarrier, MemWriteOp);
-                    0x1: Nop::membar(IsMemBarrier, MemReadOp);
+                    0x1: Nop::membar(IsReadBarrier, IsWriteBarrier,
+                                     MemReadOp);
                 }
                 0x10: Priv::rdpcr({{Rd = Pcr;}});
                 0x11: Priv::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
index 5d4514405d612edc47975544a2b4851423b880fb..e8b1e3d769852b2fa3689e7e551f58bc18fe45aa 100644 (file)
             //0x6: group15();
             0x6: decode MODRM_MOD {
                 0x3: decode MODRM_REG {
-                    0x5: BasicOperate::LFENCE(
-                                 {{/*Nothing*/}}, IsReadBarrier,
-                                 IsSerializeAfter);
-                    0x6: BasicOperate::MFENCE(
-                                 {{/*Nothing*/}}, IsMemBarrier);
-                    0x7: BasicOperate::SFENCE(
-                                 {{/*Nothing*/}}, IsWriteBarrier);
+                    0x5: BasicOperate::LFENCE({{/*Nothing*/}},
+                                              IsReadBarrier, IsSerializeAfter);
+                    0x6: BasicOperate::MFENCE({{/*Nothing*/}},
+                                              IsReadBarrier, IsWriteBarrier);
+                    0x7: BasicOperate::SFENCE({{/*Nothing*/}},
+                                              IsWriteBarrier);
                     default: Inst::UD2();
                 }
                 default: decode MODRM_REG {
index a7dda10cf251a5946ed4ee930de5a026e779d0fc..1d50569f08cf53f63a9d8a281084f5870051707f 100644 (file)
@@ -233,7 +233,8 @@ let {{
         def __init__(self):
             self.className = "Mfence"
             self.mnemonic = "mfence"
-            self.instFlags = "| (1ULL << StaticInst::IsMemBarrier)"
+            self.instFlags = "| (1ULL << StaticInst::IsReadBarrier)" + \
+                             "| (1ULL << StaticInst::IsWriteBarrier)"
 
         def getAllocator(self, microFlags):
             allocString = '''
index cbdfec3940e17bb0adf107de8f7b8c84ab6b689e..e11ee6813a5a62ad64343b84c3e979aba692262d 100644 (file)
@@ -40,11 +40,6 @@ from m5.params import *
 # - If IsControl is set, then exactly one of IsDirectControl or IsIndirect
 # Control will be set, and exactly one of IsCondControl or IsUncondControl
 # will be set.
-# - IsSerializing, IsMemBarrier, and IsWriteBarrier are implemented as flags
-# since in the current model there's no other way for instructions to inject
-# behavior into the pipeline outside of fetch.  Once we go to an exec-in-exec
-# CPU model we should be able to get rid of these flags and implement this
-# behavior via the execute() methods.
 
 class StaticInstFlags(Enum):
     wrapper_name = 'StaticInstFlags'
@@ -79,7 +74,6 @@ class StaticInstFlags(Enum):
                             # older instructions have committed.
         'IsSerializeBefore',
         'IsSerializeAfter',
-        'IsMemBarrier',     # Is a memory barrier
         'IsWriteBarrier',   # Is a write barrier
         'IsReadBarrier',    # Is a read barrier
 
index 64ed060aca005a343cebb71074e8a82bff04bba1..fd216b173e5f315e7955c03947f686ee6d18d44e 100644 (file)
@@ -553,7 +553,8 @@ class BaseDynInst : public ExecContext, public RefCounted
         return staticInst->isSerializeAfter() || status[SerializeAfter];
     }
     bool isSquashAfter() const { return staticInst->isSquashAfter(); }
-    bool isMemBarrier()   const { return staticInst->isMemBarrier(); }
+    bool isFullMemBarrier()   const { return staticInst->isFullMemBarrier(); }
+    bool isReadBarrier() const { return staticInst->isReadBarrier(); }
     bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
     bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
     bool isQuiesce() const { return staticInst->isQuiesce(); }
index f8db5231a401961c718eb23b2dd27c07eb576723..0833224996517b1b973fe7612f5ac41a58a133cd 100644 (file)
@@ -781,7 +781,7 @@ Execute::issue(ThreadID thread_id)
 
             /* Mark up barriers in the LSQ */
             if (!discarded && inst->isInst() &&
-                inst->staticInst->isMemBarrier())
+                inst->staticInst->isFullMemBarrier())
             {
                 DPRINTF(MinorMem, "Issuing memory barrier inst: %s\n", *inst);
                 lsq.issuedMemBarrierInst(inst);
@@ -951,7 +951,7 @@ Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
             completed_inst = completed_mem_inst;
         }
         completed_mem_issue = completed_inst;
-    } else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
+    } else if (inst->isInst() && inst->staticInst->isFullMemBarrier() &&
         !lsq.canPushIntoStoreBuffer())
     {
         DPRINTF(MinorExecute, "Can't commit data barrier inst: %s yet as"
@@ -1368,7 +1368,7 @@ Execute::commit(ThreadID thread_id, bool only_commit_microops, bool discard,
             ex_info.inFlightInsts->pop();
 
             /* Complete barriers in the LSQ/move to store buffer */
-            if (inst->isInst() && inst->staticInst->isMemBarrier()) {
+            if (inst->isInst() && inst->staticInst->isFullMemBarrier()) {
                 DPRINTF(MinorMem, "Completing memory barrier"
                     " inst: %s committed: %d\n", *inst, committed_inst);
                 lsq.completeMemBarrierInst(inst, committed_inst);
index 106b51b6e7532b35d1c2181029a890139e458df4..d8c1c7a3bf9b92fbe72d2bbbaac77fd0b41f35bf 100644 (file)
@@ -154,7 +154,7 @@ LSQ::LSQRequest::containsAddrRangeOf(LSQRequestPtr other_request)
 bool
 LSQ::LSQRequest::isBarrier()
 {
-    return inst->isInst() && inst->staticInst->isMemBarrier();
+    return inst->isInst() && inst->staticInst->isFullMemBarrier();
 }
 
 bool
@@ -1711,7 +1711,7 @@ makePacketForRequest(const RequestPtr &request, bool isLoad,
 void
 LSQ::issuedMemBarrierInst(MinorDynInstPtr inst)
 {
-    assert(inst->isInst() && inst->staticInst->isMemBarrier());
+    assert(inst->isInst() && inst->staticInst->isFullMemBarrier());
     assert(inst->id.execSeqNum > lastMemBarrier[inst->id.threadId]);
 
     /* Remember the barrier.  We only have a notion of one
index 0d5cbe5db9ed82ef80f528a863bc7bbac54bf1a8..f6a2e2e6edf8ca6747f38200c1c1d51beb4e4d17 100644 (file)
@@ -1196,7 +1196,7 @@ DefaultCommit<Impl>::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
         // Make sure we are only trying to commit un-executed instructions we
         // think are possible.
         assert(head_inst->isNonSpeculative() || head_inst->isStoreConditional()
-               || head_inst->isMemBarrier() || head_inst->isWriteBarrier()
+               || head_inst->isReadBarrier() || head_inst->isWriteBarrier()
                || head_inst->isAtomic()
                || (head_inst->isLoad() && head_inst->strictlyOrdered()));
 
@@ -1462,7 +1462,7 @@ DefaultCommit<Impl>::updateComInstStats(const DynInstPtr &inst)
         }
     }
 
-    if (inst->isMemBarrier()) {
+    if (inst->isFullMemBarrier()) {
         stats.membars[tid]++;
     }
 
index 497c5321b61820e31f9775d6fbea589f7a11a034..b39001dbc8b6c2b56062f471c01d264d6488953c 100644 (file)
@@ -1119,7 +1119,7 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid)
             }
 
             toRename->iewInfo[tid].dispatchedToSQ++;
-        } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
+        } else if (inst->isReadBarrier() || inst->isWriteBarrier()) {
             // Same as non-speculative stores.
             inst->setCanCommit();
             instQueue.insertBarrier(inst);
index ff5b3be4fe54d5687b39097019177366590c79f5..19ed49a5dbfd333ecfee7dc8eb2af70622f2943b 100644 (file)
@@ -1014,7 +1014,7 @@ InstructionQueue<Impl>::wakeDependents(const DynInstPtr &completed_inst)
         ++freeEntries;
         completed_inst->memOpDone(true);
         count[tid]--;
-    } else if (completed_inst->isMemBarrier() ||
+    } else if (completed_inst->isReadBarrier() ||
                completed_inst->isWriteBarrier()) {
         // Completes a non mem ref barrier
         memDepUnit[tid].completeInst(completed_inst);
@@ -1245,7 +1245,7 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
             DPRINTF(IQ, "[tid:%i] Instruction [sn:%llu] PC %s squashed.\n",
                     tid, squashed_inst->seqNum, squashed_inst->pcState());
 
-            bool is_acq_rel = squashed_inst->isMemBarrier() &&
+            bool is_acq_rel = squashed_inst->isFullMemBarrier() &&
                          (squashed_inst->isLoad() ||
                           (squashed_inst->isStore() &&
                              !squashed_inst->isStoreConditional()));
@@ -1255,7 +1255,7 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
                 (!squashed_inst->isNonSpeculative() &&
                  !squashed_inst->isStoreConditional() &&
                  !squashed_inst->isAtomic() &&
-                 !squashed_inst->isMemBarrier() &&
+                 !squashed_inst->isReadBarrier() &&
                  !squashed_inst->isWriteBarrier())) {
 
                 for (int src_reg_idx = 0;
index 4be98c51d0dd16cc2b4779d959e580cdd6d72ce7..7b83efdf43b922d16d7a64cd41d3cb2d506b520a 100644 (file)
@@ -44,6 +44,7 @@
 #include <map>
 #include <vector>
 
+#include "base/debug.hh"
 #include "cpu/o3/inst_queue.hh"
 #include "cpu/o3/mem_dep_unit.hh"
 #include "debug/MemDepUnit.hh"
@@ -171,24 +172,31 @@ void
 MemDepUnit<MemDepPred, Impl>::insertBarrierSN(const DynInstPtr &barr_inst)
 {
     InstSeqNum barr_sn = barr_inst->seqNum;
-    // Memory barriers block loads and stores, write barriers only stores.
-    // Required also for hardware transactional memory commands which
-    // can have strict ordering semantics
-    if (barr_inst->isMemBarrier() || barr_inst->isHtmCmd()) {
+
+    if (barr_inst->isReadBarrier() || barr_inst->isHtmCmd())
         loadBarrierSNs.insert(barr_sn);
+    if (barr_inst->isWriteBarrier() || barr_inst->isHtmCmd())
         storeBarrierSNs.insert(barr_sn);
-        DPRINTF(MemDepUnit, "Inserted a memory barrier %s SN:%lli\n",
-                barr_inst->pcState(), barr_sn);
-    } else if (barr_inst->isWriteBarrier()) {
-        storeBarrierSNs.insert(barr_sn);
-        DPRINTF(MemDepUnit, "Inserted a write barrier %s SN:%lli\n",
-                barr_inst->pcState(), barr_sn);
-    }
 
-    if (loadBarrierSNs.size() || storeBarrierSNs.size()) {
-        DPRINTF(MemDepUnit, "Outstanding load barriers = %d; "
-                            "store barriers = %d\n",
-                loadBarrierSNs.size(), storeBarrierSNs.size());
+    if (DTRACE(MemDepUnit)) {
+        const char *barrier_type = nullptr;
+        if (barr_inst->isReadBarrier() && barr_inst->isWriteBarrier())
+            barrier_type = "memory";
+        else if (barr_inst->isReadBarrier())
+            barrier_type = "read";
+        else if (barr_inst->isWriteBarrier())
+            barrier_type = "write";
+
+        if (barrier_type) {
+            DPRINTF(MemDepUnit, "Inserted a %s barrier %s SN:%lli\n",
+                    barrier_type, barr_inst->pcState(), barr_sn);
+        }
+
+        if (loadBarrierSNs.size() || storeBarrierSNs.size()) {
+            DPRINTF(MemDepUnit, "Outstanding load barriers = %d; "
+                                "store barriers = %d\n",
+                    loadBarrierSNs.size(), storeBarrierSNs.size());
+        }
     }
 }
 
@@ -444,18 +452,27 @@ MemDepUnit<MemDepPred, Impl>::completeInst(const DynInstPtr &inst)
     completed(inst);
     InstSeqNum barr_sn = inst->seqNum;
 
-    if (inst->isMemBarrier() || inst->isHtmCmd()) {
-        assert(hasLoadBarrier());
+    if (inst->isWriteBarrier() || inst->isHtmCmd()) {
         assert(hasStoreBarrier());
-        loadBarrierSNs.erase(barr_sn);
         storeBarrierSNs.erase(barr_sn);
-        DPRINTF(MemDepUnit, "Memory barrier completed: %s SN:%lli\n",
-                            inst->pcState(), inst->seqNum);
-    } else if (inst->isWriteBarrier()) {
-        assert(hasStoreBarrier());
-        storeBarrierSNs.erase(barr_sn);
-        DPRINTF(MemDepUnit, "Write barrier completed: %s SN:%lli\n",
-                            inst->pcState(), inst->seqNum);
+    }
+    if (inst->isReadBarrier() || inst->isHtmCmd()) {
+        assert(hasLoadBarrier());
+        loadBarrierSNs.erase(barr_sn);
+    }
+    if (DTRACE(MemDepUnit)) {
+        const char *barrier_type = nullptr;
+        if (inst->isWriteBarrier() && inst->isReadBarrier())
+            barrier_type = "Memory";
+        else if (inst->isWriteBarrier())
+            barrier_type = "Write";
+        else if (inst->isReadBarrier())
+            barrier_type = "Read";
+
+        if (barrier_type) {
+            DPRINTF(MemDepUnit, "%s barrier completed: %s SN:%lli\n",
+                                barrier_type, inst->pcState(), inst->seqNum);
+        }
     }
 }
 
@@ -463,9 +480,8 @@ template <class MemDepPred, class Impl>
 void
 MemDepUnit<MemDepPred, Impl>::wakeDependents(const DynInstPtr &inst)
 {
-    // Only stores, atomics, barriers and
-    // hardware transactional memory commands have dependents.
-    if (!inst->isStore() && !inst->isAtomic() && !inst->isMemBarrier() &&
+    // Only stores, atomics and barriers have dependents.
+    if (!inst->isStore() && !inst->isAtomic() && !inst->isReadBarrier() &&
         !inst->isWriteBarrier() && !inst->isHtmCmd()) {
         return;
     }
index f77193a4488b3446ee0052a517597715b638807e..258749c4c858413978a7b8fa21aa71a64400ebfb 100644 (file)
@@ -185,7 +185,12 @@ class StaticInst : public RefCounted, public StaticInstFlags
     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
+    isFullMemBarrier() const
+    {
+        return flags[IsReadBarrier] && flags[IsWriteBarrier];
+    }
+    bool isReadBarrier() const { return flags[IsReadBarrier]; }
     bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
     bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
     bool isQuiesce() const { return flags[IsQuiesce]; }