cpu: Handle Request::NO_ACCESS flag in MinorCPU and O3CPU

The Request::NO_ACCESS flag instructs the cpu model to not issue
the request to the memory port.

While Atomic and Timing CPU models properly implement it [1], [2],

* MinorCPU is not looking at the flag
* O3CPU is looking at the flag only in case of a nested transaction
start/commit

This patch is extending NO_ACCESS support to all memory instructions.
This is achieved by using the localAccess callback in the Request object.

Handling of nested hardware transactions in the O3 LSQUnit is moved within
the local accessor callback

[1]: https://github.com/gem5/gem5/blob/v21.1.0.2/\
    src/cpu/simple/timing.cc#L318
[2]: https://github.com/gem5/gem5/blob/v21.1.0.2/\
    src/cpu/simple/atomic.cc#L396

Change-Id: Ifd5b388c53ead4fe358aa35d2197c12f1c5bb4f2
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/56591
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: ZHENGRONG WANG <seanyukigeek@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
Giacomo Travaglini
2021-10-28 11:44:36 +01:00
parent 071858595d
commit b4ba4916dd
3 changed files with 26 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2014,2017-2018,2020 ARM Limited
* Copyright (c) 2013-2014,2017-2018,2020-2021 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -1651,6 +1651,14 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
inst->pc->instAddr(), std::move(amo_op));
request->request->setByteEnable(byte_enable);
/* If the request is marked as NO_ACCESS, setup a local access
* doing nothing */
if (flags.isSet(Request::NO_ACCESS)) {
assert(!request->request->isLocalAccess());
request->request->setLocalAccessor(
[] (ThreadContext *tc, PacketPtr pkt) { return Cycles(1); });
}
requests.push(request);
inst->inLSQ = true;
request->startAddrTranslation();

View File

@@ -1089,6 +1089,23 @@ LSQ::LSQRequest::addReq(Addr addr, unsigned size,
_inst->pcState().instAddr(), _inst->contextId(),
std::move(_amo_op));
req->setByteEnable(byte_enable);
/* If the request is marked as NO_ACCESS, setup a local access */
if (_flags.isSet(Request::NO_ACCESS)) {
req->setLocalAccessor(
[this, req](gem5::ThreadContext *tc, PacketPtr pkt) -> Cycles
{
if ((req->isHTMStart() || req->isHTMCommit())) {
auto& inst = this->instruction();
assert(inst->inHtmTransactionalState());
pkt->setHtmTransactional(
inst->getHtmTransactionUid());
}
return Cycles(1);
}
);
}
_reqs.push_back(req);
}
}

View File

@@ -1336,7 +1336,6 @@ LSQUnit::read(LSQRequest *request, int load_idx)
if (request->mainReq()->isLocalAccess()) {
assert(!load_inst->memData);
assert(!load_inst->inHtmTransactionalState());
load_inst->memData = new uint8_t[MaxDataBytes];
gem5::ThreadContext *thread = cpu->tcBase(lsqID);
@@ -1351,37 +1350,6 @@ LSQUnit::read(LSQRequest *request, int load_idx)
return NoFault;
}
// hardware transactional memory
if (request->mainReq()->isHTMStart() || request->mainReq()->isHTMCommit())
{
// don't want to send nested transactionStarts and
// transactionStops outside of core, e.g. to Ruby
if (request->mainReq()->getFlags().isSet(Request::NO_ACCESS)) {
Cycles delay(0);
PacketPtr data_pkt =
new Packet(request->mainReq(), MemCmd::ReadReq);
// Allocate memory if this is the first time a load is issued.
if (!load_inst->memData) {
load_inst->memData =
new uint8_t[request->mainReq()->getSize()];
// sanity checks espect zero in request's data
memset(load_inst->memData, 0, request->mainReq()->getSize());
}
data_pkt->dataStatic(load_inst->memData);
if (load_inst->inHtmTransactionalState()) {
data_pkt->setHtmTransactional(
load_inst->getHtmTransactionUid());
}
data_pkt->makeResponse();
WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this);
cpu->schedule(wb, cpu->clockEdge(delay));
return NoFault;
}
}
// Check the SQ for any previous stores that might lead to forwarding
auto store_it = load_inst->sqIt;
assert (store_it >= storeWBIt);