# Complex ALU instructions have a variable latencies
class O3_ARM_v7a_Complex_Int(FUDesc):
- opList = [ OpDesc(opClass='IntMult', opLat=3, issueLat=1),
- OpDesc(opClass='IntDiv', opLat=12, issueLat=12),
- OpDesc(opClass='IprAccess', opLat=3, issueLat=1) ]
+ opList = [ OpDesc(opClass='IntMult', opLat=3, pipelined=True),
+ OpDesc(opClass='IntDiv', opLat=12, pipelined=False),
+ OpDesc(opClass='IprAccess', opLat=3, pipelined=True) ]
count = 1
OpDesc(opClass='FloatAdd', opLat=5),
OpDesc(opClass='FloatCmp', opLat=5),
OpDesc(opClass='FloatCvt', opLat=5),
- OpDesc(opClass='FloatDiv', opLat=9, issueLat=9),
- OpDesc(opClass='FloatSqrt', opLat=33, issueLat=33),
+ OpDesc(opClass='FloatDiv', opLat=9, pipelined=False),
+ OpDesc(opClass='FloatSqrt', opLat=33, pipelined=False),
OpDesc(opClass='FloatMult', opLat=4) ]
count = 2
class OpDesc(SimObject):
type = 'OpDesc'
cxx_header = "cpu/func_unit.hh"
- issueLat = Param.Cycles(1, "cycles until another can be issued")
opClass = Param.OpClass("type of operation")
opLat = Param.Cycles(1, "cycles until result is available")
+ pipelined = Param.Bool(True, "set to true when the functional unit for"
+ "this op is fully pipelined. False means not pipelined at all.")
class FUDesc(SimObject):
type = 'FUDesc'
for (int i = 0; i < Num_OpClasses; ++i) {
opLatencies[i] = fu.opLatencies[i];
- issueLatencies[i] = fu.issueLatencies[i];
+ pipelined[i] = fu.pipelined[i];
}
capabilityList = fu.capabilityList;
void
-FuncUnit::addCapability(OpClass cap, unsigned oplat, unsigned issuelat)
+FuncUnit::addCapability(OpClass cap, unsigned oplat, bool pipeline)
{
- if (issuelat == 0 || oplat == 0)
+ if (oplat == 0)
panic("FuncUnit: you don't really want a zero-cycle latency do you?");
capabilityList.set(cap);
opLatencies[cap] = oplat;
- issueLatencies[cap] = issuelat;
+ pipelined[cap] = pipeline;
}
bool
return opLatencies[cap];
}
-unsigned
-FuncUnit::issueLatency(OpClass capability)
+bool
+FuncUnit::isPipelined(OpClass capability)
{
- return issueLatencies[capability];
+ return pipelined[capability];
}
////////////////////////////////////////////////////////////////////////////
public:
OpClass opClass;
Cycles opLat;
- Cycles issueLat;
+ bool pipelined;
OpDesc(const OpDescParams *p)
: SimObject(p), opClass(p->opClass), opLat(p->opLat),
- issueLat(p->issueLat) {};
+ pipelined(p->pipelined) {};
};
class FUDesc : public SimObject
{
private:
unsigned opLatencies[Num_OpClasses];
- unsigned issueLatencies[Num_OpClasses];
+ bool pipelined[Num_OpClasses];
std::bitset<Num_OpClasses> capabilityList;
public:
std::string name;
- void addCapability(OpClass cap, unsigned oplat, unsigned issuelat);
+ void addCapability(OpClass cap, unsigned oplat, bool pipelined);
bool provides(OpClass capability);
std::bitset<Num_OpClasses> capabilities();
unsigned &opLatency(OpClass capability);
- unsigned issueLatency(OpClass capability);
+ bool isPipelined(OpClass capability);
};
#endif // __FU_POOL_HH__
class IntMultDiv(FUDesc):
opList = [ OpDesc(opClass='IntMult', opLat=3),
- OpDesc(opClass='IntDiv', opLat=20, issueLat=19) ]
+ OpDesc(opClass='IntDiv', opLat=20, pipelined=False) ]
# DIV and IDIV instructions in x86 are implemented using a loop which
# issues division microops. The latency of these microops should really be
# of the quotient.
if buildEnv['TARGET_ISA'] in ('x86'):
opList[1].opLat=1
- opList[1].issueLat=1
count=2
class FP_MultDiv(FUDesc):
opList = [ OpDesc(opClass='FloatMult', opLat=4),
- OpDesc(opClass='FloatDiv', opLat=12, issueLat=12),
- OpDesc(opClass='FloatSqrt', opLat=24, issueLat=24) ]
+ OpDesc(opClass='FloatDiv', opLat=12, pipelined=False),
+ OpDesc(opClass='FloatSqrt', opLat=24, pipelined=False) ]
count = 2
class SIMD_Unit(FUDesc):
count = 4
class IprPort(FUDesc):
- opList = [ OpDesc(opClass='IprAccess', opLat = 3, issueLat = 3) ]
+ opList = [ OpDesc(opClass='IprAccess', opLat = 3, pipelined = False) ]
count = 1
for (int i = 0; i < Num_OpClasses; ++i) {
maxOpLatencies[i] = Cycles(0);
- maxIssueLatencies[i] = Cycles(0);
+ pipelined[i] = true;
}
//
fuPerCapList[(*j)->opClass].addFU(numFU + k);
// indicate that this FU has the capability
- fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->issueLat);
+ fu->addCapability((*j)->opClass, (*j)->opLat, (*j)->pipelined);
if ((*j)->opLat > maxOpLatencies[(*j)->opClass])
maxOpLatencies[(*j)->opClass] = (*j)->opLat;
- if ((*j)->issueLat > maxIssueLatencies[(*j)->opClass])
- maxIssueLatencies[(*j)->opClass] = (*j)->issueLat;
+ if (!(*j)->pipelined)
+ pipelined[(*j)->opClass] = false;
}
numFU++;
private:
/** Maximum op execution latencies, per op class. */
Cycles maxOpLatencies[Num_OpClasses];
- /** Maximum issue latencies, per op class. */
- Cycles maxIssueLatencies[Num_OpClasses];
+ /** Whether op is pipelined or not. */
+ bool pipelined[Num_OpClasses];
/** Bitvector listing capabilities of this FU pool. */
std::bitset<Num_OpClasses> capabilityList;
}
/** Returns the issue latency of the given capability. */
- Cycles getIssueLatency(OpClass capability) {
- return maxIssueLatencies[capability];
+ bool isPipelined(OpClass capability) {
+ return pipelined[capability];
}
/** Have all the FUs drained? */
if (idx >= 0)
fuPool->freeUnitNextCycle(idx);
} else {
- Cycles issue_latency = fuPool->getIssueLatency(op_class);
+ bool pipelined = fuPool->isPipelined(op_class);
// Generate completion event for the FU
++wbOutstanding;
FUCompletion *execution = new FUCompletion(issuing_inst,
cpu->schedule(execution,
cpu->clockEdge(Cycles(op_latency - 1)));
- // @todo: Enforce that issue_latency == 1 or op_latency
- if (issue_latency > Cycles(1)) {
+ if (!pipelined) {
// If FU isn't pipelined, then it must be freed
// upon the execution completing.
execution->setFreeFU();