12292SN/A/*
29783Sandreas.hansson@arm.com * Copyright (c) 2012-2013 ARM Limited
39444SAndreas.Sandberg@ARM.com * All rights reserved
49444SAndreas.Sandberg@ARM.com *
59444SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall
69444SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual
79444SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating
89444SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software
99444SAndreas.Sandberg@ARM.com * licensed hereunder.  You may use the software subject to the license
109444SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated
119444SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software,
129444SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form.
139444SAndreas.Sandberg@ARM.com *
142689Sktlim@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
152292SN/A * All rights reserved.
162292SN/A *
172292SN/A * Redistribution and use in source and binary forms, with or without
182292SN/A * modification, are permitted provided that the following conditions are
192292SN/A * met: redistributions of source code must retain the above copyright
202292SN/A * notice, this list of conditions and the following disclaimer;
212292SN/A * redistributions in binary form must reproduce the above copyright
222292SN/A * notice, this list of conditions and the following disclaimer in the
232292SN/A * documentation and/or other materials provided with the distribution;
242292SN/A * neither the name of the copyright holders nor the names of its
252292SN/A * contributors may be used to endorse or promote products derived from
262292SN/A * this software without specific prior written permission.
272292SN/A *
282292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392689Sktlim@umich.edu *
402689Sktlim@umich.edu * Authors: Kevin Lim
412292SN/A */
422292SN/A
4311793Sbrandon.potter@amd.com#include "cpu/o3/fu_pool.hh"
4411793Sbrandon.potter@amd.com
452292SN/A#include <sstream>
462292SN/A
472736Sktlim@umich.edu#include "cpu/func_unit.hh"
482292SN/A
492292SN/Ausing namespace std;
502292SN/A
512292SN/A////////////////////////////////////////////////////////////////////////////
522292SN/A//
532292SN/A//  A pool of function units
542292SN/A//
552292SN/A
562292SN/Ainline void
572292SN/AFUPool::FUIdxQueue::addFU(int fu_idx)
582292SN/A{
592292SN/A    funcUnitsIdx.push_back(fu_idx);
602292SN/A    ++size;
612292SN/A}
622292SN/A
632292SN/Ainline int
642292SN/AFUPool::FUIdxQueue::getFU()
652292SN/A{
662292SN/A    int retval = funcUnitsIdx[idx++];
672292SN/A
682292SN/A    if (idx == size)
692292SN/A        idx = 0;
702292SN/A
712292SN/A    return retval;
722292SN/A}
732292SN/A
742292SN/AFUPool::~FUPool()
752292SN/A{
762292SN/A    fuListIterator i = funcUnits.begin();
772292SN/A    fuListIterator end = funcUnits.end();
782292SN/A    for (; i != end; ++i)
792292SN/A        delete *i;
802292SN/A}
812292SN/A
822292SN/A
832292SN/A// Constructor
845034Smilesck@eecs.umich.eduFUPool::FUPool(const Params *p)
855034Smilesck@eecs.umich.edu    : SimObject(p)
862292SN/A{
872292SN/A    numFU = 0;
882292SN/A
892292SN/A    funcUnits.clear();
902292SN/A
9110814Sandreas.hansson@arm.com    maxOpLatencies.fill(Cycles(0));
9210814Sandreas.hansson@arm.com    pipelined.fill(true);
932292SN/A
942292SN/A    //
952292SN/A    //  Iterate through the list of FUDescData structures
962292SN/A    //
975034Smilesck@eecs.umich.edu    const vector<FUDesc *> &paramList =  p->FUList;
982292SN/A    for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) {
992292SN/A
1002292SN/A        //
1012292SN/A        //  Don't bother with this if we're not going to create any FU's
1022292SN/A        //
1032292SN/A        if ((*i)->number) {
1042292SN/A            //
1052292SN/A            //  Create the FuncUnit object from this structure
1062292SN/A            //   - add the capabilities listed in the FU's operation
1072292SN/A            //     description
1082292SN/A            //
1092292SN/A            //  We create the first unit, then duplicate it as needed
1102292SN/A            //
1112292SN/A            FuncUnit *fu = new FuncUnit;
1122292SN/A
1132292SN/A            OPDDiterator j = (*i)->opDescList.begin();
1142292SN/A            OPDDiterator end = (*i)->opDescList.end();
1152292SN/A            for (; j != end; ++j) {
1162292SN/A                // indicate that this pool has this capability
1172292SN/A                capabilityList.set((*j)->opClass);
1182292SN/A
1192292SN/A                // Add each of the FU's that will have this capability to the
1202292SN/A                // appropriate queue.
1212292SN/A                for (int k = 0; k < (*i)->number; ++k)
1222292SN/A                    fuPerCapList[(*j)->opClass].addFU(numFU + k);
1232292SN/A
1242292SN/A                // indicate that this FU has the capability
12510807Snilay@cs.wisc.edu                fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->pipelined);
1262292SN/A
1272292SN/A                if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
1282292SN/A                    maxOpLatencies[(*j)->opClass] = (*j)->opLat;
1292292SN/A
13010807Snilay@cs.wisc.edu                if (!(*j)->pipelined)
13110807Snilay@cs.wisc.edu                    pipelined[(*j)->opClass] = false;
1322292SN/A            }
1332292SN/A
1342292SN/A            numFU++;
1352292SN/A
1362292SN/A            //  Add the appropriate number of copies of this FU to the list
1379550Sandreas.hansson@arm.com            fu->name = (*i)->name() + "(0)";
1382292SN/A            funcUnits.push_back(fu);
1392292SN/A
1402292SN/A            for (int c = 1; c < (*i)->number; ++c) {
1412292SN/A                ostringstream s;
1422292SN/A                numFU++;
1432292SN/A                FuncUnit *fu2 = new FuncUnit(*fu);
1442292SN/A
1452292SN/A                s << (*i)->name() << "(" << c << ")";
1462292SN/A                fu2->name = s.str();
1472292SN/A                funcUnits.push_back(fu2);
1482292SN/A            }
1492292SN/A        }
1502292SN/A    }
1512292SN/A
1522292SN/A    unitBusy.resize(numFU);
1532292SN/A
1542292SN/A    for (int i = 0; i < numFU; i++) {
1552292SN/A        unitBusy[i] = false;
1562292SN/A    }
1572292SN/A}
1582292SN/A
1592292SN/Aint
1602292SN/AFUPool::getUnit(OpClass capability)
1612292SN/A{
1622292SN/A    //  If this pool doesn't have the specified capability,
1632292SN/A    //  return this information to the caller
1642292SN/A    if (!capabilityList[capability])
1652292SN/A        return -2;
1662292SN/A
1672292SN/A    int fu_idx = fuPerCapList[capability].getFU();
1682292SN/A    int start_idx = fu_idx;
1692292SN/A
1702292SN/A    // Iterate through the circular queue if needed, stopping if we've reached
1712292SN/A    // the first element again.
1722292SN/A    while (unitBusy[fu_idx]) {
1732292SN/A        fu_idx = fuPerCapList[capability].getFU();
1742292SN/A        if (fu_idx == start_idx) {
1752292SN/A            // No FU available
1762292SN/A            return -1;
1772292SN/A        }
1782292SN/A    }
1792292SN/A
1802348SN/A    assert(fu_idx < numFU);
1812348SN/A
1822292SN/A    unitBusy[fu_idx] = true;
1832292SN/A
1842292SN/A    return fu_idx;
1852292SN/A}
1862292SN/A
1872292SN/Avoid
1882327SN/AFUPool::freeUnitNextCycle(int fu_idx)
1892292SN/A{
1902292SN/A    assert(unitBusy[fu_idx]);
1912292SN/A    unitsToBeFreed.push_back(fu_idx);
1922292SN/A}
1932292SN/A
1942292SN/Avoid
1952292SN/AFUPool::processFreeUnits()
1962292SN/A{
1972292SN/A    while (!unitsToBeFreed.empty()) {
1982292SN/A        int fu_idx = unitsToBeFreed.back();
1992292SN/A        unitsToBeFreed.pop_back();
2002292SN/A
2012292SN/A        assert(unitBusy[fu_idx]);
2022292SN/A
2032292SN/A        unitBusy[fu_idx] = false;
2042292SN/A    }
2052292SN/A}
2062292SN/A
2072292SN/Avoid
2082292SN/AFUPool::dump()
2092292SN/A{
2102292SN/A    cout << "Function Unit Pool (" << name() << ")\n";
2112292SN/A    cout << "======================================\n";
2122292SN/A    cout << "Free List:\n";
2132292SN/A
2142292SN/A    for (int i = 0; i < numFU; ++i) {
2152292SN/A        if (unitBusy[i]) {
2162292SN/A            continue;
2172292SN/A        }
2182292SN/A
2192292SN/A        cout << "  [" << i << "] : ";
2202292SN/A
2212292SN/A        cout << funcUnits[i]->name << " ";
2222292SN/A
2232292SN/A        cout << "\n";
2242292SN/A    }
2252292SN/A
2262292SN/A    cout << "======================================\n";
2272292SN/A    cout << "Busy List:\n";
2282292SN/A    for (int i = 0; i < numFU; ++i) {
2292292SN/A        if (!unitBusy[i]) {
2302292SN/A            continue;
2312292SN/A        }
2322292SN/A
2332292SN/A        cout << "  [" << i << "] : ";
2342292SN/A
2352292SN/A        cout << funcUnits[i]->name << " ";
2362292SN/A
2372292SN/A        cout << "\n";
2382292SN/A    }
2392292SN/A}
2402292SN/A
2419783Sandreas.hansson@arm.combool
2429783Sandreas.hansson@arm.comFUPool::isDrained() const
2432307SN/A{
2449783Sandreas.hansson@arm.com    bool is_drained = true;
2459444SAndreas.Sandberg@ARM.com    for (int i = 0; i < numFU; i++)
2469783Sandreas.hansson@arm.com        is_drained = is_drained && !unitBusy[i];
2479783Sandreas.hansson@arm.com
2489783Sandreas.hansson@arm.com    return is_drained;
2492307SN/A}
2502307SN/A
2512292SN/A//
2522292SN/A
2532292SN/A////////////////////////////////////////////////////////////////////////////
2542292SN/A//
2552292SN/A//  The SimObjects we use to get the FU information into the simulator
2562292SN/A//
2572292SN/A////////////////////////////////////////////////////////////////////////////
2582292SN/A
2592292SN/A//
2602292SN/A//    FUPool - Contails a list of FUDesc objects to make available
2612292SN/A//
2622292SN/A
2632292SN/A//
2642292SN/A//  The FuPool object
2652292SN/A//
2664762Snate@binkert.orgFUPool *
2674762Snate@binkert.orgFUPoolParams::create()
2682292SN/A{
2695034Smilesck@eecs.umich.edu    return new FUPool(this);
2702292SN/A}
271