Giacomo Gabrielli has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/13520

Change subject: cpu-o3: Add support for pinned writes
......................................................................

cpu-o3: Add support for pinned writes

This patch adds support for pinning registers for a certain number of
consecutive writes.  This is only relevant for timing CPU models
(functional-only models are unaffected), and it is primarily needed to
provide a realistic execution model for micro-coded operations whose
microops can write to non-overlapping portions of a destination
register, e.g.  vector gather loads.  In those cases, this mechanism
can disable renaming for a sequence of consecutive writes, thus making
the resulting execution more efficient: allocating a new physical
register for each microop would introduce a read-modify-write chain of
dependencies, while with these modifications the microops can write
back in parallel.

Please note that this new feature is only leveraged by O3CPU for the
time being.

Change-Id: I07eb5fdbd1fa0b748c9bdc1174d9f330fda34f81
Signed-off-by: Giacomo Gabrielli <[email protected]>
---
M src/cpu/o3/comm.hh
M src/cpu/o3/free_list.hh
M src/cpu/o3/iew_impl.hh
M src/cpu/o3/inst_queue_impl.hh
M src/cpu/o3/regfile.cc
M src/cpu/o3/regfile.hh
M src/cpu/o3/rename_impl.hh
M src/cpu/o3/rename_map.cc
M src/cpu/reg_class.hh
9 files changed, 92 insertions(+), 41 deletions(-)



diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh
index 67411cd..95d1d93 100644
--- a/src/cpu/o3/comm.hh
+++ b/src/cpu/o3/comm.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016-2017 ARM Limited
+ * Copyright (c) 2011, 2016-2018 ARM Limited
  * Copyright (c) 2013 Advanced Micro Devices, Inc.
  * All rights reserved
  *
@@ -65,20 +65,26 @@
 class PhysRegId : private RegId {
   private:
     PhysRegIndex flatIdx;
+    int numPinnedWritesToComplete;

   public:
-    explicit PhysRegId() : RegId(IntRegClass, -1), flatIdx(-1) {}
+    explicit PhysRegId() : RegId(IntRegClass, -1), flatIdx(-1),
+                           numPinnedWritesToComplete(0)
+    {}

     /** Scalar PhysRegId constructor. */
     explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
               PhysRegIndex _flatIdx)
-        : RegId(_regClass, _regIdx), flatIdx(_flatIdx)
+        : RegId(_regClass, _regIdx), flatIdx(_flatIdx),
+          numPinnedWritesToComplete(0)
     {}

     /** Vector PhysRegId constructor (w/ elemIndex). */
     explicit PhysRegId(RegClass _regClass, PhysRegIndex _regIdx,
               ElemIndex elem_idx, PhysRegIndex flat_idx)
-        : RegId(_regClass, _regIdx, elem_idx), flatIdx(flat_idx) { }
+        : RegId(_regClass, _regIdx, elem_idx), flatIdx(flat_idx),
+          numPinnedWritesToComplete(0)
+    {}

     /** Visible RegId methods */
     /** @{ */
@@ -139,17 +145,35 @@
     /** Flat index accessor */
     const PhysRegIndex& flatIndex() const { return flatIdx; }

-    static PhysRegId elemId(const PhysRegId* vid, ElemIndex elem)
+    static PhysRegId elemId(PhysRegId* vid, ElemIndex elem)
     {
         assert(vid->isVectorPhysReg());
         return PhysRegId(VecElemClass, vid->index(), elem);
     }
+
+    int getNumPinnedWrites() const { return numPinnedWrites; }
+
+    void setNumPinnedWrites(int numWrites)
+    {
+        numPinnedWrites = numWrites;
+    }
+
+    void decrNumPinnedWrites() { --numPinnedWrites; }
+
+    int getNumPinnedWritesToComplete() const
+    {
+        return numPinnedWritesToComplete;
+    }
+
+    void setNumPinnedWritesToComplete(int numWrites)
+    {
+        numPinnedWritesToComplete = numWrites;
+    }
+
+    void decrNumPinnedWritesToComplete() { --numPinnedWritesToComplete; }
 };

-/** Constant pointer definition.
- * PhysRegIds only need to be created once and then we can just share
- * pointers */
-using PhysRegIdPtr = const PhysRegId*;
+using PhysRegIdPtr = PhysRegId*;

 /** Struct that defines the information passed from fetch to decode. */
 template<class Impl>
diff --git a/src/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh
index e270fef..3536a02 100644
--- a/src/cpu/o3/free_list.hh
+++ b/src/cpu/o3/free_list.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -79,10 +79,9 @@
     template<class InputIt>
     void
     addRegs(InputIt first, InputIt last) {
-        std::for_each(first, last,
-            [this](const typename InputIt::value_type& reg) {
-                this->freeRegs.push(&reg);
-            });
+ std::for_each(first, last, [this](typename InputIt::value_type& reg) {
+            this->freeRegs.push(&reg);
+        });
     }

     /** Get the next available register from the free list */
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 266355a..dd79383 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -1433,11 +1433,14 @@
             int dependents = instQueue.wakeDependents(inst);

             for (int i = 0; i < inst->numDestRegs(); i++) {
-                //mark as Ready
-                DPRINTF(IEW,"Setting Destination Register %i (%s)\n",
-                        inst->renamedDestRegIdx(i)->index(),
-                        inst->renamedDestRegIdx(i)->className());
-                scoreboard->setReg(inst->renamedDestRegIdx(i));
+                // Mark register as ready if not pinned
+                if (inst->renamedDestRegIdx(i)->
+                        getNumPinnedWritesToComplete() == 0) {
+                    DPRINTF(IEW,"Setting Destination Register %i (%s)\n",
+                            inst->renamedDestRegIdx(i)->index(),
+                            inst->renamedDestRegIdx(i)->className());
+                    scoreboard->setReg(inst->renamedDestRegIdx(i));
+                }
             }

             if (dependents) {
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index 3245458..b704144 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -1045,6 +1045,14 @@
             continue;
         }

+        // Avoid waking up dependents if the register is pinned
+        if (dest_reg->getNumPinnedWritesToComplete() != 0) {
+            dest_reg->decrNumPinnedWritesToComplete();
+            DPRINTF(IQ, "Reg %d [%s] is pinned, skipping\n",
+                    dest_reg->index(), dest_reg->className());
+            continue;
+        }
+
         DPRINTF(IQ, "Waking any dependents on register %i (%s).\n",
                 dest_reg->index(),
                 dest_reg->className());
diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc
index b48d38a..ce3b644 100644
--- a/src/cpu/o3/regfile.cc
+++ b/src/cpu/o3/regfile.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -216,8 +216,8 @@
         return std::make_pair(miscRegIds.begin(), miscRegIds.end());
     }
     /* There is no way to make an empty iterator */
-    return std::make_pair(PhysIds::const_iterator(),
-                          PhysIds::const_iterator());
+    return std::make_pair(PhysIds::iterator(),
+                          PhysIds::iterator());
 }

 PhysRegIdPtr
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
index 013bd6a..01e8faa 100644
--- a/src/cpu/o3/regfile.hh
+++ b/src/cpu/o3/regfile.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -75,8 +75,8 @@
     using VecMode = Enums::VecRegRenameMode;
     using PredRegContainer = TheISA::PredRegContainer;
   public:
-    using IdRange = std::pair<PhysIds::const_iterator,
-                              PhysIds::const_iterator>;
+    using IdRange = std::pair<PhysIds::iterator,
+                              PhysIds::iterator>;
   private:
static constexpr auto NumVecElemPerVecReg = TheISA::NumVecElemPerVecReg;

diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index 700ea60..81ad31c 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012, 2014-2016 ARM Limited
+ * Copyright (c) 2010-2012, 2014-2018 ARM Limited
  * Copyright (c) 2013 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
@@ -1098,13 +1098,17 @@
         typename RenameMap::RenameInfo rename_result;

         RegId flat_dest_regid = tc->flattenRegId(dest_reg);
+        flat_dest_regid.setNumPinnedWrites(dest_reg.getNumPinnedWrites());

         rename_result = map->rename(flat_dest_regid);

         inst->flattenDestReg(dest_idx, flat_dest_regid);

-        // Mark Scoreboard entry as not ready
-        scoreboard->unsetReg(rename_result.first);
+        if (rename_result.first->getNumPinnedWrites() == 0) {
+            // Mark scoreboard entry as not ready (only once for pinned
+            // registers)
+            scoreboard->unsetReg(rename_result.first);
+        }

         DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i (%s) to physical "
                 "reg %i (%i).\n", tid, dest_reg.index(),
diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc
index c6a49e4..d76f22b 100644
--- a/src/cpu/o3/rename_map.cc
+++ b/src/cpu/o3/rename_map.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -78,16 +78,21 @@
     // requested architected register.
     PhysRegIdPtr prev_reg = map[arch_reg.index()];

-    // If it's not referencing the zero register, then rename the
-    // register.
-    if (arch_reg != zeroReg) {
-        renamed_reg = freeList->getReg();
-
-        map[arch_reg.index()] = renamed_reg;
-    } else {
-        // Otherwise return the zero register so nothing bad happens.
+    if (arch_reg == zeroReg) {
         assert(prev_reg->isZeroReg());
         renamed_reg = prev_reg;
+    } else if (prev_reg->getNumPinnedWrites() > 0) {
+        // Do not rename if the register is pinned
+        assert(arch_reg.getNumPinnedWrites() == 0);  // Prevent pinning the
+                                                     // same register twice
+        renamed_reg = prev_reg;
+        renamed_reg->decrNumPinnedWrites();
+    } else {
+        renamed_reg = freeList->getReg();
+        map[arch_reg.index()] = renamed_reg;
+        renamed_reg->setNumPinnedWrites(arch_reg.getNumPinnedWrites());
+        renamed_reg->setNumPinnedWritesToComplete(
+            arch_reg.getNumPinnedWrites());
     }

DPRINTF(Rename, "Renamed reg %d to physical reg %d (%d) old mapping was"
diff --git a/src/cpu/reg_class.hh b/src/cpu/reg_class.hh
index 9c5bd8a..5fbdc1e 100644
--- a/src/cpu/reg_class.hh
+++ b/src/cpu/reg_class.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 ARM Limited
+ * Copyright (c) 2016-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -77,24 +77,29 @@
  * index 3 is represented by Regid(IntRegClass, 3).
  */
 class RegId {
-  private:
+  protected:
     static const char* regClassStrings[];
     RegClass regClass;
     RegIndex regIdx;
     ElemIndex elemIdx;
     static constexpr size_t Scale = TheISA::NumVecElemPerVecReg;
+    int numPinnedWrites;
+
     friend struct std::hash<RegId>;
+
   public:
     RegId() : regClass(IntRegClass), regIdx(0), elemIdx(-1) {}
     RegId(RegClass reg_class, RegIndex reg_idx)
-        : regClass(reg_class), regIdx(reg_idx), elemIdx(-1)
+        : regClass(reg_class), regIdx(reg_idx), elemIdx(-1),
+          numPinnedWrites(0)
     {
         panic_if(regClass == VecElemClass,
                 "Creating vector physical index w/o element index");
     }

explicit RegId(RegClass reg_class, RegIndex reg_idx, ElemIndex elem_idx)
-        : regClass(reg_class), regIdx(reg_idx), elemIdx(elem_idx)
+        : regClass(reg_class), regIdx(reg_idx), elemIdx(elem_idx),
+          numPinnedWrites(0)
     {
         panic_if(regClass != VecElemClass,
                 "Creating non-vector physical index w/ element index");
@@ -202,6 +207,9 @@
     /** Return a const char* with the register class name. */
     const char* className() const { return regClassStrings[regClass]; }

+    int getNumPinnedWrites() const { return numPinnedWrites; }
+ void setNumPinnedWrites(int num_writes) { numPinnedWrites = num_writes; }
+
     friend std::ostream&
     operator<<(std::ostream& os, const RegId& rid) {
         return os << rid.className() << "{" << rid.index() << "}";

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/13520
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I07eb5fdbd1fa0b748c9bdc1174d9f330fda34f81
Gerrit-Change-Number: 13520
Gerrit-PatchSet: 1
Gerrit-Owner: Giacomo Gabrielli <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to