2006-04-23 00:26:48 +02:00
|
|
|
/*
|
2006-06-07 22:02:55 +02:00
|
|
|
* Copyright (c) 2006 The Regents of The University of Michigan
|
2006-04-23 00:26:48 +02:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2006-06-07 22:02:55 +02:00
|
|
|
*
|
|
|
|
* Authors: Kevin Lim
|
2006-04-23 00:26:48 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "cpu/o3/fu_pool.hh"
|
2006-06-16 23:52:15 +02:00
|
|
|
#include "cpu/func_unit.hh"
|
2006-04-23 00:26:48 +02:00
|
|
|
#include "sim/builder.hh"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// A pool of function units
|
|
|
|
//
|
|
|
|
|
|
|
|
inline void
|
|
|
|
FUPool::FUIdxQueue::addFU(int fu_idx)
|
|
|
|
{
|
|
|
|
funcUnitsIdx.push_back(fu_idx);
|
|
|
|
++size;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int
|
|
|
|
FUPool::FUIdxQueue::getFU()
|
|
|
|
{
|
|
|
|
int retval = funcUnitsIdx[idx++];
|
|
|
|
|
|
|
|
if (idx == size)
|
|
|
|
idx = 0;
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
FUPool::~FUPool()
|
|
|
|
{
|
|
|
|
fuListIterator i = funcUnits.begin();
|
|
|
|
fuListIterator end = funcUnits.end();
|
|
|
|
for (; i != end; ++i)
|
|
|
|
delete *i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Constructor
|
|
|
|
FUPool::FUPool(string name, vector<FUDesc *> paramList)
|
|
|
|
: SimObject(name)
|
|
|
|
{
|
|
|
|
numFU = 0;
|
|
|
|
|
|
|
|
funcUnits.clear();
|
|
|
|
|
|
|
|
for (int i = 0; i < Num_OpClasses; ++i) {
|
|
|
|
maxOpLatencies[i] = 0;
|
|
|
|
maxIssueLatencies[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Iterate through the list of FUDescData structures
|
|
|
|
//
|
|
|
|
for (FUDDiterator i = paramList.begin(); i != paramList.end(); ++i) {
|
|
|
|
|
|
|
|
//
|
|
|
|
// Don't bother with this if we're not going to create any FU's
|
|
|
|
//
|
|
|
|
if ((*i)->number) {
|
|
|
|
//
|
|
|
|
// Create the FuncUnit object from this structure
|
|
|
|
// - add the capabilities listed in the FU's operation
|
|
|
|
// description
|
|
|
|
//
|
|
|
|
// We create the first unit, then duplicate it as needed
|
|
|
|
//
|
|
|
|
FuncUnit *fu = new FuncUnit;
|
|
|
|
|
|
|
|
OPDDiterator j = (*i)->opDescList.begin();
|
|
|
|
OPDDiterator end = (*i)->opDescList.end();
|
|
|
|
for (; j != end; ++j) {
|
|
|
|
// indicate that this pool has this capability
|
|
|
|
capabilityList.set((*j)->opClass);
|
|
|
|
|
|
|
|
// Add each of the FU's that will have this capability to the
|
|
|
|
// appropriate queue.
|
|
|
|
for (int k = 0; k < (*i)->number; ++k)
|
|
|
|
fuPerCapList[(*j)->opClass].addFU(numFU + k);
|
|
|
|
|
|
|
|
// indicate that this FU has the capability
|
|
|
|
fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat);
|
|
|
|
|
|
|
|
if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
|
|
|
|
maxOpLatencies[(*j)->opClass] = (*j)->opLat;
|
|
|
|
|
|
|
|
if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass])
|
|
|
|
maxIssueLatencies[(*j)->opClass] = (*j)->issueLat;
|
|
|
|
}
|
|
|
|
|
|
|
|
numFU++;
|
|
|
|
|
|
|
|
// Add the appropriate number of copies of this FU to the list
|
|
|
|
ostringstream s;
|
|
|
|
|
|
|
|
s << (*i)->name() << "(0)";
|
|
|
|
fu->name = s.str();
|
|
|
|
funcUnits.push_back(fu);
|
|
|
|
|
|
|
|
for (int c = 1; c < (*i)->number; ++c) {
|
|
|
|
ostringstream s;
|
|
|
|
numFU++;
|
|
|
|
FuncUnit *fu2 = new FuncUnit(*fu);
|
|
|
|
|
|
|
|
s << (*i)->name() << "(" << c << ")";
|
|
|
|
fu2->name = s.str();
|
|
|
|
funcUnits.push_back(fu2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unitBusy.resize(numFU);
|
|
|
|
|
|
|
|
for (int i = 0; i < numFU; i++) {
|
|
|
|
unitBusy[i] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FUPool::annotateMemoryUnits(unsigned hit_latency)
|
|
|
|
{
|
|
|
|
maxOpLatencies[MemReadOp] = hit_latency;
|
|
|
|
|
|
|
|
fuListIterator i = funcUnits.begin();
|
|
|
|
fuListIterator iend = funcUnits.end();
|
|
|
|
for (; i != iend; ++i) {
|
|
|
|
if ((*i)->provides(MemReadOp))
|
|
|
|
(*i)->opLatency(MemReadOp) = hit_latency;
|
|
|
|
|
|
|
|
if ((*i)->provides(MemWriteOp))
|
|
|
|
(*i)->opLatency(MemWriteOp) = hit_latency;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
FUPool::getUnit(OpClass capability)
|
|
|
|
{
|
|
|
|
// If this pool doesn't have the specified capability,
|
|
|
|
// return this information to the caller
|
|
|
|
if (!capabilityList[capability])
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
int fu_idx = fuPerCapList[capability].getFU();
|
|
|
|
int start_idx = fu_idx;
|
|
|
|
|
|
|
|
// Iterate through the circular queue if needed, stopping if we've reached
|
|
|
|
// the first element again.
|
|
|
|
while (unitBusy[fu_idx]) {
|
|
|
|
fu_idx = fuPerCapList[capability].getFU();
|
|
|
|
if (fu_idx == start_idx) {
|
|
|
|
// No FU available
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-31 17:45:02 +02:00
|
|
|
assert(fu_idx < numFU);
|
|
|
|
|
2006-04-23 00:26:48 +02:00
|
|
|
unitBusy[fu_idx] = true;
|
|
|
|
|
|
|
|
return fu_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-05-19 21:45:06 +02:00
|
|
|
FUPool::freeUnitNextCycle(int fu_idx)
|
2006-04-23 00:26:48 +02:00
|
|
|
{
|
|
|
|
assert(unitBusy[fu_idx]);
|
|
|
|
unitsToBeFreed.push_back(fu_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FUPool::processFreeUnits()
|
|
|
|
{
|
|
|
|
while (!unitsToBeFreed.empty()) {
|
|
|
|
int fu_idx = unitsToBeFreed.back();
|
|
|
|
unitsToBeFreed.pop_back();
|
|
|
|
|
|
|
|
assert(unitBusy[fu_idx]);
|
|
|
|
|
|
|
|
unitBusy[fu_idx] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FUPool::dump()
|
|
|
|
{
|
|
|
|
cout << "Function Unit Pool (" << name() << ")\n";
|
|
|
|
cout << "======================================\n";
|
|
|
|
cout << "Free List:\n";
|
|
|
|
|
|
|
|
for (int i = 0; i < numFU; ++i) {
|
|
|
|
if (unitBusy[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << " [" << i << "] : ";
|
|
|
|
|
|
|
|
cout << funcUnits[i]->name << " ";
|
|
|
|
|
|
|
|
cout << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << "======================================\n";
|
|
|
|
cout << "Busy List:\n";
|
|
|
|
for (int i = 0; i < numFU; ++i) {
|
|
|
|
if (!unitBusy[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << " [" << i << "] : ";
|
|
|
|
|
|
|
|
cout << funcUnits[i]->name << " ";
|
|
|
|
|
|
|
|
cout << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-04 17:36:20 +02:00
|
|
|
void
|
|
|
|
FUPool::switchOut()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FUPool::takeOverFrom()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numFU; i++) {
|
|
|
|
unitBusy[i] = false;
|
|
|
|
}
|
|
|
|
unitsToBeFreed.clear();
|
|
|
|
}
|
|
|
|
|
2006-04-23 00:26:48 +02:00
|
|
|
//
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// The SimObjects we use to get the FU information into the simulator
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//
|
|
|
|
// FUPool - Contails a list of FUDesc objects to make available
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// The FuPool object
|
|
|
|
//
|
|
|
|
|
|
|
|
BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUPool)
|
|
|
|
|
|
|
|
SimObjectVectorParam<FUDesc *> FUList;
|
|
|
|
|
|
|
|
END_DECLARE_SIM_OBJECT_PARAMS(FUPool)
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_INIT_SIM_OBJECT_PARAMS(FUPool)
|
|
|
|
|
|
|
|
INIT_PARAM(FUList, "list of FU's for this pool")
|
|
|
|
|
|
|
|
END_INIT_SIM_OBJECT_PARAMS(FUPool)
|
|
|
|
|
|
|
|
|
|
|
|
CREATE_SIM_OBJECT(FUPool)
|
|
|
|
{
|
|
|
|
return new FUPool(getInstanceName(), FUList);
|
|
|
|
}
|
|
|
|
|
|
|
|
REGISTER_SIM_OBJECT("FUPool", FUPool)
|
|
|
|
|