From 05f33fbef5fee95e83733e2283fe72b51a0d2e4b Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Mon, 14 Nov 2022 12:02:10 +0000 Subject: [PATCH 1/5] mem-cache: Squash prefetch queue entries by block address. Prefetch queue entries were being squashed by comparing the address of each queued prefetch against the block address of the demand access. Only prefetches that happen to fall on a cache-line block boundary would be squashed. This patch converts the prefetch addresses to block addresses before comparison. Change-Id: I3a80a1e3d752f925595e33edebf5359d2cc67182 Reviewed-by: Andreas Sandberg --- src/mem/cache/prefetch/queued.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index e22d6f5eb8..c16e6ce905 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, 2023 ARM Limited + * Copyright (c) 2014-2015, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -180,7 +180,7 @@ Queued::notify(const CacheAccessProbeArg &acc, const PrefetchInfo &pfi) if (queueSquash) { auto itr = pfq.begin(); while (itr != pfq.end()) { - if (itr->pfInfo.getAddr() == blk_addr && + if (blockAddress(itr->pfInfo.getAddr()) == blk_addr && itr->pfInfo.isSecure() == is_secure) { DPRINTF(HWPrefetch, "Removing pf candidate addr: %#x " "(cl: %#x), demand request going to the same addr\n", From 9fe998a8c081795e3aeae7d7d18bef0291db0852 Mon Sep 17 00:00:00 2001 From: Richard Cooper Date: Mon, 14 Nov 2022 10:56:36 +0000 Subject: [PATCH 2/5] mem-cache: Update default prefetch options. Update the default prefetch options to achieve out-of-the box prefetcher performance closer to that which a typical user would expect. Configurations that set these parameters explicitly will be unaffected. The new defaults were identified as part of work on gem5 prefetchers undertaken by Nikolaos Kyparissas while on internship at Arm. Change-Id: Ia6c1803c86e42feef01de40c34d928de50fe0bed Reviewed-by: Andreas Sandberg --- src/mem/cache/prefetch/Prefetcher.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index 335d6f6942..c6d6d00dde 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2014, 2019, 2023 ARM Limited +# Copyright (c) 2012, 2014, 2019, 2023-2024 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -79,7 +79,7 @@ class BasePrefetcher(ClockedObject): "Notify the hardware prefetcher on every access (not just misses)", ) prefetch_on_pf_hit = Param.Bool( - False, + True, "Notify the hardware prefetcher on hit on prefetched lines", ) use_virtual_addresses = Param.Bool( From 1ccdf407cbd91f68763b10fa12c533e030fa5c1d Mon Sep 17 00:00:00 2001 From: Nikolaos Kyparissas Date: Tue, 30 Aug 2022 17:14:03 +0100 Subject: [PATCH 3/5] mem-cache: Added clean eviction check for prefetchers. pkt->req->isCacheMaintenance() would not include a check for clean eviction before notifying the prefetcher, causing gem5 to crash. Change-Id: I4a56c7384818c63d6e2263f26645e87cef1243cb Reviewed-by: Andreas Sandberg --- src/mem/cache/prefetch/base.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index e3464a8239..a85b024109 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2023-2024 Arm Limited + * Copyright (c) 2013-2014, 2022-2024 Arm Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -238,6 +238,7 @@ Base::probeNotify(const CacheAccessProbeArg &acc, bool miss) // operations or for writes that we are coaslescing. if (pkt->cmd.isSWPrefetch()) return; if (pkt->req->isCacheMaintenance()) return; + if (pkt->isCleanEviction()) return; if (pkt->isWrite() && cache.coalesce()) return; if (!pkt->req->hasPaddr()) { panic("Request must have a physical address"); From a5fece3b9145408360ffde1956c18fd781282a7c Mon Sep 17 00:00:00 2001 From: Nikolaos Kyparissas Date: Tue, 30 Aug 2022 17:04:21 +0100 Subject: [PATCH 4/5] mem: added distance parameter to stride prefetcher The Stride Prefetcher will skip this number of strides ahead of the first identified prefetch, then generate `degree` prefetches at `stride` intervals. A value of zero indicates no skip (i.e. start prefetching from the next identified prefetch address). This parameter can be used to increase the timeliness of prefetches by starting to prefetch far enough ahead of the demand stream to cover the memory system latency. [Richard Cooper : - Added detail to commit comment and `distance` Param documentation. - Changed `distance` Param from `Param.Int` to `Param.Unsigned`. ] Change-Id: I4ce79c72d74445b12acf68e0a54e13966e30041c Co-authored-by: Richard Cooper Signed-off-by: Richard Cooper Reviewed-by: Andreas Sandberg --- src/mem/cache/prefetch/Prefetcher.py | 9 ++++++++- src/mem/cache/prefetch/stride.cc | 6 ++++-- src/mem/cache/prefetch/stride.hh | 10 +++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py index c6d6d00dde..8f0a66fb69 100644 --- a/src/mem/cache/prefetch/Prefetcher.py +++ b/src/mem/cache/prefetch/Prefetcher.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, 2014, 2019, 2023-2024 Arm Limited +# Copyright (c) 2012, 2014, 2019, 2022-2024 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -191,6 +191,13 @@ class StridePrefetcher(QueuedPrefetcher): use_requestor_id = Param.Bool(True, "Use requestor id based history") degree = Param.Int(4, "Number of prefetches to generate") + distance = Param.Unsigned( + 0, + "How far ahead of the demand stream to start prefetching. " + "Skip this number of strides ahead of the first identified prefetch, " + "then generate `degree` prefetches at `stride` intervals. " + "A value of zero indicates no skip.", + ) table_assoc = Param.Int(4, "Associativity of the PC table") table_entries = Param.MemorySize("64", "Number of entries of the PC table") diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index b2e4702f20..7b517cecca 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2022 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -84,6 +84,7 @@ Stride::Stride(const StridePrefetcherParams &p) threshConf(p.confidence_threshold/100.0), useRequestorId(p.use_requestor_id), degree(p.degree), + distance(p.distance), pcTableInfo(p.table_assoc, p.table_entries, p.table_indexing_policy, p.table_replacement_policy) { @@ -176,7 +177,8 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi, prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; } - Addr new_addr = pf_addr + d * prefetch_stride; + Addr new_addr = pf_addr + distance * prefetch_stride + + d * prefetch_stride; addresses.push_back(AddrPriority(new_addr, 0)); } } else { diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 41cadbe7d0..cb5d79fd0e 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2022 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -105,6 +105,14 @@ class Stride : public Queued const int degree; + /** How far ahead of the demand stream to start prefetching. + * + * Skip this number of strides ahead of the first identified + * prefetch, then generate `degree` prefetches at `stride` + * intervals. A value of zero indicates no skip. + */ + const int distance; + /** * Information used to create a new PC table. All of them behave equally. */ From 1d5be8d9e583c05499bd17dc7f4daa7baf72c54e Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Thu, 9 Nov 2023 16:57:01 +0000 Subject: [PATCH 5/5] mem-cache: Optimize strided prefetcher address generation This commit optimizes the address generation logic in the strided prefetcher by introducing the following changes (d is the degree of the prefetcher) * Evaluate the fixed prefetch_stride only once (and not d-times) * Replace 2d multiplications (d * prefetch_stride and distance * prefetch_stride) with additions by updating the new base prefetch address while looping Change-Id: I3ec0c642bc9ec7635b0d38308797e99b645304bb Signed-off-by: Giacomo Travaglini --- src/mem/cache/prefetch/stride.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index 7b517cecca..e4a552b912 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Inria - * Copyright (c) 2012-2013, 2015, 2022 Arm Limited + * Copyright (c) 2012-2013, 2015, 2022-2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -169,16 +169,16 @@ Stride::calculatePrefetch(const PrefetchInfo &pfi, return; } + // Round strides up to atleast 1 cacheline + int prefetch_stride = new_stride; + if (abs(new_stride) < blkSize) { + prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; + } + + Addr new_addr = pf_addr + distance * prefetch_stride; // Generate up to degree prefetches for (int d = 1; d <= degree; d++) { - // Round strides up to atleast 1 cacheline - int prefetch_stride = new_stride; - if (abs(new_stride) < blkSize) { - prefetch_stride = (new_stride < 0) ? -blkSize : blkSize; - } - - Addr new_addr = pf_addr + distance * prefetch_stride - + d * prefetch_stride; + new_addr += prefetch_stride; addresses.push_back(AddrPriority(new_addr, 0)); } } else {