Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/41733 )

Change subject: arch,cpu: Create register class descriptors.
......................................................................

arch,cpu: Create register class descriptors.

These currently only hold the number of registers in a particular class,
but can be extended in the future to hold other information about each
class. The ISA class holds a vector of descriptors which other parts of
gem5 can retrieve to set up storage for each class, etc.

Currently, the RegClass enum is used to explicitly index into the vector
of descriptors to get information about a particular class. Once enough
information is stored in the descriptors, the other parts of gem5 should
be able to set up for each register class generically, and the ISAs will
be able to leave out or create new register classes without having to
set up global plumbing for it.

The more immediate benefit is that this should (mostly) parameterize
away the ISA register constants to break another TheISA style
dependency. Currently a global set of descriptors are set up in the
BaseISA class using the old TheISA constants, but it should be easy to
break those out and make the ISAs set up their own descriptors. That
will bring arch/registers.hh significantly closer to being eliminated.

Change-Id: I6d6d1256288f880391246b71045482a4a03c4198
---
M src/arch/generic/isa.hh
M src/cpu/minor/execute.cc
M src/cpu/minor/scoreboard.cc
M src/cpu/minor/scoreboard.hh
M src/cpu/o3/cpu.cc
M src/cpu/o3/free_list.cc
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/o3/rename_map.hh
M src/cpu/reg_class.hh
M src/cpu/simple_thread.cc
M src/cpu/simple_thread.hh
M src/cpu/thread_context.cc
15 files changed, 249 insertions(+), 167 deletions(-)



diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh
index 4c717c7..8b8b2db 100644
--- a/src/arch/generic/isa.hh
+++ b/src/arch/generic/isa.hh
@@ -40,23 +40,44 @@
 #ifndef __ARCH_GENERIC_ISA_HH__
 #define __ARCH_GENERIC_ISA_HH__

+#include <vector>
+
+#include "arch/registers.hh"
+#include "cpu/reg_class.hh"
 #include "sim/sim_object.hh"

 class ThreadContext;

 class BaseISA : public SimObject
 {
+  public:
+    typedef std::vector<RegClassInfo> RegClasses;
+
   protected:
     using SimObject::SimObject;

     ThreadContext *tc = nullptr;

+    RegClasses _regClasses = {
+#if THE_ISA != NULL_ISA
+        { TheISA::NumIntRegs },
+        { TheISA::NumFloatRegs },
+        { TheISA::NumVecRegs },
+        { TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg },
+        { TheISA::NumVecPredRegs },
+        { TheISA::NumCCRegs },
+        { TheISA::NumMiscRegs }
+#endif // THE_ISA != NULL_ISA
+    };
+
   public:
virtual void takeOverFrom(ThreadContext *new_tc, ThreadContext *old_tc) {}
     virtual void setThreadContext(ThreadContext *_tc) { tc = _tc; }

     virtual uint64_t getExecutingAsid() const { return 0; }
     virtual bool inUserMode() const = 0;
+
+    const RegClasses &regClasses() const { return _regClasses; }
 };

 #endif // __ARCH_GENERIC_ISA_HH__
diff --git a/src/cpu/minor/execute.cc b/src/cpu/minor/execute.cc
index 3eb7811..7575cf9 100644
--- a/src/cpu/minor/execute.cc
+++ b/src/cpu/minor/execute.cc
@@ -175,8 +175,10 @@
                 name_ + ".inputBuffer" + tid_str, "insts",
                 params.executeInputBufferSize));

+ const auto &regClasses = cpu.threads[tid]->getIsaPtr()->regClasses();
+
         /* Scoreboards */
-        scoreboard.push_back(Scoreboard(name_ + ".scoreboard" + tid_str));
+ scoreboard.emplace_back(name_ + ".scoreboard" + tid_str, regClasses);

         /* In-flight instruction records */
         executeInfo[tid].inFlightInsts =  new Queue<QueuedInst,
diff --git a/src/cpu/minor/scoreboard.cc b/src/cpu/minor/scoreboard.cc
index c0846c7..0d943f1 100644
--- a/src/cpu/minor/scoreboard.cc
+++ b/src/cpu/minor/scoreboard.cc
@@ -61,27 +61,20 @@
             ret = true;
             break;
           case FloatRegClass:
-            scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
-                reg.index();
+            scoreboard_index = floatRegOffset + reg.index();
             ret = true;
             break;
           case VecRegClass:
-            scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
-                TheISA::NumFloatRegs + reg.index();
-            ret = true;
-            break;
           case VecElemClass:
-            scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
-                TheISA::NumFloatRegs + reg.flatIndex();
+            scoreboard_index = vecRegOffset + reg.index();
             ret = true;
             break;
           case VecPredRegClass:
-            scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
-                TheISA::NumFloatRegs + TheISA::NumVecRegs + reg.index();
+            scoreboard_index = vecPredRegOffset + reg.index();
             ret = true;
             break;
           case CCRegClass:
-            scoreboard_index = TheISA::NumIntRegs + reg.index();
+            scoreboard_index = ccRegOffset + reg.index();
             ret = true;
             break;
           case MiscRegClass:
diff --git a/src/cpu/minor/scoreboard.hh b/src/cpu/minor/scoreboard.hh
index aab0b2b..1e4b1f1 100644
--- a/src/cpu/minor/scoreboard.hh
+++ b/src/cpu/minor/scoreboard.hh
@@ -50,6 +50,7 @@
 #include "cpu/minor/cpu.hh"
 #include "cpu/minor/dyn_inst.hh"
 #include "cpu/minor/trace.hh"
+#include "cpu/reg_class.hh"

 namespace Minor
 {
@@ -60,6 +61,14 @@
 class Scoreboard : public Named
 {
   public:
+    const BaseISA::RegClasses regClasses;
+
+    const unsigned intRegOffset;
+    const unsigned floatRegOffset;
+    const unsigned ccRegOffset;
+    const unsigned vecRegOffset;
+    const unsigned vecPredRegOffset;
+
     /** The number of registers in the Scoreboard.  These
      *  are just the integer, CC and float registers packed
      *  together with integer regs in the range [0,NumIntRegs-1],
@@ -92,12 +101,16 @@
     std::vector<InstSeqNum> writingInst;

   public:
-    Scoreboard(const std::string &name) :
+    Scoreboard(const std::string &name,
+            const BaseISA::RegClasses& reg_classes) :
         Named(name),
-        numRegs(TheISA::NumIntRegs + TheISA::NumCCRegs +
-            TheISA::NumFloatRegs +
-            (TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg) +
-            TheISA::NumVecPredRegs),
+        regClasses(reg_classes),
+        intRegOffset(0),
+        floatRegOffset(intRegOffset + reg_classes.at(IntRegClass).size()),
+        ccRegOffset(floatRegOffset + reg_classes.at(FloatRegClass).size()),
+        vecRegOffset(ccRegOffset + reg_classes.at(CCRegClass).size()),
+ vecPredRegOffset(vecRegOffset + reg_classes.at(VecElemClass).size()),
+        numRegs(vecPredRegOffset + reg_classes.at(VecPredRegClass).size()),
         numResults(numRegs, 0),
         numUnpredictableResults(numRegs, 0),
         fuIndices(numRegs, 0),
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index 3b9f991..3cebbf1 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -95,6 +95,7 @@
               params.numPhysVecRegs,
               params.numPhysVecPredRegs,
               params.numPhysCCRegs,
+              params.isa[0]->regClasses().at(MiscRegClass).size(),
               vecMode),

       freeList(name() + ".freelist", &regFile),
@@ -194,12 +195,26 @@
         }
     }

-    //Make Sure That this a Valid Architeture
-    assert(params.numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
-    assert(params.numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
-    assert(params.numPhysVecRegs >= numThreads * TheISA::NumVecRegs);
- assert(params.numPhysVecPredRegs >= numThreads * TheISA::NumVecPredRegs);
-    assert(params.numPhysCCRegs >= numThreads * TheISA::NumCCRegs);
+    // Make Sure That this a Valid Architeture
+    assert(numThreads);
+    const auto &regClasses = params.isa[0]->regClasses();
+
+    assert(params.numPhysIntRegs >=
+            numThreads * regClasses.at(IntRegClass).size());
+    assert(params.numPhysFloatRegs >=
+            numThreads * regClasses.at(FloatRegClass).size());
+    assert(params.numPhysVecRegs >=
+            numThreads * regClasses.at(VecRegClass).size());
+    assert(params.numPhysVecPredRegs >=
+            numThreads * regClasses.at(VecPredRegClass).size());
+    assert(params.numPhysCCRegs >=
+            numThreads * regClasses.at(CCRegClass).size());
+
+    // Just make this a warning and go ahead anyway, to keep from having to
+    // add checks everywhere.
+ warn_if(regClasses.at(CCRegClass).size() == 0 && params.numPhysCCRegs != 0,
+            "Non-zero number of physical CC regs specified, even though\n"
+            "    ISA does not use them.");

     rename.setScoreboard(&scoreboard);
     iew.setScoreboard(&scoreboard);
@@ -213,19 +228,20 @@
         // Only Alpha has an FP zero register, so for other ISAs we
         // use an invalid FP register index to avoid special treatment
         // of any valid FP reg.
-        RegIndex invalidFPReg = TheISA::NumFloatRegs + 1;
+        RegIndex invalidFPReg = regClasses.at(FloatRegClass).size() + 1;

-        commitRenameMap[tid].init(&regFile, TheISA::ZeroReg, invalidFPReg,
-                                  &freeList, vecMode);
+        commitRenameMap[tid].init(regClasses, &regFile, TheISA::ZeroReg,
+                invalidFPReg, &freeList, vecMode);

-        renameMap[tid].init(&regFile, TheISA::ZeroReg, invalidFPReg,
-                            &freeList, vecMode);
+        renameMap[tid].init(regClasses, &regFile, TheISA::ZeroReg,
+                invalidFPReg, &freeList, vecMode);
     }

     // Initialize rename map to assign physical registers to the
     // architectural registers for active threads only.
     for (ThreadID tid = 0; tid < active_threads; tid++) {
-        for (RegIndex ridx = 0; ridx < TheISA::NumIntRegs; ++ridx) {
+        for (RegIndex ridx = 0; ridx < regClasses.at(IntRegClass).size();
+                ++ridx) {
             // Note that we can't use the rename() method because we don't
             // want special treatment for the zero register at this point
             PhysRegIdPtr phys_reg = freeList.getIntReg();
@@ -233,7 +249,8 @@
commitRenameMap[tid].setEntry(RegId(IntRegClass, ridx), phys_reg);
         }

-        for (RegIndex ridx = 0; ridx < TheISA::NumFloatRegs; ++ridx) {
+        for (RegIndex ridx = 0; ridx < regClasses.at(FloatRegClass).size();
+                ++ridx) {
             PhysRegIdPtr phys_reg = freeList.getFloatReg();
             renameMap[tid].setEntry(RegId(FloatRegClass, ridx), phys_reg);
             commitRenameMap[tid].setEntry(
@@ -243,9 +260,10 @@
         /* Here we need two 'interfaces' the 'whole register' and the
          * 'register element'. At any point only one of them will be
          * active. */
+        const size_t numVecs = regClasses.at(VecRegClass).size();
         if (vecMode == Enums::Full) {
             /* Initialize the full-vector interface */
-            for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
+            for (RegIndex ridx = 0; ridx < numVecs; ++ridx) {
                 RegId rid = RegId(VecRegClass, ridx);
                 PhysRegIdPtr phys_reg = freeList.getVecReg();
                 renameMap[tid].setEntry(rid, phys_reg);
@@ -253,9 +271,10 @@
             }
         } else {
             /* Initialize the vector-element interface */
-            for (RegIndex ridx = 0; ridx < TheISA::NumVecRegs; ++ridx) {
-                for (ElemIndex ldx = 0; ldx < TheISA::NumVecElemPerVecReg;
-                        ++ldx) {
+            const size_t numElems = regClasses.at(VecElemClass).size();
+            const size_t elemsPerVec = numElems / numVecs;
+            for (RegIndex ridx = 0; ridx < numVecs; ++ridx) {
+                for (ElemIndex ldx = 0; ldx < elemsPerVec; ++ldx) {
                     RegId lrid = RegId(VecElemClass, ridx, ldx);
                     PhysRegIdPtr phys_elem = freeList.getVecElem();
                     renameMap[tid].setEntry(lrid, phys_elem);
@@ -264,14 +283,16 @@
             }
         }

-        for (RegIndex ridx = 0; ridx < TheISA::NumVecPredRegs; ++ridx) {
+ for (RegIndex ridx = 0; ridx < regClasses.at(VecPredRegClass).size();
+                ++ridx) {
             PhysRegIdPtr phys_reg = freeList.getVecPredReg();
renameMap[tid].setEntry(RegId(VecPredRegClass, ridx), phys_reg);
             commitRenameMap[tid].setEntry(
                     RegId(VecPredRegClass, ridx), phys_reg);
         }

-        for (RegIndex ridx = 0; ridx < TheISA::NumCCRegs; ++ridx) {
+        for (RegIndex ridx = 0; ridx < regClasses.at(CCRegClass).size();
+                ++ridx) {
             PhysRegIdPtr phys_reg = freeList.getCCReg();
             renameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
commitRenameMap[tid].setEntry(RegId(CCRegClass, ridx), phys_reg);
@@ -750,25 +771,29 @@
         src_tc = tcBase(tid);

     //Bind Int Regs to Rename Map
+    const auto &regClasses = isa[tid]->regClasses();

-    for (RegId reg_id(IntRegClass, 0); reg_id.index() < TheISA::NumIntRegs;
-         reg_id.index()++) {
+    for (RegId reg_id(IntRegClass, 0);
+            reg_id.index() < regClasses.at(IntRegClass).size();
+            reg_id.index()++) {
         PhysRegIdPtr phys_reg = freeList.getIntReg();
         renameMap[tid].setEntry(reg_id, phys_reg);
         scoreboard.setReg(phys_reg);
     }

     //Bind Float Regs to Rename Map
- for (RegId reg_id(FloatRegClass, 0); reg_id.index() < TheISA::NumFloatRegs;
-         reg_id.index()++) {
+    for (RegId reg_id(FloatRegClass, 0);
+            reg_id.index() < regClasses.at(FloatRegClass).size();
+            reg_id.index()++) {
         PhysRegIdPtr phys_reg = freeList.getFloatReg();
         renameMap[tid].setEntry(reg_id, phys_reg);
         scoreboard.setReg(phys_reg);
     }

     //Bind condition-code Regs to Rename Map
-    for (RegId reg_id(CCRegClass, 0); reg_id.index() < TheISA::NumCCRegs;
-         reg_id.index()++) {
+    for (RegId reg_id(CCRegClass, 0);
+            reg_id.index() < regClasses.at(CCRegClass).size();
+            reg_id.index()++) {
         PhysRegIdPtr phys_reg = freeList.getCCReg();
         renameMap[tid].setEntry(reg_id, phys_reg);
         scoreboard.setReg(phys_reg);
@@ -845,21 +870,23 @@
 void
 FullO3CPU<Impl>::setVectorsAsReady(ThreadID tid)
 {
+    const auto &regClasses = isa[tid]->regClasses();
+
+    const size_t numVecs = regClasses.at(VecRegClass).size();
     if (vecMode == Enums::Elem) {
-        for (auto v = 0; v < TheISA::NumVecRegs; v++)
-            for (auto e = 0; e < TheISA::NumVecElemPerVecReg; e++)
-                scoreboard.setReg(
-                    commitRenameMap[tid].lookup(
-                        RegId(VecElemClass, v, e)
-                    )
-                );
+        const size_t numElems = regClasses.at(VecElemClass).size();
+        const size_t elemsPerVec = numElems / numVecs;
+        for (auto v = 0; v < numVecs; v++) {
+            for (auto e = 0; e < elemsPerVec; e++) {
+                scoreboard.setReg(commitRenameMap[tid].lookup(
+                            RegId(VecElemClass, v, e)));
+            }
+        }
     } else if (vecMode == Enums::Full) {
-        for (auto v = 0; v < TheISA::NumVecRegs; v++)
-            scoreboard.setReg(
-                commitRenameMap[tid].lookup(
-                    RegId(VecRegClass, v)
-                )
-            );
+        for (auto v = 0; v < numVecs; v++) {
+            scoreboard.setReg(commitRenameMap[tid].lookup(
+                        RegId(VecRegClass, v)));
+        }
     }
 }

diff --git a/src/cpu/o3/free_list.cc b/src/cpu/o3/free_list.cc
index 0e92e2c..f293fa0 100644
--- a/src/cpu/o3/free_list.cc
+++ b/src/cpu/o3/free_list.cc
@@ -29,9 +29,7 @@

 #include "cpu/o3/free_list.hh"

-#include "arch/registers.hh"
 #include "base/trace.hh"
-#include "config/the_isa.hh"
 #include "debug/FreeList.hh"

 UnifiedFreeList::UnifiedFreeList(const std::string &_my_name,
diff --git a/src/cpu/o3/regfile.cc b/src/cpu/o3/regfile.cc
index 323340e..fa08191 100644
--- a/src/cpu/o3/regfile.cc
+++ b/src/cpu/o3/regfile.cc
@@ -50,6 +50,7 @@
                          unsigned _numPhysicalVecRegs,
                          unsigned _numPhysicalVecPredRegs,
                          unsigned _numPhysicalCCRegs,
+                         unsigned _numPhysicalMiscRegs,
                          VecMode vmode)
     : intRegFile(_numPhysicalIntRegs),
       floatRegFile(_numPhysicalFloatRegs),
@@ -74,12 +75,6 @@
     PhysRegIndex phys_reg;
     PhysRegIndex flat_reg_idx = 0;

-    if (TheISA::NumCCRegs == 0 && _numPhysicalCCRegs != 0) {
-        // Just make this a warning and go ahead and allocate them
-        // anyway, to keep from having to add checks everywhere
-        warn("Non-zero number of physical CC regs specified, even though\n"
-             "    ISA does not use them.\n");
-    }
     // The initial batch of registers are the integer ones
     for (phys_reg = 0; phys_reg < numPhysicalIntRegs; phys_reg++) {
         intRegIds.emplace_back(IntRegClass, phys_reg, flat_reg_idx++);
@@ -121,7 +116,7 @@
     }

     // Misc regs have a fixed mapping but still need PhysRegIds.
-    for (phys_reg = 0; phys_reg < TheISA::NumMiscRegs; phys_reg++) {
+    for (phys_reg = 0; phys_reg < _numPhysicalMiscRegs; phys_reg++) {
         miscRegIds.emplace_back(MiscRegClass, phys_reg, 0);
     }
 }
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
index ec8716b..c9e0d9f 100644
--- a/src/cpu/o3/regfile.hh
+++ b/src/cpu/o3/regfile.hh
@@ -136,6 +136,7 @@
                 unsigned _numPhysicalVecRegs,
                 unsigned _numPhysicalVecPredRegs,
                 unsigned _numPhysicalCCRegs,
+                unsigned _numPhysicalMiscRegs,
                 VecMode vmode
                 );

diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index 237ba95..eb836c5 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -44,8 +44,6 @@

 #include <list>

-#include "arch/registers.hh"
-#include "config/the_isa.hh"
 #include "cpu/o3/rename.hh"
 #include "cpu/reg_class.hh"
 #include "debug/Activity.hh"
diff --git a/src/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc
index cda9924..5579929 100644
--- a/src/cpu/o3/rename_map.cc
+++ b/src/cpu/o3/rename_map.cc
@@ -43,25 +43,26 @@

 #include <vector>

+#include "arch/registers.hh"
 #include "cpu/reg_class.hh"
 #include "debug/Rename.hh"

 /**** SimpleRenameMap methods ****/

 SimpleRenameMap::SimpleRenameMap()
-    : freeList(NULL), zeroReg(IntRegClass,0)
+    : freeList(NULL), zeroReg(IntRegClass, 0)
 {
 }


 void
-SimpleRenameMap::init(unsigned size, SimpleFreeList *_freeList,
-                      RegIndex _zeroReg)
+SimpleRenameMap::init(const RegClassInfo &reg_class_info,
+        SimpleFreeList *_freeList, RegIndex _zeroReg)
 {
     assert(freeList == NULL);
     assert(map.empty());

-    map.resize(size);
+    map.resize(reg_class_info.size());
     freeList = _freeList;
     zeroReg = RegId(IntRegClass, _zeroReg);
 }
@@ -105,7 +106,8 @@
 /**** UnifiedRenameMap methods ****/

 void
-UnifiedRenameMap::init(PhysRegFile *_regFile,
+UnifiedRenameMap::init(const BaseISA::RegClasses &regClasses,
+                       PhysRegFile *_regFile,
                        RegIndex _intZeroReg,
                        RegIndex _floatZeroReg,
                        UnifiedFreeList *freeList,
@@ -114,18 +116,21 @@
     regFile = _regFile;
     vecMode = _mode;

-    intMap.init(TheISA::NumIntRegs, &(freeList->intList), _intZeroReg);
+ intMap.init(regClasses.at(IntRegClass), &(freeList->intList), _intZeroReg);

- floatMap.init(TheISA::NumFloatRegs, &(freeList->floatList), _floatZeroReg);
+    floatMap.init(regClasses.at(FloatRegClass), &(freeList->floatList),
+            _floatZeroReg);

-    vecMap.init(TheISA::NumVecRegs, &(freeList->vecList), (RegIndex)-1);
+    vecMap.init(regClasses.at(VecRegClass), &(freeList->vecList),
+            (RegIndex)-1);

-    vecElemMap.init(TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg,
-            &(freeList->vecElemList), (RegIndex)-1);
+    vecElemMap.init(regClasses.at(VecElemClass), &(freeList->vecElemList),
+            (RegIndex)-1);

- predMap.init(TheISA::NumVecPredRegs, &(freeList->predList), (RegIndex)-1);
+    predMap.init(regClasses.at(VecPredRegClass), &(freeList->predList),
+            (RegIndex)-1);

-    ccMap.init(TheISA::NumCCRegs, &(freeList->ccList), (RegIndex)-1);
+ ccMap.init(regClasses.at(CCRegClass), &(freeList->ccList), (RegIndex)-1);

 }

@@ -138,7 +143,7 @@
         panic_if(freeList->hasFreeVecElems(),
                 "The free list is already tracking Vec elems");
         panic_if(freeList->numFreeVecRegs() !=
-                regFile->numVecPhysRegs() - TheISA::NumVecRegs,
+                regFile->numVecPhysRegs() - vecMap.numArchRegs(),
                 "The free list has lost vector registers");

         /* Split the free regs. */
@@ -154,12 +159,11 @@
         panic_if(freeList->hasFreeVecRegs(),
                 "The free list is already tracking full Vec");
         panic_if(freeList->numFreeVecElems() !=
-                 regFile->numVecElemPhysRegs() -
-                 TheISA::NumVecRegs * TheISA::NumVecElemPerVecReg,
+                 regFile->numVecElemPhysRegs() - vecElemMap.numArchRegs(),
                  "The free list has lost vector register elements");

         auto range = regFile->getRegIds(VecRegClass);
-        freeList->addRegs(range.first + TheISA::NumVecRegs, range.second);
+ freeList->addRegs(range.first + vecMap.numArchRegs(), range.second);

         /* We remove the elems from the free list. */
         while (freeList->hasFreeVecElems())
@@ -198,23 +202,26 @@
          *  2.- Replace the contents of the register file with the vectors
          *  3.- Set the remaining registers as free
          */
-        TheISA::VecRegContainer new_RF[TheISA::NumVecRegs];
-        for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
+        TheISA::VecRegContainer new_RF[vecMap.numArchRegs()];
+        const size_t numVecs = vecMap.numArchRegs();
+        const size_t numElems = vecElemMap.numArchRegs();
+        const size_t elemsPerVec = numElems / numVecs;
+        for (uint32_t i = 0; i < numVecs; i++) {
             TheISA::VecReg dst = new_RF[i].as<TheISA::VecElem>();
-            for (uint32_t l = 0; l < TheISA::NumVecElemPerVecReg; l++) {
+            for (uint32_t l = 0; l < elemsPerVec; l++) {
                 RegId s_rid(VecElemClass, i, l);
                 PhysRegIdPtr s_prid = vecElemMap.lookup(s_rid);
                 dst[l] = regFile->readVecElem(s_prid);
             }
         }

-        for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
+        for (uint32_t i = 0; i < numVecs; i++) {
             PhysRegId pregId(VecRegClass, i, 0);
             regFile->setVecReg(regFile->getTrueId(&pregId), new_RF[i]);
         }

         auto range = regFile->getRegIds(VecRegClass);
-        for (uint32_t i = 0; i < TheISA::NumVecRegs; i++) {
+        for (uint32_t i = 0; i < numVecs; i++) {
             setEntry(RegId(VecRegClass, i), &(*(range.first + i)));
         }

diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh
index b14b83e..5f779bd 100644
--- a/src/cpu/o3/rename_map.hh
+++ b/src/cpu/o3/rename_map.hh
@@ -90,14 +90,13 @@

     SimpleRenameMap();

-    ~SimpleRenameMap() {};
-
     /**
      * Because we have an array of rename maps (one per thread) in the CPU,
      * it's awkward to initialize this object via the constructor.
      * Instead, this method is used for initialization.
      */
-    void init(unsigned size, SimpleFreeList *_freeList, RegIndex _zeroReg);
+ void init(const RegClassInfo &reg_class_info, SimpleFreeList *_freeList,
+            RegIndex _zeroReg);

     /**
      * Pair of a physical register and a physical register.  Used to
@@ -144,6 +143,8 @@
     /** Return the number of free entries on the associated free list. */
     unsigned numFreeEntries() const { return freeList->numFreeRegs(); }

+    size_t numArchRegs() const { return map.size(); }
+
     /** Forward begin/cbegin to the map. */
     /** @{ */
     iterator begin() { return map.begin(); }
@@ -207,7 +208,8 @@
     ~UnifiedRenameMap() {};

     /** Initializes rename map with given parameters. */
-    void init(PhysRegFile *_regFile,
+    void init(const BaseISA::RegClasses &regClasses,
+              PhysRegFile *_regFile,
               RegIndex _intZeroReg,
               RegIndex _floatZeroReg,
               UnifiedFreeList *freeList,
diff --git a/src/cpu/reg_class.hh b/src/cpu/reg_class.hh
index d48e700..3496874 100644
--- a/src/cpu/reg_class.hh
+++ b/src/cpu/reg_class.hh
@@ -61,6 +61,17 @@
     MiscRegClass        ///< Control (misc) register
 };

+class RegClassInfo
+{
+  private:
+    size_t _size;
+
+  public:
+    RegClassInfo(size_t new_size) : _size(new_size) {}
+
+    size_t size() const { return _size; }
+};
+
 /** 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.
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index f15be91..7e65bc7 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -74,22 +74,19 @@
       htmTransactionStarts(0), htmTransactionStops(0)
 {
     assert(isa);
+    const auto &regClasses = isa->regClasses();
+    intRegs.resize(regClasses.at(IntRegClass).size());
+    floatRegs.resize(regClasses.at(FloatRegClass).size());
+    vecRegs.resize(regClasses.at(VecRegClass).size());
+    vecPredRegs.resize(regClasses.at(VecPredRegClass).size());
+    ccRegs.resize(regClasses.at(CCRegClass).size());
     clearArchRegs();
 }

 SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
                            BaseMMU *_mmu, BaseISA *_isa)
-    : ThreadState(_cpu, _thread_num, NULL),
-      isa(dynamic_cast<TheISA::ISA *>(_isa)),
-      predicate(true), memAccPredicate(true),
-      comInstEventQueue("instruction-based event queue"),
-      system(_sys), mmu(_mmu), decoder(isa),
-      htmTransactionStarts(0), htmTransactionStops(0)
-{
-    assert(isa);
-
-    clearArchRegs();
-}
+    : SimpleThread(_cpu, _thread_num, _sys, nullptr, _mmu, _isa)
+{}

 void
 SimpleThread::takeOverFrom(ThreadContext *oldContext)
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index 317f947..42ac6a4 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -42,7 +42,8 @@
 #ifndef __CPU_SIMPLE_THREAD_HH__
 #define __CPU_SIMPLE_THREAD_HH__

-#include <array>
+#include <algorithm>
+#include <vector>

 #include "arch/decoder.hh"
 #include "arch/generic/htm.hh"
@@ -93,12 +94,11 @@
     typedef ThreadContext::Status Status;

   protected:
-    std::array<RegVal, TheISA::NumFloatRegs> floatRegs;
-    std::array<RegVal, TheISA::NumIntRegs> intRegs;
-    std::array<TheISA::VecRegContainer, TheISA::NumVecRegs> vecRegs;
-    std::array<TheISA::VecPredRegContainer, TheISA::NumVecPredRegs>
-        vecPredRegs;
-    std::array<RegVal, TheISA::NumCCRegs> ccRegs;
+    std::vector<RegVal> floatRegs;
+    std::vector<RegVal> intRegs;
+    std::vector<TheISA::VecRegContainer> vecRegs;
+    std::vector<TheISA::VecPredRegContainer> vecPredRegs;
+    std::vector<RegVal> ccRegs;
     TheISA::ISA *const isa;    // one "instance" of the current ISA.

     TheISA::PCState _pcState;
@@ -253,13 +253,13 @@
     clearArchRegs() override
     {
         _pcState = 0;
-        intRegs.fill(0);
-        floatRegs.fill(0);
+        std::fill(intRegs.begin(), intRegs.end(), 0);
+        std::fill(floatRegs.begin(), floatRegs.end(), 0);
         for (auto &vec_reg: vecRegs)
             vec_reg.zero();
         for (auto &pred_reg: vecPredRegs)
             pred_reg.reset();
-        ccRegs.fill(0);
+        std::fill(ccRegs.begin(), ccRegs.end(), 0);
         isa->clear();
     }

@@ -270,8 +270,8 @@
     readIntReg(RegIndex reg_idx) const override
     {
         int flatIndex = isa->flattenIntIndex(reg_idx);
-        assert(flatIndex < TheISA::NumIntRegs);
-        uint64_t regVal(readIntRegFlat(flatIndex));
+        assert(flatIndex < intRegs.size());
+        uint64_t regVal = readIntRegFlat(flatIndex);
         DPRINTF(IntRegs, "Reading int reg %d (%d) as %#x.\n",
                 reg_idx, flatIndex, regVal);
         return regVal;
@@ -281,8 +281,8 @@
     readFloatReg(RegIndex reg_idx) const override
     {
         int flatIndex = isa->flattenFloatIndex(reg_idx);
-        assert(flatIndex < TheISA::NumFloatRegs);
-        RegVal regVal(readFloatRegFlat(flatIndex));
+        assert(flatIndex < floatRegs.size());
+        RegVal regVal = readFloatRegFlat(flatIndex);
         DPRINTF(FloatRegs, "Reading float reg %d (%d) bits as %#x.\n",
                 reg_idx, flatIndex, regVal);
         return regVal;
@@ -292,7 +292,7 @@
     readVecReg(const RegId& reg) const override
     {
         int flatIndex = isa->flattenVecIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         const TheISA::VecRegContainer& regVal = readVecRegFlat(flatIndex);
         DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s.\n",
                 reg.index(), flatIndex, regVal.print());
@@ -303,7 +303,7 @@
     getWritableVecReg(const RegId& reg) override
     {
         int flatIndex = isa->flattenVecIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         TheISA::VecRegContainer& regVal = getWritableVecRegFlat(flatIndex);
         DPRINTF(VecRegs, "Reading vector reg %d (%d) as %s for modify.\n",
                 reg.index(), flatIndex, regVal.print());
@@ -318,7 +318,7 @@
     readVecLane(const RegId& reg) const
     {
         int flatIndex = isa->flattenVecIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         auto regVal = readVecLaneFlat<T>(flatIndex, reg.elemIndex());
         DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] as %lx.\n",
                 reg.index(), flatIndex, reg.elemIndex(), regVal);
@@ -359,7 +359,7 @@
     setVecLaneT(const RegId &reg, const LD &val)
     {
         int flatIndex = isa->flattenVecIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         setVecLaneFlat(flatIndex, reg.elemIndex(), val);
         DPRINTF(VecRegs, "Reading vector lane %d (%d)[%d] to %lx.\n",
                 reg.index(), flatIndex, reg.elemIndex(), val);
@@ -393,7 +393,7 @@
     readVecElem(const RegId &reg) const override
     {
         int flatIndex = isa->flattenVecElemIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         const TheISA::VecElem& regVal =
             readVecElemFlat(flatIndex, reg.elemIndex());
         DPRINTF(VecRegs, "Reading element %d of vector reg %d (%d) as"
@@ -405,7 +405,7 @@
     readVecPredReg(const RegId &reg) const override
     {
         int flatIndex = isa->flattenVecPredIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecPredRegs);
+        assert(flatIndex < vecPredRegs.size());
         const TheISA::VecPredRegContainer& regVal =
             readVecPredRegFlat(flatIndex);
         DPRINTF(VecPredRegs, "Reading predicate reg %d (%d) as %s.\n",
@@ -417,7 +417,7 @@
     getWritableVecPredReg(const RegId &reg) override
     {
         int flatIndex = isa->flattenVecPredIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecPredRegs);
+        assert(flatIndex < vecPredRegs.size());
         TheISA::VecPredRegContainer& regVal =
             getWritableVecPredRegFlat(flatIndex);
         DPRINTF(VecPredRegs,
@@ -431,7 +431,7 @@
     {
         int flatIndex = isa->flattenCCIndex(reg_idx);
         assert(0 <= flatIndex);
-        assert(flatIndex < TheISA::NumCCRegs);
+        assert(flatIndex < ccRegs.size());
         uint64_t regVal(readCCRegFlat(flatIndex));
         DPRINTF(CCRegs, "Reading CC reg %d (%d) as %#x.\n",
                 reg_idx, flatIndex, regVal);
@@ -442,7 +442,7 @@
     setIntReg(RegIndex reg_idx, RegVal val) override
     {
         int flatIndex = isa->flattenIntIndex(reg_idx);
-        assert(flatIndex < TheISA::NumIntRegs);
+        assert(flatIndex < intRegs.size());
         DPRINTF(IntRegs, "Setting int reg %d (%d) to %#x.\n",
                 reg_idx, flatIndex, val);
         setIntRegFlat(flatIndex, val);
@@ -452,10 +452,10 @@
     setFloatReg(RegIndex reg_idx, RegVal val) override
     {
         int flatIndex = isa->flattenFloatIndex(reg_idx);
-        assert(flatIndex < TheISA::NumFloatRegs);
+        assert(flatIndex < floatRegs.size());
         // XXX: Fix array out of bounds compiler error for gem5.fast
         // when checkercpu enabled
-        if (flatIndex < TheISA::NumFloatRegs)
+        if (flatIndex < floatRegs.size())
             setFloatRegFlat(flatIndex, val);
         DPRINTF(FloatRegs, "Setting float reg %d (%d) bits to %#x.\n",
                 reg_idx, flatIndex, val);
@@ -465,7 +465,7 @@
setVecReg(const RegId &reg, const TheISA::VecRegContainer &val) override
     {
         int flatIndex = isa->flattenVecIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         setVecRegFlat(flatIndex, val);
         DPRINTF(VecRegs, "Setting vector reg %d (%d) to %s.\n",
                 reg.index(), flatIndex, val.print());
@@ -475,7 +475,7 @@
     setVecElem(const RegId &reg, const TheISA::VecElem &val) override
     {
         int flatIndex = isa->flattenVecElemIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecRegs);
+        assert(flatIndex < vecRegs.size());
         setVecElemFlat(flatIndex, reg.elemIndex(), val);
         DPRINTF(VecRegs, "Setting element %d of vector reg %d (%d) to"
                 " %#x.\n", reg.elemIndex(), reg.index(), flatIndex, val);
@@ -486,7 +486,7 @@
             const TheISA::VecPredRegContainer &val) override
     {
         int flatIndex = isa->flattenVecPredIndex(reg.index());
-        assert(flatIndex < TheISA::NumVecPredRegs);
+        assert(flatIndex < vecPredRegs.size());
         setVecPredRegFlat(flatIndex, val);
         DPRINTF(VecPredRegs, "Setting predicate reg %d (%d) to %s.\n",
                 reg.index(), flatIndex, val.print());
@@ -496,7 +496,7 @@
     setCCReg(RegIndex reg_idx, RegVal val) override
     {
         int flatIndex = isa->flattenCCIndex(reg_idx);
-        assert(flatIndex < TheISA::NumCCRegs);
+        assert(flatIndex < ccRegs.size());
         DPRINTF(CCRegs, "Setting CC reg %d (%d) to %#x.\n",
                 reg_idx, flatIndex, val);
         setCCRegFlat(flatIndex, val);
diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc
index 16db818..1a78693 100644
--- a/src/cpu/thread_context.cc
+++ b/src/cpu/thread_context.cc
@@ -54,10 +54,12 @@
 void
 ThreadContext::compare(ThreadContext *one, ThreadContext *two)
 {
+    const auto &regClasses = one->getIsaPtr()->regClasses();
+
     DPRINTF(Context, "Comparing thread contexts\n");

     // First loop through the integer registers.
-    for (int i = 0; i < TheISA::NumIntRegs; ++i) {
+    for (int i = 0; i < regClasses.at(IntRegClass).size(); ++i) {
         RegVal t1 = one->readIntReg(i);
         RegVal t2 = two->readIntReg(i);
         if (t1 != t2)
@@ -66,7 +68,7 @@
     }

     // Then loop through the floating point registers.
-    for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
+    for (int i = 0; i < regClasses.at(FloatRegClass).size(); ++i) {
         RegVal t1 = one->readFloatReg(i);
         RegVal t2 = two->readFloatReg(i);
         if (t1 != t2)
@@ -75,7 +77,7 @@
     }

     // Then loop through the vector registers.
-    for (int i = 0; i < TheISA::NumVecRegs; ++i) {
+    for (int i = 0; i < regClasses.at(VecRegClass).size(); ++i) {
         RegId rid(VecRegClass, i);
         const TheISA::VecRegContainer& t1 = one->readVecReg(rid);
         const TheISA::VecRegContainer& t2 = two->readVecReg(rid);
@@ -85,7 +87,7 @@
     }

     // Then loop through the predicate registers.
-    for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
+    for (int i = 0; i < regClasses.at(VecPredRegClass).size(); ++i) {
         RegId rid(VecPredRegClass, i);
         const TheISA::VecPredRegContainer& t1 = one->readVecPredReg(rid);
         const TheISA::VecPredRegContainer& t2 = two->readVecPredReg(rid);
@@ -94,7 +96,7 @@
                   i, t1, t2);
     }

-    for (int i = 0; i < TheISA::NumMiscRegs; ++i) {
+    for (int i = 0; i < regClasses.at(MiscRegClass).size(); ++i) {
         RegVal t1 = one->readMiscRegNoEffect(i);
         RegVal t2 = two->readMiscRegNoEffect(i);
         if (t1 != t2)
@@ -103,7 +105,7 @@
     }

     // loop through the Condition Code registers.
-    for (int i = 0; i < TheISA::NumCCRegs; ++i) {
+    for (int i = 0; i < regClasses.at(CCRegClass).size(); ++i) {
         RegVal t1 = one->readCCReg(i);
         RegVal t2 = two->readCCReg(i);
         if (t1 != t2)
@@ -141,36 +143,45 @@
 void
 serialize(const ThreadContext &tc, CheckpointOut &cp)
 {
-    RegVal floatRegs[TheISA::NumFloatRegs];
-    for (int i = 0; i < TheISA::NumFloatRegs; ++i)
+ // Cast away the const so we can get the non-const ISA ptr, which we then
+    // use to get the const register classes.
+    auto &nc_tc = const_cast<ThreadContext &>(tc);
+    const auto &regClasses = nc_tc.getIsaPtr()->regClasses();
+
+    const size_t numFloats = regClasses.at(FloatRegClass).size();
+    RegVal floatRegs[numFloats];
+    for (int i = 0; i < numFloats; ++i)
         floatRegs[i] = tc.readFloatRegFlat(i);
     // This is a bit ugly, but needed to maintain backwards
     // compatibility.
-    arrayParamOut(cp, "floatRegs.i", floatRegs, TheISA::NumFloatRegs);
+    arrayParamOut(cp, "floatRegs.i", floatRegs, numFloats);

-    std::vector<TheISA::VecRegContainer> vecRegs(TheISA::NumVecRegs);
-    for (int i = 0; i < TheISA::NumVecRegs; ++i) {
+    const size_t numVecs = regClasses.at(VecRegClass).size();
+    std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
+    for (int i = 0; i < numVecs; ++i) {
         vecRegs[i] = tc.readVecRegFlat(i);
     }
     SERIALIZE_CONTAINER(vecRegs);

-    std::vector<TheISA::VecPredRegContainer>
-        vecPredRegs(TheISA::NumVecPredRegs);
-    for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
+    const size_t numPreds = regClasses.at(VecPredRegClass).size();
+    std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
+    for (int i = 0; i < numPreds; ++i) {
         vecPredRegs[i] = tc.readVecPredRegFlat(i);
     }
     SERIALIZE_CONTAINER(vecPredRegs);

-    RegVal intRegs[TheISA::NumIntRegs];
-    for (int i = 0; i < TheISA::NumIntRegs; ++i)
+    const size_t numInts = regClasses.at(IntRegClass).size();
+    RegVal intRegs[numInts];
+    for (int i = 0; i < numInts; ++i)
         intRegs[i] = tc.readIntRegFlat(i);
-    SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
+    SERIALIZE_ARRAY(intRegs, numInts);

-    if (TheISA::NumCCRegs) {
-        RegVal ccRegs[TheISA::NumCCRegs];
-        for (int i = 0; i < TheISA::NumCCRegs; ++i)
+    const size_t numCcs = regClasses.at(CCRegClass).size();
+    if (numCcs) {
+        RegVal ccRegs[numCcs];
+        for (int i = 0; i < numCcs; ++i)
             ccRegs[i] = tc.readCCRegFlat(i);
-        SERIALIZE_ARRAY(ccRegs, TheISA::NumCCRegs);
+        SERIALIZE_ARRAY(ccRegs, numCcs);
     }

     tc.pcState().serialize(cp);
@@ -181,35 +192,41 @@
 void
 unserialize(ThreadContext &tc, CheckpointIn &cp)
 {
-    RegVal floatRegs[TheISA::NumFloatRegs];
+    const auto &regClasses = tc.getIsaPtr()->regClasses();
+
+    const size_t numFloats = regClasses.at(FloatRegClass).size();
+    RegVal floatRegs[numFloats];
     // This is a bit ugly, but needed to maintain backwards
     // compatibility.
-    arrayParamIn(cp, "floatRegs.i", floatRegs, TheISA::NumFloatRegs);
-    for (int i = 0; i < TheISA::NumFloatRegs; ++i)
+    arrayParamIn(cp, "floatRegs.i", floatRegs, numFloats);
+    for (int i = 0; i < numFloats; ++i)
         tc.setFloatRegFlat(i, floatRegs[i]);

-    std::vector<TheISA::VecRegContainer> vecRegs(TheISA::NumVecRegs);
+    const size_t numVecs = regClasses.at(VecRegClass).size();
+    std::vector<TheISA::VecRegContainer> vecRegs(numVecs);
     UNSERIALIZE_CONTAINER(vecRegs);
-    for (int i = 0; i < TheISA::NumVecRegs; ++i) {
+    for (int i = 0; i < numVecs; ++i) {
         tc.setVecRegFlat(i, vecRegs[i]);
     }

-    std::vector<TheISA::VecPredRegContainer>
-        vecPredRegs(TheISA::NumVecPredRegs);
+    const size_t numPreds = regClasses.at(VecPredRegClass).size();
+    std::vector<TheISA::VecPredRegContainer> vecPredRegs(numPreds);
     UNSERIALIZE_CONTAINER(vecPredRegs);
-    for (int i = 0; i < TheISA::NumVecPredRegs; ++i) {
+    for (int i = 0; i < numPreds; ++i) {
         tc.setVecPredRegFlat(i, vecPredRegs[i]);
     }

-    RegVal intRegs[TheISA::NumIntRegs];
-    UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
-    for (int i = 0; i < TheISA::NumIntRegs; ++i)
+    const size_t numInts = regClasses.at(IntRegClass).size();
+    RegVal intRegs[numInts];
+    UNSERIALIZE_ARRAY(intRegs, numInts);
+    for (int i = 0; i < numInts; ++i)
         tc.setIntRegFlat(i, intRegs[i]);

-    if (TheISA::NumCCRegs) {
-        RegVal ccRegs[TheISA::NumCCRegs];
-        UNSERIALIZE_ARRAY(ccRegs, TheISA::NumCCRegs);
-        for (int i = 0; i < TheISA::NumCCRegs; ++i)
+    const size_t numCcs = regClasses.at(CCRegClass).size();
+    if (numCcs) {
+        RegVal ccRegs[numCcs];
+        UNSERIALIZE_ARRAY(ccRegs, numCcs);
+        for (int i = 0; i < numCcs; ++i)
             tc.setCCRegFlat(i, ccRegs[i]);
     }


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

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I6d6d1256288f880391246b71045482a4a03c4198
Gerrit-Change-Number: 41733
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to