summaryrefslogtreecommitdiff
path: root/src/cpu/minor/lsq.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/minor/lsq.cc')
-rw-r--r--src/cpu/minor/lsq.cc45
1 files changed, 33 insertions, 12 deletions
diff --git a/src/cpu/minor/lsq.cc b/src/cpu/minor/lsq.cc
index b836ed22d..6fe6c3738 100644
--- a/src/cpu/minor/lsq.cc
+++ b/src/cpu/minor/lsq.cc
@@ -676,9 +676,9 @@ LSQ::StoreBuffer::canForwardDataToLoad(LSQRequestPtr request,
while (ret == NoAddrRangeCoverage && i != slots.rend()) {
LSQRequestPtr slot = *i;
- /* Cache maintenance instructions go down via the store path *
- * but they carry no data and they shouldn't be considered for
- * forwarding */
+ /* Cache maintenance instructions go down via the store path but
+ * they carry no data and they shouldn't be considered
+ * for forwarding */
if (slot->packet &&
slot->inst->id.threadId == request->inst->id.threadId &&
!slot->packet->req->isCacheMaintenance()) {
@@ -931,8 +931,9 @@ LSQ::tryToSendToTransfers(LSQRequestPtr request)
bool is_load = request->isLoad;
bool is_llsc = request->request->isLLSC();
bool is_swap = request->request->isSwap();
+ bool is_atomic = request->request->isAtomic();
bool bufferable = !(request->request->isStrictlyOrdered() ||
- is_llsc || is_swap);
+ is_llsc || is_swap || is_atomic);
if (is_load) {
if (numStoresInTransfers != 0) {
@@ -965,9 +966,16 @@ LSQ::tryToSendToTransfers(LSQRequestPtr request)
if (storeBuffer.canForwardDataToLoad(request, forwarding_slot) !=
NoAddrRangeCoverage)
{
+ // There's at least another request that targets the same
+ // address and is staying in the storeBuffer. Since our
+ // request is non-bufferable (e.g., strictly ordered or atomic),
+ // we must wait for the other request in the storeBuffer to
+ // complete before we can issue this non-bufferable request.
+ // This is to make sure that the order they access the cache is
+ // correct.
DPRINTF(MinorMem, "Memory access can receive forwarded data"
- " from the store buffer, need to wait for store buffer to"
- " drain\n");
+ " from the store buffer, but need to wait for store buffer"
+ " to drain\n");
return;
}
}
@@ -1469,9 +1477,21 @@ LSQ::needsToTick()
void
LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
unsigned int size, Addr addr, Request::Flags flags,
- uint64_t *res)
+ uint64_t *res, AtomicOpFunctor *amo_op)
{
bool needs_burst = transferNeedsBurst(addr, size, lineWidth);
+
+ if (needs_burst && inst->staticInst->isAtomic()) {
+ // AMO requests that access across a cache line boundary are not
+ // allowed since the cache does not guarantee AMO ops to be executed
+ // atomically in two cache lines
+ // For ISAs such as x86 that requires AMO operations to work on
+ // accesses that cross cache-line boundaries, the cache needs to be
+ // modified to support locking both cache lines to guarantee the
+ // atomicity.
+ panic("Do not expect cross-cache-line atomic memory request\n");
+ }
+
LSQRequestPtr request;
/* Copy given data into the request. The request will pass this to the
@@ -1480,15 +1500,16 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
DPRINTF(MinorMem, "Pushing request (%s) addr: 0x%x size: %d flags:"
" 0x%x%s lineWidth : 0x%x\n",
- (isLoad ? "load" : "store"), addr, size, flags,
+ (isLoad ? "load" : "store/atomic"), addr, size, flags,
(needs_burst ? " (needs burst)" : ""), lineWidth);
if (!isLoad) {
- /* request_data becomes the property of a ...DataRequest (see below)
+ /* Request_data becomes the property of a ...DataRequest (see below)
* and destroyed by its destructor */
request_data = new uint8_t[size];
- if (flags & Request::STORE_NO_DATA) {
- /* For cache zeroing, just use zeroed data */
+ if (inst->staticInst->isAtomic() ||
+ (flags & Request::STORE_NO_DATA)) {
+ /* For atomic or store-no-data, just use zeroed data */
std::memset(request_data, 0, size);
} else {
std::memcpy(request_data, data, size);
@@ -1511,7 +1532,7 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
request->request->setVirt(0 /* asid */,
addr, size, flags, cpu.dataMasterId(),
/* I've no idea why we need the PC, but give it */
- inst->pc.instAddr());
+ inst->pc.instAddr(), amo_op);
requests.push(request);
request->startAddrTranslation();