diff --git a/src/arch/generic/isa.hh b/src/arch/generic/isa.hh index 4c717c71db..8b8b2db1d9 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 + +#include "arch/registers.hh" +#include "cpu/reg_class.hh" #include "sim/sim_object.hh" class ThreadContext; class BaseISA : public SimObject { + public: + typedef std::vector 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 ®Classes() const { return _regClasses; } }; #endif // __ARCH_GENERIC_ISA_HH__ diff --git a/src/cpu/minor/execute.cc b/src/cpu/minor/execute.cc index 3eb7811417..7575cf9eab 100644 --- a/src/cpu/minor/execute.cc +++ b/src/cpu/minor/execute.cc @@ -175,8 +175,10 @@ Execute::Execute(const std::string &name_, name_ + ".inputBuffer" + tid_str, "insts", params.executeInputBufferSize)); + const auto ®Classes = 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 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 3b9f99195c..3cebbf19bc 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -95,6 +95,7 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) params.numPhysVecRegs, params.numPhysVecPredRegs, params.numPhysCCRegs, + params.isa[0]->regClasses().at(MiscRegClass).size(), vecMode), freeList(name() + ".freelist", ®File), @@ -194,12 +195,26 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) } } - //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 ®Classes = 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 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) // 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(®File, TheISA::ZeroReg, invalidFPReg, - &freeList, vecMode); + commitRenameMap[tid].init(regClasses, ®File, TheISA::ZeroReg, + invalidFPReg, &freeList, vecMode); - renameMap[tid].init(®File, TheISA::ZeroReg, invalidFPReg, - &freeList, vecMode); + renameMap[tid].init(regClasses, ®File, 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 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) 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 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) /* 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 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) } } 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 @@ FullO3CPU::FullO3CPU(const DerivO3CPUParams ¶ms) } } - 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 @@ FullO3CPU::insertThread(ThreadID tid) src_tc = tcBase(tid); //Bind Int Regs to Rename Map + const auto ®Classes = 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 @@ template void FullO3CPU::setVectorsAsReady(ThreadID tid) { + const auto ®Classes = 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 0e92e2cb37..f293fa0c3d 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 323340ece9..fa081915be 100644 --- a/src/cpu/o3/regfile.cc +++ b/src/cpu/o3/regfile.cc @@ -50,6 +50,7 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, unsigned _numPhysicalVecRegs, unsigned _numPhysicalVecPredRegs, unsigned _numPhysicalCCRegs, + unsigned _numPhysicalMiscRegs, VecMode vmode) : intRegFile(_numPhysicalIntRegs), floatRegFile(_numPhysicalFloatRegs), @@ -74,12 +75,6 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, 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 @@ PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs, } // 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 6c6b9b3353..d30f577f8e 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -136,6 +136,7 @@ class PhysRegFile 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 237ba95b5d..eb836c576f 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -44,8 +44,6 @@ #include -#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 cda99249dc..55799294b7 100644 --- a/src/cpu/o3/rename_map.cc +++ b/src/cpu/o3/rename_map.cc @@ -43,25 +43,26 @@ #include +#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 ®_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 @@ SimpleRenameMap::rename(const RegId& arch_reg) /**** UnifiedRenameMap methods ****/ void -UnifiedRenameMap::init(PhysRegFile *_regFile, +UnifiedRenameMap::init(const BaseISA::RegClasses ®Classes, + PhysRegFile *_regFile, RegIndex _intZeroReg, RegIndex _floatZeroReg, UnifiedFreeList *freeList, @@ -114,18 +116,21 @@ UnifiedRenameMap::init(PhysRegFile *_regFile, 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 @@ UnifiedRenameMap::switchFreeList(UnifiedFreeList* freeList) 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 @@ UnifiedRenameMap::switchFreeList(UnifiedFreeList* freeList) 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 @@ UnifiedRenameMap::switchMode(VecMode newVecMode) * 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(); - 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 b14b83e3e2..5f779bd8ef 100644 --- a/src/cpu/o3/rename_map.hh +++ b/src/cpu/o3/rename_map.hh @@ -90,14 +90,13 @@ class SimpleRenameMap 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 ®_class_info, SimpleFreeList *_freeList, + RegIndex _zeroReg); /** * Pair of a physical register and a physical register. Used to @@ -144,6 +143,8 @@ class SimpleRenameMap /** 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 @@ class UnifiedRenameMap ~UnifiedRenameMap() {}; /** Initializes rename map with given parameters. */ - void init(PhysRegFile *_regFile, + void init(const BaseISA::RegClasses ®Classes, + PhysRegFile *_regFile, RegIndex _intZeroReg, RegIndex _floatZeroReg, UnifiedFreeList *freeList, diff --git a/src/cpu/reg_class.hh b/src/cpu/reg_class.hh index d48e700cf8..34968748cb 100644 --- a/src/cpu/reg_class.hh +++ b/src/cpu/reg_class.hh @@ -61,6 +61,17 @@ enum RegClass { 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 f15be91c9b..7e65bc7630 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -74,22 +74,19 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, htmTransactionStarts(0), htmTransactionStops(0) { assert(isa); + const auto ®Classes = 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(_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 8f65ea3959..e192ff16a2 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 +#include +#include #include "arch/decoder.hh" #include "arch/generic/htm.hh" @@ -93,12 +94,11 @@ class SimpleThread : public ThreadState, public ThreadContext typedef ThreadContext::Status Status; protected: - std::array floatRegs; - std::array intRegs; - std::array vecRegs; - std::array - vecPredRegs; - std::array ccRegs; + std::vector floatRegs; + std::vector intRegs; + std::vector vecRegs; + std::vector vecPredRegs; + std::vector ccRegs; TheISA::ISA *const isa; // one "instance" of the current ISA. TheISA::PCState _pcState; @@ -253,13 +253,13 @@ class SimpleThread : public ThreadState, public ThreadContext 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 @@ class SimpleThread : public ThreadState, public ThreadContext 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 @@ class SimpleThread : public ThreadState, public ThreadContext 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 @@ class SimpleThread : public ThreadState, public ThreadContext 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); @@ -303,7 +303,7 @@ class SimpleThread : public ThreadState, public ThreadContext 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); @@ -314,7 +314,7 @@ class SimpleThread : public ThreadState, public ThreadContext readVecElem(const RegId ®) 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" @@ -326,7 +326,7 @@ class SimpleThread : public ThreadState, public ThreadContext readVecPredReg(const RegId ®) 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", @@ -338,7 +338,7 @@ class SimpleThread : public ThreadState, public ThreadContext getWritableVecPredReg(const RegId ®) override { int flatIndex = isa->flattenVecPredIndex(reg.index()); - assert(flatIndex < TheISA::NumVecPredRegs); + assert(flatIndex < vecPredRegs.size()); TheISA::VecPredRegContainer& regVal = getWritableVecPredRegFlat(flatIndex); DPRINTF(VecPredRegs, @@ -352,7 +352,7 @@ class SimpleThread : public ThreadState, public ThreadContext { 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); @@ -363,7 +363,7 @@ class SimpleThread : public ThreadState, public ThreadContext 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); @@ -373,10 +373,10 @@ class SimpleThread : public ThreadState, public ThreadContext 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); @@ -386,7 +386,7 @@ class SimpleThread : public ThreadState, public ThreadContext setVecReg(const RegId ®, 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); @@ -396,7 +396,7 @@ class SimpleThread : public ThreadState, public ThreadContext setVecElem(const RegId ®, 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); @@ -407,7 +407,7 @@ class SimpleThread : public ThreadState, public ThreadContext 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()); @@ -417,7 +417,7 @@ class SimpleThread : public ThreadState, public ThreadContext 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 16db818ade..1a78693753 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 ®Classes = 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 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } // 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 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } // 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 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } // 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 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) 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 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } // 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 @@ ThreadContext::quiesceTick(Tick resume) 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(tc); + const auto ®Classes = 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 vecRegs(TheISA::NumVecRegs); - for (int i = 0; i < TheISA::NumVecRegs; ++i) { + const size_t numVecs = regClasses.at(VecRegClass).size(); + std::vector vecRegs(numVecs); + for (int i = 0; i < numVecs; ++i) { vecRegs[i] = tc.readVecRegFlat(i); } SERIALIZE_CONTAINER(vecRegs); - std::vector - vecPredRegs(TheISA::NumVecPredRegs); - for (int i = 0; i < TheISA::NumVecPredRegs; ++i) { + const size_t numPreds = regClasses.at(VecPredRegClass).size(); + std::vector 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 @@ serialize(const ThreadContext &tc, CheckpointOut &cp) void unserialize(ThreadContext &tc, CheckpointIn &cp) { - RegVal floatRegs[TheISA::NumFloatRegs]; + const auto ®Classes = 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 vecRegs(TheISA::NumVecRegs); + const size_t numVecs = regClasses.at(VecRegClass).size(); + std::vector 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 - vecPredRegs(TheISA::NumVecPredRegs); + const size_t numPreds = regClasses.at(VecPredRegClass).size(); + std::vector 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]); }