fu_pool.cc revision 9184
12SN/A/* 21762SN/A * Copyright (c) 2006 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292665Ssaidi@eecs.umich.edu */ 302SN/A 312SN/A#include <sstream> 322SN/A 332SN/A#include "cpu/o3/fu_pool.hh" 342SN/A#include "cpu/func_unit.hh" 358229Snate@binkert.org 362SN/Ausing namespace std; 372SN/A 382SN/A//////////////////////////////////////////////////////////////////////////// 392SN/A// 402SN/A// A pool of function units 412SN/A// 422SN/A 432SN/Ainline void 442SN/AFUPool::FUIdxQueue::addFU(int fu_idx) 452SN/A{ 462SN/A funcUnitsIdx.push_back(fu_idx); 472SN/A ++size; 482SN/A} 492SN/A 502SN/Ainline int 512SN/AFUPool::FUIdxQueue::getFU() 522SN/A{ 532SN/A int retval = funcUnitsIdx[idx++]; 542SN/A 552SN/A if (idx == size) 562SN/A idx = 0; 572SN/A 582SN/A return retval; 592SN/A} 602SN/A 612SN/AFUPool::~FUPool() 622SN/A{ 632SN/A fuListIterator i = funcUnits.begin(); 642SN/A fuListIterator end = funcUnits.end(); 652SN/A for (; i != end; ++i) 662SN/A delete *i; 672SN/A} 682SN/A 692SN/A 702SN/A// Constructor 712SN/AFUPool::FUPool(const Params *p) 722SN/A : SimObject(p) 732SN/A{ 742SN/A numFU = 0; 752SN/A 762SN/A funcUnits.clear(); 772SN/A 782SN/A for (int i = 0; i < Num_OpClasses; ++i) { 792SN/A maxOpLatencies[i] = Cycles(0); 802SN/A maxIssueLatencies[i] = Cycles(0); 812SN/A } 822SN/A 832SN/A // 842SN/A // Iterate through the list of FUDescData structures 852SN/A // 862SN/A const vector<FUDesc *> ¶mList = p->FUList; 872SN/A for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) { 882SN/A 892SN/A // 902SN/A // Don't bother with this if we're not going to create any FU's 912SN/A // 922SN/A if ((*i)->number) { 932SN/A // 942SN/A // Create the FuncUnit object from this structure 951380SN/A // - add the capabilities listed in the FU's operation 961380SN/A // description 971380SN/A // 981380SN/A // We create the first unit, then duplicate it as needed 991380SN/A // 1001380SN/A FuncUnit *fu = new FuncUnit; 1011380SN/A 1021380SN/A OPDDiterator j = (*i)->opDescList.begin(); 1031380SN/A OPDDiterator end = (*i)->opDescList.end(); 1041380SN/A for (; j != end; ++j) { 1051380SN/A // indicate that this pool has this capability 1061380SN/A capabilityList.set((*j)->opClass); 1071380SN/A 1081380SN/A // Add each of the FU's that will have this capability to the 1092SN/A // appropriate queue. 1102SN/A for (int k = 0; k < (*i)->number; ++k) 1112SN/A fuPerCapList[(*j)->opClass].addFU(numFU + k); 1122SN/A 1132SN/A // indicate that this FU has the capability 1142SN/A fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat); 1152SN/A 1162SN/A if ((*j)->opLat > maxOpLatencies[(*j)->opClass]) 117400SN/A maxOpLatencies[(*j)->opClass] = (*j)->opLat; 118502SN/A 1192SN/A if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass]) 1202SN/A maxIssueLatencies[(*j)->opClass] = (*j)->issueLat; 1212SN/A } 1222SN/A 1232SN/A numFU++; 1242SN/A 1252SN/A // Add the appropriate number of copies of this FU to the list 1262SN/A ostringstream s; 1272SN/A 1282SN/A s << (*i)->name() << "(0)"; 1292SN/A fu->name = s.str(); 1302SN/A funcUnits.push_back(fu); 1312SN/A 1322SN/A for (int c = 1; c < (*i)->number; ++c) { 1332SN/A ostringstream s; 1342SN/A numFU++; 1352SN/A FuncUnit *fu2 = new FuncUnit(*fu); 1362SN/A 1372SN/A s << (*i)->name() << "(" << c << ")"; 1382SN/A fu2->name = s.str(); 1392SN/A funcUnits.push_back(fu2); 1402SN/A } 1412SN/A } 1422SN/A } 1432SN/A 144 unitBusy.resize(numFU); 145 146 for (int i = 0; i < numFU; i++) { 147 unitBusy[i] = false; 148 } 149} 150 151void 152FUPool::annotateMemoryUnits(Cycles hit_latency) 153{ 154 maxOpLatencies[MemReadOp] = hit_latency; 155 156 fuListIterator i = funcUnits.begin(); 157 fuListIterator iend = funcUnits.end(); 158 for (; i != iend; ++i) { 159 if ((*i)->provides(MemReadOp)) 160 (*i)->opLatency(MemReadOp) = hit_latency; 161 162 if ((*i)->provides(MemWriteOp)) 163 (*i)->opLatency(MemWriteOp) = hit_latency; 164 } 165} 166 167int 168FUPool::getUnit(OpClass capability) 169{ 170 // If this pool doesn't have the specified capability, 171 // return this information to the caller 172 if (!capabilityList[capability]) 173 return -2; 174 175 int fu_idx = fuPerCapList[capability].getFU(); 176 int start_idx = fu_idx; 177 178 // Iterate through the circular queue if needed, stopping if we've reached 179 // the first element again. 180 while (unitBusy[fu_idx]) { 181 fu_idx = fuPerCapList[capability].getFU(); 182 if (fu_idx == start_idx) { 183 // No FU available 184 return -1; 185 } 186 } 187 188 assert(fu_idx < numFU); 189 190 unitBusy[fu_idx] = true; 191 192 return fu_idx; 193} 194 195void 196FUPool::freeUnitNextCycle(int fu_idx) 197{ 198 assert(unitBusy[fu_idx]); 199 unitsToBeFreed.push_back(fu_idx); 200} 201 202void 203FUPool::processFreeUnits() 204{ 205 while (!unitsToBeFreed.empty()) { 206 int fu_idx = unitsToBeFreed.back(); 207 unitsToBeFreed.pop_back(); 208 209 assert(unitBusy[fu_idx]); 210 211 unitBusy[fu_idx] = false; 212 } 213} 214 215void 216FUPool::dump() 217{ 218 cout << "Function Unit Pool (" << name() << ")\n"; 219 cout << "======================================\n"; 220 cout << "Free List:\n"; 221 222 for (int i = 0; i < numFU; ++i) { 223 if (unitBusy[i]) { 224 continue; 225 } 226 227 cout << " [" << i << "] : "; 228 229 cout << funcUnits[i]->name << " "; 230 231 cout << "\n"; 232 } 233 234 cout << "======================================\n"; 235 cout << "Busy List:\n"; 236 for (int i = 0; i < numFU; ++i) { 237 if (!unitBusy[i]) { 238 continue; 239 } 240 241 cout << " [" << i << "] : "; 242 243 cout << funcUnits[i]->name << " "; 244 245 cout << "\n"; 246 } 247} 248 249void 250FUPool::switchOut() 251{ 252} 253 254void 255FUPool::takeOver() 256{ 257 for (int i = 0; i < numFU; i++) { 258 unitBusy[i] = false; 259 } 260 unitsToBeFreed.clear(); 261} 262 263// 264 265//////////////////////////////////////////////////////////////////////////// 266// 267// The SimObjects we use to get the FU information into the simulator 268// 269//////////////////////////////////////////////////////////////////////////// 270 271// 272// FUPool - Contails a list of FUDesc objects to make available 273// 274 275// 276// The FuPool object 277// 278FUPool * 279FUPoolParams::create() 280{ 281 return new FUPool(this); 282} 283