fu_pool.cc revision 9184
12292SN/A/*
22689Sktlim@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
32292SN/A * All rights reserved.
42292SN/A *
52292SN/A * Redistribution and use in source and binary forms, with or without
62292SN/A * modification, are permitted provided that the following conditions are
72292SN/A * met: redistributions of source code must retain the above copyright
82292SN/A * notice, this list of conditions and the following disclaimer;
92292SN/A * redistributions in binary form must reproduce the above copyright
102292SN/A * notice, this list of conditions and the following disclaimer in the
112292SN/A * documentation and/or other materials provided with the distribution;
122292SN/A * neither the name of the copyright holders nor the names of its
132292SN/A * contributors may be used to endorse or promote products derived from
142292SN/A * this software without specific prior written permission.
152292SN/A *
162292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272689Sktlim@umich.edu *
282689Sktlim@umich.edu * Authors: Kevin Lim
292292SN/A */
302292SN/A
312292SN/A#include <sstream>
322292SN/A
332292SN/A#include "cpu/o3/fu_pool.hh"
342736Sktlim@umich.edu#include "cpu/func_unit.hh"
352292SN/A
362292SN/Ausing namespace std;
372292SN/A
382292SN/A////////////////////////////////////////////////////////////////////////////
392292SN/A//
402292SN/A//  A pool of function units
412292SN/A//
422292SN/A
432292SN/Ainline void
442292SN/AFUPool::FUIdxQueue::addFU(int fu_idx)
452292SN/A{
462292SN/A    funcUnitsIdx.push_back(fu_idx);
472292SN/A    ++size;
482292SN/A}
492292SN/A
502292SN/Ainline int
512292SN/AFUPool::FUIdxQueue::getFU()
522292SN/A{
532292SN/A    int retval = funcUnitsIdx[idx++];
542292SN/A
552292SN/A    if (idx == size)
562292SN/A        idx = 0;
572292SN/A
582292SN/A    return retval;
592292SN/A}
602292SN/A
612292SN/AFUPool::~FUPool()
622292SN/A{
632292SN/A    fuListIterator i = funcUnits.begin();
642292SN/A    fuListIterator end = funcUnits.end();
652292SN/A    for (; i != end; ++i)
662292SN/A        delete *i;
672292SN/A}
682292SN/A
692292SN/A
702292SN/A// Constructor
715034Smilesck@eecs.umich.eduFUPool::FUPool(const Params *p)
725034Smilesck@eecs.umich.edu    : SimObject(p)
732292SN/A{
742292SN/A    numFU = 0;
752292SN/A
762292SN/A    funcUnits.clear();
772292SN/A
782292SN/A    for (int i = 0; i < Num_OpClasses; ++i) {
799184Sandreas.hansson@arm.com        maxOpLatencies[i] = Cycles(0);
809184Sandreas.hansson@arm.com        maxIssueLatencies[i] = Cycles(0);
812292SN/A    }
822292SN/A
832292SN/A    //
842292SN/A    //  Iterate through the list of FUDescData structures
852292SN/A    //
865034Smilesck@eecs.umich.edu    const vector<FUDesc *> &paramList =  p->FUList;
872292SN/A    for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) {
882292SN/A
892292SN/A        //
902292SN/A        //  Don't bother with this if we're not going to create any FU's
912292SN/A        //
922292SN/A        if ((*i)->number) {
932292SN/A            //
942292SN/A            //  Create the FuncUnit object from this structure
952292SN/A            //   - add the capabilities listed in the FU's operation
962292SN/A            //     description
972292SN/A            //
982292SN/A            //  We create the first unit, then duplicate it as needed
992292SN/A            //
1002292SN/A            FuncUnit *fu = new FuncUnit;
1012292SN/A
1022292SN/A            OPDDiterator j = (*i)->opDescList.begin();
1032292SN/A            OPDDiterator end = (*i)->opDescList.end();
1042292SN/A            for (; j != end; ++j) {
1052292SN/A                // indicate that this pool has this capability
1062292SN/A                capabilityList.set((*j)->opClass);
1072292SN/A
1082292SN/A                // Add each of the FU's that will have this capability to the
1092292SN/A                // appropriate queue.
1102292SN/A                for (int k = 0; k < (*i)->number; ++k)
1112292SN/A                    fuPerCapList[(*j)->opClass].addFU(numFU + k);
1122292SN/A
1132292SN/A                // indicate that this FU has the capability
1142292SN/A                fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat);
1152292SN/A
1162292SN/A                if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
1172292SN/A                    maxOpLatencies[(*j)->opClass] = (*j)->opLat;
1182292SN/A
1192292SN/A                if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass])
1202292SN/A                    maxIssueLatencies[(*j)->opClass] = (*j)->issueLat;
1212292SN/A            }
1222292SN/A
1232292SN/A            numFU++;
1242292SN/A
1252292SN/A            //  Add the appropriate number of copies of this FU to the list
1262292SN/A            ostringstream s;
1272292SN/A
1282292SN/A            s << (*i)->name() << "(0)";
1292292SN/A            fu->name = s.str();
1302292SN/A            funcUnits.push_back(fu);
1312292SN/A
1322292SN/A            for (int c = 1; c < (*i)->number; ++c) {
1332292SN/A                ostringstream s;
1342292SN/A                numFU++;
1352292SN/A                FuncUnit *fu2 = new FuncUnit(*fu);
1362292SN/A
1372292SN/A                s << (*i)->name() << "(" << c << ")";
1382292SN/A                fu2->name = s.str();
1392292SN/A                funcUnits.push_back(fu2);
1402292SN/A            }
1412292SN/A        }
1422292SN/A    }
1432292SN/A
1442292SN/A    unitBusy.resize(numFU);
1452292SN/A
1462292SN/A    for (int i = 0; i < numFU; i++) {
1472292SN/A        unitBusy[i] = false;
1482292SN/A    }
1492292SN/A}
1502292SN/A
1512292SN/Avoid
1529184Sandreas.hansson@arm.comFUPool::annotateMemoryUnits(Cycles hit_latency)
1532292SN/A{
1542292SN/A    maxOpLatencies[MemReadOp] = hit_latency;
1552292SN/A
1562292SN/A    fuListIterator i = funcUnits.begin();
1572292SN/A    fuListIterator iend = funcUnits.end();
1582292SN/A    for (; i != iend; ++i) {
1592292SN/A        if ((*i)->provides(MemReadOp))
1602292SN/A            (*i)->opLatency(MemReadOp) = hit_latency;
1612292SN/A
1622292SN/A        if ((*i)->provides(MemWriteOp))
1632292SN/A            (*i)->opLatency(MemWriteOp) = hit_latency;
1642292SN/A    }
1652292SN/A}
1662292SN/A
1672292SN/Aint
1682292SN/AFUPool::getUnit(OpClass capability)
1692292SN/A{
1702292SN/A    //  If this pool doesn't have the specified capability,
1712292SN/A    //  return this information to the caller
1722292SN/A    if (!capabilityList[capability])
1732292SN/A        return -2;
1742292SN/A
1752292SN/A    int fu_idx = fuPerCapList[capability].getFU();
1762292SN/A    int start_idx = fu_idx;
1772292SN/A
1782292SN/A    // Iterate through the circular queue if needed, stopping if we've reached
1792292SN/A    // the first element again.
1802292SN/A    while (unitBusy[fu_idx]) {
1812292SN/A        fu_idx = fuPerCapList[capability].getFU();
1822292SN/A        if (fu_idx == start_idx) {
1832292SN/A            // No FU available
1842292SN/A            return -1;
1852292SN/A        }
1862292SN/A    }
1872292SN/A
1882348SN/A    assert(fu_idx < numFU);
1892348SN/A
1902292SN/A    unitBusy[fu_idx] = true;
1912292SN/A
1922292SN/A    return fu_idx;
1932292SN/A}
1942292SN/A
1952292SN/Avoid
1962327SN/AFUPool::freeUnitNextCycle(int fu_idx)
1972292SN/A{
1982292SN/A    assert(unitBusy[fu_idx]);
1992292SN/A    unitsToBeFreed.push_back(fu_idx);
2002292SN/A}
2012292SN/A
2022292SN/Avoid
2032292SN/AFUPool::processFreeUnits()
2042292SN/A{
2052292SN/A    while (!unitsToBeFreed.empty()) {
2062292SN/A        int fu_idx = unitsToBeFreed.back();
2072292SN/A        unitsToBeFreed.pop_back();
2082292SN/A
2092292SN/A        assert(unitBusy[fu_idx]);
2102292SN/A
2112292SN/A        unitBusy[fu_idx] = false;
2122292SN/A    }
2132292SN/A}
2142292SN/A
2152292SN/Avoid
2162292SN/AFUPool::dump()
2172292SN/A{
2182292SN/A    cout << "Function Unit Pool (" << name() << ")\n";
2192292SN/A    cout << "======================================\n";
2202292SN/A    cout << "Free List:\n";
2212292SN/A
2222292SN/A    for (int i = 0; i < numFU; ++i) {
2232292SN/A        if (unitBusy[i]) {
2242292SN/A            continue;
2252292SN/A        }
2262292SN/A
2272292SN/A        cout << "  [" << i << "] : ";
2282292SN/A
2292292SN/A        cout << funcUnits[i]->name << " ";
2302292SN/A
2312292SN/A        cout << "\n";
2322292SN/A    }
2332292SN/A
2342292SN/A    cout << "======================================\n";
2352292SN/A    cout << "Busy List:\n";
2362292SN/A    for (int i = 0; i < numFU; ++i) {
2372292SN/A        if (!unitBusy[i]) {
2382292SN/A            continue;
2392292SN/A        }
2402292SN/A
2412292SN/A        cout << "  [" << i << "] : ";
2422292SN/A
2432292SN/A        cout << funcUnits[i]->name << " ";
2442292SN/A
2452292SN/A        cout << "\n";
2462292SN/A    }
2472292SN/A}
2482292SN/A
2492307SN/Avoid
2502307SN/AFUPool::switchOut()
2512307SN/A{
2522307SN/A}
2532307SN/A
2542307SN/Avoid
2558737Skoansin.tan@gmail.comFUPool::takeOver()
2562307SN/A{
2572307SN/A    for (int i = 0; i < numFU; i++) {
2582307SN/A        unitBusy[i] = false;
2592307SN/A    }
2602307SN/A    unitsToBeFreed.clear();
2612307SN/A}
2622307SN/A
2632292SN/A//
2642292SN/A
2652292SN/A////////////////////////////////////////////////////////////////////////////
2662292SN/A//
2672292SN/A//  The SimObjects we use to get the FU information into the simulator
2682292SN/A//
2692292SN/A////////////////////////////////////////////////////////////////////////////
2702292SN/A
2712292SN/A//
2722292SN/A//    FUPool - Contails a list of FUDesc objects to make available
2732292SN/A//
2742292SN/A
2752292SN/A//
2762292SN/A//  The FuPool object
2772292SN/A//
2784762Snate@binkert.orgFUPool *
2794762Snate@binkert.orgFUPoolParams::create()
2802292SN/A{
2815034Smilesck@eecs.umich.edu    return new FUPool(this);
2822292SN/A}
283