00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pch.h>
00033
00034 #include "Sim/Register/RegisterFreeList.h"
00035 #include "Sim/Core/Core.h"
00036 #include "Sim/Register/RegisterFile.h"
00037
00038 using namespace std;
00039 using namespace Onikiri;
00040
00041 RegisterFreeList::RegisterFreeList()
00042 {
00043 }
00044
00045 RegisterFreeList::~RegisterFreeList()
00046 {
00047 ReleaseParam();
00048 }
00049
00050 void RegisterFreeList::Initialize(InitPhase phase)
00051 {
00052 if(phase == INIT_PRE_CONNECTION){
00053 LoadParam();
00054 }
00055 else if(phase == INIT_POST_CONNECTION){
00056
00057 if( m_registerFile.GetSize() == 0 ) {
00058 THROW_RUNTIME_ERROR("registerFile not set.");
00059 }
00060 if( m_emulator.GetSize() == 0 ) {
00061 THROW_RUNTIME_ERROR("emulator not set.");
00062 }
00063
00064 ISAInfoIF* isaInfo = m_emulator[0]->GetISAInfo();
00065
00066 int numLogicalReg = isaInfo->GetRegisterCount();
00067
00068
00069
00070 set<int> segmentSet;
00071 for (int i = 0; i < numLogicalReg; ++i) {
00072 int segment = isaInfo->GetRegisterSegmentID(i);
00073 segmentSet.insert(segment);
00074 }
00075
00076
00077 m_freeList.resize(segmentSet.size());
00078
00079
00080 int phyRegNo = 0;
00081 for(set<int>::iterator iter = segmentSet.begin();
00082 iter != segmentSet.end();
00083 ++iter)
00084 {
00085 int segment = *iter;
00086 int capacity = m_registerFile[0]->GetCapacity(segment);
00087
00088 for (int i = 0; i < capacity; i++) {
00089 m_freeList[segment].push_back(phyRegNo);
00090 ++phyRegNo;
00091 }
00092 }
00093
00094 ASSERT(
00095 phyRegNo == m_registerFile[0]->GetTotalCapacity(),
00096 "phyreg count unmatch"
00097 );
00098
00099
00100
00101
00102 vector<int> logicalRegNumList(segmentSet.size(), 0);
00103 for (int i = 0; i < numLogicalReg; i++) {
00104 int segment = isaInfo->GetRegisterSegmentID(i);
00105 logicalRegNumList[segment]++;
00106 }
00107
00108 int threadCount = m_core[0]->GetThreadCount();
00109 for( size_t i = 0; i < segmentSet.size(); i++ ){
00110 int requiredRegCount = logicalRegNumList[i] * threadCount + 1;
00111 if( GetFreeEntryCount((int)i) < requiredRegCount ){
00112 THROW_RUNTIME_ERROR(
00113 "The number of the physical register is too small.\n"
00114 "segment: %d\n"
00115 "phy reg num: %d\n"
00116 "requried num: %d (log reg num:%d x thread num:%d + 1)\n",
00117 i,
00118 m_registerFile[0]->GetCapacity((int)i),
00119 requiredRegCount,
00120 logicalRegNumList[i],
00121 threadCount
00122 );
00123 }
00124 }
00125 }
00126 }
00127
00128 void RegisterFreeList::Release(int segment, int phyRegNum)
00129 {
00130 m_freeList[segment].push_back(phyRegNum);
00131 }
00132
00133 int RegisterFreeList::Allocate(int segment)
00134 {
00135 ASSERT( m_freeList[segment].size() > 0, "cannot allocate register.");
00136
00137 int phyRegNo = m_freeList[segment].front();
00138 m_freeList[segment].pop_front();
00139
00140 return phyRegNo;
00141 }
00142
00143 int RegisterFreeList::GetSegmentCount()
00144 {
00145 return (int)m_freeList.size();
00146 }
00147
00148 int RegisterFreeList::GetFreeEntryCount(int segment)
00149 {
00150 return (int)m_freeList[segment].size();
00151 }