cpu: Turn the stage 2 ARM MMUs from params to children.
[gem5.git] / src / cpu / reg_class.hh
index 25c882c5841cdf2f68e97fb2a9530e2945cb19eb..e71e938bf1e5d0d4abbab52b9161ce883949fd9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 ARM Limited
+ * Copyright (c) 2016-2019 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -39,6 +39,7 @@
  *
  * Authors: Steve Reinhardt
  *          Nathanael Premillieu
+ *          Rekai Gonzalez
  */
 
 #ifndef __CPU__REG_CLASS_HH__
 #include "arch/registers.hh"
 #include "config/the_isa.hh"
 
-/// Enumerate the classes of registers.
+/** Enumerate the classes of registers. */
 enum RegClass {
     IntRegClass,        ///< Integer register
     FloatRegClass,      ///< Floating-point register
+    /** Vector Register. */
+    VecRegClass,
+    /** Vector Register Native Elem lane. */
+    VecElemClass,
+    VecPredRegClass,
     CCRegClass,         ///< Condition-code register
     MiscRegClass        ///< Control (misc) register
 };
 
-/// Number of register classes.  This value is not part of the enum,
-/// because putting it there makes the compiler complain about
-/// unhandled cases in some switch statements.
+/** Number of register classes.
+ * This value is not part of the enum, because putting it there makes the
+ * compiler complain about unhandled cases in some switch statements.
+ */
 const int NumRegClasses = MiscRegClass + 1;
 
-/// Register ID: describe an architectural register with its class and index.
-/// This structure is used instead of just the register index to disambiguate
-/// between different classes of registers.
-/// For example, a integer register with index 3 is represented by
-/// Regid(IntRegClass, 3).
-struct RegId {
+/** Register ID: describe an architectural register with its class and index.
+ * This structure is used instead of just the register index to disambiguate
+ * between different classes of registers. For example, a integer register with
+ * index 3 is represented by Regid(IntRegClass, 3).
+ */
+class RegId {
+  protected:
+    static const char* regClassStrings[];
     RegClass regClass;
     RegIndex regIdx;
-    RegId() {};
+    ElemIndex elemIdx;
+    static constexpr size_t Scale = TheISA::NumVecElemPerVecReg;
+    int numPinnedWrites;
+
+    friend struct std::hash<RegId>;
+
+  public:
+    RegId() : RegId(IntRegClass, 0) {}
+
     RegId(RegClass reg_class, RegIndex reg_idx)
-        : regClass(reg_class), regIdx(reg_idx)
-    {}
+        : RegId(reg_class, reg_idx, ILLEGAL_ELEM_INDEX) {}
+
+    explicit RegId(RegClass reg_class, RegIndex reg_idx, ElemIndex elem_idx)
+        : regClass(reg_class), regIdx(reg_idx), elemIdx(elem_idx),
+          numPinnedWrites(0) {
+        if (elemIdx == ILLEGAL_ELEM_INDEX) {
+            panic_if(regClass == VecElemClass,
+                    "Creating vector physical index w/o element index");
+        } else {
+            panic_if(regClass != VecElemClass,
+                    "Creating non-vector physical index w/ element index");
+        }
+    }
 
     bool operator==(const RegId& that) const {
-        return regClass == that.regClass && regIdx == that.regIdx;
+        return regClass == that.classValue() && regIdx == that.index()
+                                             && elemIdx == that.elemIndex();
     }
 
     bool operator!=(const RegId& that) const {
         return !(*this==that);
     }
 
+    /** Order operator.
+     * The order is required to implement maps with key type RegId
+     */
+    bool operator<(const RegId& that) const {
+        return regClass < that.classValue() ||
+            (regClass == that.classValue() && (
+                   regIdx < that.index() ||
+                   (regIdx == that.index() && elemIdx < that.elemIndex())));
+    }
+
     /**
+     * Return true if this register can be renamed
+     */
+    bool isRenameable() const
+    {
+        return regClass != MiscRegClass;
+    }
+
+    /**
+     * Check if this is the zero register.
      * Returns true if this register is a zero register (needs to have a
-     * constant zero value throughout the execution)
+     * constant zero value throughout the execution).
      */
-    bool isZeroReg() const
+
+    inline bool isZeroReg() const
     {
-        return (regIdx == TheISA::ZeroReg &&
-                (regClass == IntRegClass ||
-                 (THE_ISA == ALPHA_ISA && regClass == FloatRegClass)));
+        return ((regClass == IntRegClass && regIdx == TheISA::ZeroReg) ||
+               (THE_ISA == ALPHA_ISA && regClass == FloatRegClass &&
+                regIdx == TheISA::ZeroReg));
     }
 
+    /** @return true if it is an integer physical register. */
+    bool isIntReg() const { return regClass == IntRegClass; }
+
+    /** @return true if it is a floating-point physical register. */
+    bool isFloatReg() const { return regClass == FloatRegClass; }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isVecReg() const { return regClass == VecRegClass; }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isVecElem() const { return regClass == VecElemClass; }
+
+    /** @Return true if it is a predicate physical register. */
+    bool isVecPredReg() const { return regClass == VecPredRegClass; }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isCCReg() const { return regClass == CCRegClass; }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isMiscReg() const { return regClass == MiscRegClass; }
+
     /**
      * Return true if this register can be renamed
      */
@@ -104,9 +174,209 @@ struct RegId {
         return regClass != MiscRegClass;
     }
 
-    static const RegId zeroReg;
+    /** Index accessors */
+    /** @{ */
+    const RegIndex& index() const { return regIdx; }
+    RegIndex& index() { return regIdx; }
+
+    /** Index flattening.
+     * Required to be able to use a vector for the register mapping.
+     */
+    inline RegIndex flatIndex() const
+    {
+        switch (regClass) {
+          case IntRegClass:
+          case FloatRegClass:
+          case VecRegClass:
+          case VecPredRegClass:
+          case CCRegClass:
+          case MiscRegClass:
+            return regIdx;
+          case VecElemClass:
+            return Scale*regIdx + elemIdx;
+        }
+        panic("Trying to flatten a register without class!");
+        return -1;
+    }
+    /** @} */
+
+    /** Elem accessor */
+    const RegIndex& elemIndex() const { return elemIdx; }
+    /** Class accessor */
+    const RegClass& classValue() const { return regClass; }
+    /** 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() << "}";
+    }
+};
+
+/** Physical register index type.
+ * Although the Impl might be a better for this, but there are a few classes
+ * that need this typedef yet are not templated on the Impl.
+ */
+using PhysRegIndex = short int;
+
+/** Physical register ID.
+ * Like a register ID but physical. The inheritance is private because the
+ * only relationship between this types is functional, and it is done to
+ * prevent code replication. */
+class PhysRegId : private RegId {
+  private:
+    PhysRegIndex flatIdx;
+    int numPinnedWritesToComplete;
+    bool pinned;
+
+  public:
+    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),
+          numPinnedWritesToComplete(0), pinned(false)
+    {}
+
+    /** 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),
+          numPinnedWritesToComplete(0), pinned(false)
+    {}
+
+    /** Visible RegId methods */
+    /** @{ */
+    using RegId::index;
+    using RegId::classValue;
+    using RegId::isZeroReg;
+    using RegId::className;
+    using RegId::elemIndex;
+     /** @} */
+    /**
+     * Explicit forward methods, to prevent comparisons of PhysRegId with
+     * RegIds.
+     */
+    /** @{ */
+    bool operator<(const PhysRegId& that) const {
+        return RegId::operator<(that);
+    }
+
+    bool operator==(const PhysRegId& that) const {
+        return RegId::operator==(that);
+    }
+
+    bool operator!=(const PhysRegId& that) const {
+        return RegId::operator!=(that);
+    }
+    /** @} */
+
+    /** @return true if it is an integer physical register. */
+    bool isIntPhysReg() const { return isIntReg(); }
+
+    /** @return true if it is a floating-point physical register. */
+    bool isFloatPhysReg() const { return isFloatReg(); }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isCCPhysReg() const { return isCCReg(); }
+
+    /** @Return true if it is a vector physical register. */
+    bool isVectorPhysReg() const { return isVecReg(); }
+
+    /** @Return true if it is a vector element physical register. */
+    bool isVectorPhysElem() const { return isVecElem(); }
+
+    /** @return true if it is a vector predicate physical register. */
+    bool isVecPredPhysReg() const { return isVecPredReg(); }
+
+    /** @Return true if it is a  condition-code physical register. */
+    bool isMiscPhysReg() const { return isMiscReg(); }
+
+    /**
+     * Returns true if this register is always associated to the same
+     * architectural register.
+     */
+    bool isFixedMapping() const
+    {
+        return !isRenameable();
+    }
+
+    /** Flat index accessor */
+    const PhysRegIndex& flatIndex() const { return flatIdx; }
+
+    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)
+    {
+        // An instruction with a pinned destination reg can get
+        // squashed. The numPinnedWrites counter may be zero when
+        // the squash happens but we need to know if the dest reg
+        // was pinned originally in order to reset counters properly
+        // for a possible re-rename using the same physical reg (which
+        // may be required in case of a mem access order violation).
+        pinned = (numWrites != 0);
+        numPinnedWrites = numWrites;
+    }
+
+    void decrNumPinnedWrites() { --numPinnedWrites; }
+    void incrNumPinnedWrites() { ++numPinnedWrites; }
+
+    bool isPinned() const { return pinned; }
+
+    int getNumPinnedWritesToComplete() const
+    {
+        return numPinnedWritesToComplete;
+    }
+
+    void setNumPinnedWritesToComplete(int numWrites)
+    {
+        numPinnedWritesToComplete = numWrites;
+    }
+
+    void decrNumPinnedWritesToComplete() { --numPinnedWritesToComplete; }
+    void incrNumPinnedWritesToComplete() { ++numPinnedWritesToComplete; }
+};
+
+using PhysRegIdPtr = PhysRegId*;
+
+namespace std
+{
+template<>
+struct hash<RegId>
+{
+    size_t operator()(const RegId& reg_id) const
+    {
+        // Extract unique integral values for the effective fields of a RegId.
+        const size_t flat_index = static_cast<size_t>(reg_id.flatIndex());
+        const size_t class_num = static_cast<size_t>(reg_id.regClass);
+
+        const size_t shifted_class_num = class_num << (sizeof(RegIndex) << 3);
+
+        // Concatenate the class_num to the end of the flat_index, in order to
+        // maximize information retained.
+        const size_t concatenated_hash = flat_index | shifted_class_num;
+
+        // If RegIndex is larger than size_t, then class_num will not be
+        // considered by this hash function, so we may wish to perform a
+        // different operation to include that information in the hash.
+        static_assert(sizeof(RegIndex) < sizeof(size_t),
+            "sizeof(RegIndex) should be less than sizeof(size_t)");
+
+        return concatenated_hash;
+    }
 };
+}
 
-/// Map enum values to strings for debugging
-extern const char *RegClassStrings[];
 #endif // __CPU__REG_CLASS_HH__