cpu-o3: Add cache read ports limit to LSQ
This change introduces cache read ports to limit the number of per-cycle loads. Previously only the number of per-cycle stores could be limited. Change-Id: I39bbd984056c5a696725ee2db462a55b2079e2d4 Signed-off-by: Gabor Dozsa <gabor.dozsa@arm.com> Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/13517 Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -77,7 +77,9 @@ class DerivO3CPU(BaseCPU):
|
||||
activity = Param.Unsigned(0, "Initial count")
|
||||
|
||||
cacheStorePorts = Param.Unsigned(200, "Cache Ports. "
|
||||
"Constrains stores only. Loads are constrained by load FUs.")
|
||||
"Constrains stores only.")
|
||||
cacheLoadPorts = Param.Unsigned(200, "Cache Ports. "
|
||||
"Constrains loads only.")
|
||||
|
||||
decodeToFetchDelay = Param.Cycles(1, "Decode to fetch delay")
|
||||
renameToFetchDelay = Param.Cycles(1 ,"Rename to fetch delay")
|
||||
|
||||
@@ -755,7 +755,7 @@ class LSQ
|
||||
int entryAmount(ThreadID num_threads);
|
||||
|
||||
/** Ticks the LSQ. */
|
||||
void tick() { usedStorePorts = 0; }
|
||||
void tick();
|
||||
|
||||
/** Inserts a load into the LSQ. */
|
||||
void insertLoad(const DynInstPtr &load_inst);
|
||||
@@ -962,9 +962,9 @@ class LSQ
|
||||
/** Set D-cache blocked status */
|
||||
void cacheBlocked(bool v);
|
||||
/** Is any store port available to use? */
|
||||
bool storePortAvailable() const;
|
||||
bool cachePortAvailable(bool is_load) const;
|
||||
/** Another store port is in use */
|
||||
void storePortBusy();
|
||||
void cachePortBusy(bool is_load);
|
||||
|
||||
protected:
|
||||
/** D-cache is blocked */
|
||||
@@ -973,6 +973,10 @@ class LSQ
|
||||
int cacheStorePorts;
|
||||
/** The number of used cache ports in this cycle by stores. */
|
||||
int usedStorePorts;
|
||||
/** The number of cache ports available each cycle (loads only). */
|
||||
int cacheLoadPorts;
|
||||
/** The number of used cache ports in this cycle by loads. */
|
||||
int usedLoadPorts;
|
||||
|
||||
|
||||
/** The LSQ policy for SMT mode. */
|
||||
|
||||
@@ -63,6 +63,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
|
||||
: cpu(cpu_ptr), iewStage(iew_ptr),
|
||||
_cacheBlocked(false),
|
||||
cacheStorePorts(params->cacheStorePorts), usedStorePorts(0),
|
||||
cacheLoadPorts(params->cacheLoadPorts), usedLoadPorts(0),
|
||||
lsqPolicy(params->smtLSQPolicy),
|
||||
LQEntries(params->LQEntries),
|
||||
SQEntries(params->SQEntries),
|
||||
@@ -173,6 +174,18 @@ LSQ<Impl>::takeOverFrom()
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQ<Impl>::tick()
|
||||
{
|
||||
// Re-issue loads which got blocked on the per-cycle load ports limit.
|
||||
if (usedLoadPorts == cacheLoadPorts && !_cacheBlocked)
|
||||
iewStage->cacheUnblocked();
|
||||
|
||||
usedLoadPorts = 0;
|
||||
usedStorePorts = 0;
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
bool
|
||||
LSQ<Impl>::cacheBlocked() const
|
||||
@@ -189,17 +202,27 @@ LSQ<Impl>::cacheBlocked(bool v)
|
||||
|
||||
template<class Impl>
|
||||
bool
|
||||
LSQ<Impl>::storePortAvailable() const
|
||||
LSQ<Impl>::cachePortAvailable(bool is_load) const
|
||||
{
|
||||
return usedStorePorts < cacheStorePorts;
|
||||
bool ret;
|
||||
if (is_load) {
|
||||
ret = usedLoadPorts < cacheLoadPorts;
|
||||
} else {
|
||||
ret = usedStorePorts < cacheStorePorts;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
void
|
||||
LSQ<Impl>::storePortBusy()
|
||||
LSQ<Impl>::cachePortBusy(bool is_load)
|
||||
{
|
||||
usedStorePorts++;
|
||||
assert(usedStorePorts <= cacheStorePorts);
|
||||
assert(cachePortAvailable(is_load));
|
||||
if (is_load) {
|
||||
usedLoadPorts++;
|
||||
} else {
|
||||
usedStorePorts++;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
|
||||
@@ -708,7 +708,7 @@ LSQUnit<Impl>::writebackStores()
|
||||
storeWBIt->valid() &&
|
||||
storeWBIt->canWB() &&
|
||||
((!needsTSO) || (!storeInFlight)) &&
|
||||
lsq->storePortAvailable()) {
|
||||
lsq->cachePortAvailable(false)) {
|
||||
|
||||
if (isStoreBlocked) {
|
||||
DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
|
||||
@@ -1040,7 +1040,8 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
|
||||
|
||||
auto state = dynamic_cast<LSQSenderState*>(data_pkt->senderState);
|
||||
|
||||
if (!lsq->cacheBlocked() && (isLoad || lsq->storePortAvailable())) {
|
||||
if (!lsq->cacheBlocked() &&
|
||||
lsq->cachePortAvailable(isLoad)) {
|
||||
if (!dcachePort->sendTimingReq(data_pkt)) {
|
||||
ret = false;
|
||||
cache_got_blocked = true;
|
||||
@@ -1051,9 +1052,9 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
|
||||
|
||||
if (ret) {
|
||||
if (!isLoad) {
|
||||
lsq->storePortBusy();
|
||||
isStoreBlocked = false;
|
||||
}
|
||||
lsq->cachePortBusy(isLoad);
|
||||
state->outstanding++;
|
||||
state->request()->packetSent();
|
||||
} else {
|
||||
@@ -1067,7 +1068,6 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
|
||||
}
|
||||
state->request()->packetNotSent();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user