mem-cache: Namespace prefetch state by ContextID - #982
Conversation
Change-Id: Ic7de7e4a146d6a438b75fb3b1b99ea04b9078200
📝 WalkthroughWalkthroughThe prefetch subsystem adds a shared ChangesContext-aware prefetch indexing
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbf6e38a2b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| re_act_entry = re_act.findEntry( | ||
| contextKey(entry->regionAddr, entry->contextId), entry->isSecure()); |
There was a problem hiding this comment.
Preserve the secure bit before probing ReACT
For secure requests that evict an ACT entry, this lookup now passes entry->isSecure() immediately after act.findVictim(), but findVictim() invalidates the victim and TaggedEntry::invalidate() clears the secure bit. As a result secure ReACT state is looked up as non-secure, so SMS misses/recreates ReACT history for secure accesses instead of reusing it; save the victim's secure bit before invalidation or use the intended secure namespace.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
It is a true problem,but it doesn't seem to affect the functionality.
| Addr page_key = contextKey(regionAddress(addr), context_id); | ||
| Addr block_key = contextKey(addr, context_id); |
There was a problem hiding this comment.
Keep shared prefetch filters under one key scheme
When XSComposite enables largeBOP/smallBOP/learnedBOP/IPCP/Opt, the constructor still points them at pfBlockLRUFilter, but those prefetchers continue to contains/insert(addr) with the raw VA. This path now checks contextKey(addr, ctx), so for nonzero ContextIDs an address inserted by those same-context producers is invisible here and vice versa, causing duplicate prefetches and inconsistent throttling; qualify all users of the shared filter or centralize the keying.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
If these prefetchers were enabled, it would indeed be an issue. BOP and CDP prefetcher is enabled in L2.
There was a problem hiding this comment.
Pull request overview
This PR introduces a ContextID-qualified keying scheme for VA/PC-derived prefetcher state to prevent cross-context aliasing in SMT runs (while keeping context 0 behavior identical to legacy single-thread indexing). It applies the new contextKey() helper across multiple upstream prefetch training tables and filters, and adds a focused unit test to validate key behavior.
Changes:
- Add
contextKey(Addr, ContextID)helper and a new GTest validating context-0 preservation and cross-context separation. - Namespace multiple prefetcher tables/filters (SMS, Berti, CMC, XSStride, XsStream, PrefetchFilter, TrainFilter) by
ContextID. - Add/extend stats counters to quantify same-VA cross-context aliasing observations.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/mem/cache/prefetch/xs_stride.hh | Add ContextID tracking to stride/non-stride entries and update non-stride filter API to take context. |
| src/mem/cache/prefetch/xs_stride.cc | Apply contextKey() to stride/non-stride indexing and per-context LRU filter keys. |
| src/mem/cache/prefetch/xs_stream.hh | Add ContextID to stream entries. |
| src/mem/cache/prefetch/xs_stream.cc | Apply contextKey() to stream table lookups/victim selection and LRU filter keys. |
| src/mem/cache/prefetch/sms.hh | Add ContextID fields to ACT/ReACT/PHT entries for context-qualified training/state. |
| src/mem/cache/prefetch/sms.cc | Use contextKey() for ACT/ReACT/PHT lookups and qualify page/block filters by context. |
| src/mem/cache/prefetch/SConscript | Register new context_key.test GTest build target. |
| src/mem/cache/prefetch/prefetch_filter.hh | Add contextKey() include and store ContextID per filter entry; add stat for context aliases. |
| src/mem/cache/prefetch/prefetch_filter.cc | Derive context for insertions, qualify tags via contextKey(), and add alias/collision diagnostics. |
| src/mem/cache/prefetch/context_key.hh | New helper to mix nonzero ContextID into prefetch keys while preserving legacy behavior for context 0/invalid. |
| src/mem/cache/prefetch/context_key.test.cc | New unit test validating key preservation/separation/stability properties. |
| src/mem/cache/prefetch/cmc.hh | Add context to CMC record/storage entries and introduce per-context recorder storage. |
| src/mem/cache/prefetch/cmc.cc | Use per-context recorders and qualify CMC storage/filter keys with contextKey(). |
| src/mem/cache/prefetch/berti.hh | Add ContextID to history table entries and qualify training lookups by context. |
| src/mem/cache/prefetch/berti.cc | Qualify Berti history table keys and filters using contextKey(). |
| src/mem/cache/prefetch/base.hh | Include context_key.hh and add TrainFilter context-alias statistic. |
| src/mem/cache/prefetch/base.cc | Qualify TrainFilter buffer deduplication by context and add context-alias counting. |
Comments suppressed due to low confidence (1)
src/mem/cache/prefetch/sms.cc:393
entry->isSecure()has been cleared byfindVictim()invalidation, so this path will insert ReACT entries as non-secure even when the evicted ACT entry was secure. Usesecureconsistently for_setSecure()and theinsertEntry()call.
re_act_entry->contextId = entry->contextId;
re_act_entry->_setSecure(entry->isSecure());
re_act.insertEntry(
contextKey(re_act_entry->regionAddr, re_act_entry->contextId),
re_act_entry->isSecure(), re_act_entry);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| re_act_entry = re_act.findEntry( | ||
| contextKey(entry->regionAddr, entry->contextId), entry->isSecure()); |
| RecordEntry() | ||
| : addr(0), is_secure(true), contextId(InvalidContextID) | ||
| {} |
| @@ -414,6 +438,7 @@ PrefetchFilter::Insert(Addr region_addr, uint64_t region_bits, uint8_t alias_bit | |||
| victim->decr_mode = decr_mode; | |||
🚀 Coremark Smoke Test Results
✅ Difftest smoke test passed! |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src/mem/cache/prefetch/xs_stride.hh (1)
62-72: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
matchedSinceAllocstill left uninitialized inStrideEntry().The ctor init list now sets
contextId(InvalidContextID)right next topc(0), butmatchedSinceAlloc(declared right belowhistStrides) is still never initialized.xs_stride.ccreads!entry->matchedSinceAllocon a freshly-victimized entry before it's ever assigned, which is a read of indeterminate state for never-before-used table slots.🛡️ Proposed fix
StrideEntry() : TaggedEntry(), stride(0), lastAddr(0), conf(2, 0), depth(1), lateConf(4, 7), longStride(4, 7), pc(0), - contextId(InvalidContextID) + contextId(InvalidContextID), + matchedSinceAlloc(false) {}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/xs_stride.hh` around lines 62 - 72, Initialize matchedSinceAlloc in the StrideEntry() constructor initializer list, using the appropriate false/zero value, so freshly allocated or victimized entries have a defined state before xs_stride.cc reads it.src/mem/cache/prefetch/cmc.hh (1)
34-46: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
RecordEntry's default constructor leavespcuninitialized.
addr,is_secure, andcontextIdare initialized, butpcis not — reading a default-constructedRecordEntry::pcis undefined behavior.🐛 Proposed fix
RecordEntry() - : addr(0), is_secure(true), contextId(InvalidContextID) + : pc(0), addr(0), is_secure(true), contextId(InvalidContextID) {}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/cmc.hh` around lines 34 - 46, Initialize the pc member in RecordEntry’s default constructor, using the same zero/default address value as addr, so every field is initialized when a RecordEntry is default-constructed.src/mem/cache/prefetch/berti.cc (1)
84-145: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winMissing context-match guard on
historyTable.findEntryhit paths — cross-context history/delta mixing on hash collision.None of these three lookups verify
entry->contextId == context_idbefore reusing the found entry'shistory/deltas(unlikePrefetchFilter::Insert, which explicitly treats a context mismatch as a collision). SincecontextKeyis explicitly documented as not partitioning capacity, a collision here will merge address history across different execution contexts and issue prefetches derived from another context's accesses. See the consolidated comment at the end of the review for the fix and all affected sites.Also applies to: 231-244, 308-351
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/berti.cc` around lines 84 - 145, Add an explicit context-match guard to each history-table lookup hit path, including updateHistoryTable and the other affected lookup sites, requiring entry->contextId to equal the requested context_id before reusing history or delta state. Treat mismatches as hash collisions and follow the existing collision-handling behavior used by PrefetchFilter::Insert rather than merging or applying the found entry.src/mem/cache/prefetch/cmc.cc (1)
141-188: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winMissing context-match guard on
storage.findEntry— cross-context prefetch address leak on hash collision.
match_entryis used directly (issuing itsaddressesas prefetch targets at 146-181, or invalidating it at 183-188) without ever checkingmatch_entry->contextId == context_id. On a hash collision between two different contexts'storage_keys — whichcontextKeyexplicitly does not prevent — this will issue prefetches to addresses recorded for a different execution context, or wrongly invalidate that other context's learned entry. This is the most severe instance of a pattern also present inberti.cc/berti.hh; see the consolidated comment at the end of the review for the fix and all affected sites.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/cmc.cc` around lines 141 - 188, Add an explicit context-match guard after storage.findEntry in the prefetch handling flow, requiring match_entry->contextId to equal context_id before using the entry. Ensure both the prefetch/address issuance path and the unused-entry invalidation path only operate on a matching-context entry; treat mismatches as no match without issuing prefetches or invalidating the entry.
🧹 Nitpick comments (5)
src/mem/cache/prefetch/cmc.hh (2)
59-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNew constant
nrEntrydoesn't follow ALL_CAPS naming.This is a newly-introduced
static constexpr(replacing the old instance fieldnr_entry), so per repo guidelines it should beNR_ENTRY. Worth renaming now since all ~6 call sites incmc.ccare already touched in this same diff.As per coding guidelines: "Constants should use ALL_CAPS naming convention."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/cmc.hh` at line 59, Rename the newly introduced static constexpr constant nrEntry to NR_ENTRY in the relevant class, and update all references in cmc.cc and nearby code to use the ALL_CAPS name. Preserve its value and behavior.Source: Coding guidelines
146-147: 🚀 Performance & Scalability | 🔵 TrivialShared 4-entry trigger stack across all contexts may become a contention point.
As noted in the PR summary, this stack intentionally stays shared. Worth keeping in mind that once more than
STACK_SIZE(4) contexts have concurrent in-flight triggers,train_trigger's!trigger.full()guard will start starving newer contexts' trigger registration until older entries drain.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/cmc.hh` around lines 146 - 147, Update the shared trigger handling around train_trigger so registrations from more than STACK_SIZE concurrent contexts are not silently starved by the !trigger.full() guard. Preserve the shared trigger design, but ensure newer contexts are queued or otherwise retried when the four-entry circular buffer is full.src/mem/cache/prefetch/berti.hh (1)
102-112: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
shouldTrain's hit lookup lacks a context-match guard (lower-impact variant of the cross-file issue below).
historyTable.findEntry(contextKey(pcHash(pc), context_id), ...)can return an entry belonging to a different context on a hash collision; here it only affects a boolean training-permission decision (less severe than the data-mutating call sites inberti.cc/cmc.cc), but it's part of the same missing-verification pattern — see the consolidated comment at the end of the review.Also applies to: 195-211
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/berti.hh` around lines 102 - 112, Update the shouldTrain hit-lookup path to verify that the entry returned by historyTable.findEntry(contextKey(pcHash(pc), context_id), ...) belongs to the requested context before using its hysteresis/training state. Preserve the existing behavior for matching contexts and treat hash-collision entries as non-matches.src/mem/cache/prefetch/prefetch_filter.cc (1)
384-459: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winO(n) full-table scan added purely for stats bookkeeping in
Insert's hot path.Lines 390-396 iterate the entire table on every
Insertcall just to incrementcontextAliasCount. Same root cause and same fix idea as thebase.ccTrainFilter scan — see the consolidated comment at the end.Separately: the explicit
e->region_addr != region_addr || e->contextId != context_idcollision guard (405-415) is the right pattern — it's exactly what's missing in Berti'shistoryTable.findEntryand CMC'sstorage.findEntrylookups (see consolidated comment).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/prefetch_filter.cc` around lines 384 - 459, The Insert hot path in the prefetch filter performs an unnecessary full-table scan solely to update contextAliasCount. Remove this O(n) loop and replace it with constant-time alias-stat bookkeeping using the existing lookup/collision information, while preserving correct counting for entries matching region_addr under a different contextId; retain the explicit collision guard around table.findEntry.src/mem/cache/prefetch/base.cc (1)
624-667: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winO(n) buffer scan added purely for stats bookkeeping on a per-cycle hot path.
For every request being flushed into
trainingBuffer, the code now linearly scans the entire buffer (for (const auto &buffered : trainingBuffer)) just to incrementtrainFilterContextAliases. This runs every cycle for every collected training request, turning an O(1)-ish filter check into an O(n·m) cost as the buffer fills. Consider trackingAddr -> ContextID(or a small multiset) alongsidetrainingBufferBlockAddrsfor O(1) alias detection instead of scanning the deque.This shares the same root cause as the analogous scan in
prefetch_filter.cc'sInsert— see the consolidated comment at the end of this review.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/base.cc` around lines 624 - 667, Replace the per-request scan over trainingBuffer in the flush logic with an auxiliary Addr-to-context tracking structure (or equivalent multiset) maintained alongside trainingBufferBlockAddrs. Use that structure for constant-time detection and incrementing of trainFilterContextAliases, and update it whenever entries are added or removed so alias statistics remain accurate without scanning the deque.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/mem/cache/prefetch/berti.cc`:
- Around line 84-145: Add an explicit context-match guard to each history-table
lookup hit path, including updateHistoryTable and the other affected lookup
sites, requiring entry->contextId to equal the requested context_id before
reusing history or delta state. Treat mismatches as hash collisions and follow
the existing collision-handling behavior used by PrefetchFilter::Insert rather
than merging or applying the found entry.
In `@src/mem/cache/prefetch/cmc.cc`:
- Around line 141-188: Add an explicit context-match guard after
storage.findEntry in the prefetch handling flow, requiring
match_entry->contextId to equal context_id before using the entry. Ensure both
the prefetch/address issuance path and the unused-entry invalidation path only
operate on a matching-context entry; treat mismatches as no match without
issuing prefetches or invalidating the entry.
In `@src/mem/cache/prefetch/cmc.hh`:
- Around line 34-46: Initialize the pc member in RecordEntry’s default
constructor, using the same zero/default address value as addr, so every field
is initialized when a RecordEntry is default-constructed.
In `@src/mem/cache/prefetch/xs_stride.hh`:
- Around line 62-72: Initialize matchedSinceAlloc in the StrideEntry()
constructor initializer list, using the appropriate false/zero value, so freshly
allocated or victimized entries have a defined state before xs_stride.cc reads
it.
---
Nitpick comments:
In `@src/mem/cache/prefetch/base.cc`:
- Around line 624-667: Replace the per-request scan over trainingBuffer in the
flush logic with an auxiliary Addr-to-context tracking structure (or equivalent
multiset) maintained alongside trainingBufferBlockAddrs. Use that structure for
constant-time detection and incrementing of trainFilterContextAliases, and
update it whenever entries are added or removed so alias statistics remain
accurate without scanning the deque.
In `@src/mem/cache/prefetch/berti.hh`:
- Around line 102-112: Update the shouldTrain hit-lookup path to verify that the
entry returned by historyTable.findEntry(contextKey(pcHash(pc), context_id),
...) belongs to the requested context before using its hysteresis/training
state. Preserve the existing behavior for matching contexts and treat
hash-collision entries as non-matches.
In `@src/mem/cache/prefetch/cmc.hh`:
- Line 59: Rename the newly introduced static constexpr constant nrEntry to
NR_ENTRY in the relevant class, and update all references in cmc.cc and nearby
code to use the ALL_CAPS name. Preserve its value and behavior.
- Around line 146-147: Update the shared trigger handling around train_trigger
so registrations from more than STACK_SIZE concurrent contexts are not silently
starved by the !trigger.full() guard. Preserve the shared trigger design, but
ensure newer contexts are queued or otherwise retried when the four-entry
circular buffer is full.
In `@src/mem/cache/prefetch/prefetch_filter.cc`:
- Around line 384-459: The Insert hot path in the prefetch filter performs an
unnecessary full-table scan solely to update contextAliasCount. Remove this O(n)
loop and replace it with constant-time alias-stat bookkeeping using the existing
lookup/collision information, while preserving correct counting for entries
matching region_addr under a different contextId; retain the explicit collision
guard around table.findEntry.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 809f50d0-d4f4-4db9-b424-3013c146f603
📒 Files selected for processing (17)
src/mem/cache/prefetch/SConscriptsrc/mem/cache/prefetch/base.ccsrc/mem/cache/prefetch/base.hhsrc/mem/cache/prefetch/berti.ccsrc/mem/cache/prefetch/berti.hhsrc/mem/cache/prefetch/cmc.ccsrc/mem/cache/prefetch/cmc.hhsrc/mem/cache/prefetch/context_key.hhsrc/mem/cache/prefetch/context_key.test.ccsrc/mem/cache/prefetch/prefetch_filter.ccsrc/mem/cache/prefetch/prefetch_filter.hhsrc/mem/cache/prefetch/sms.ccsrc/mem/cache/prefetch/sms.hhsrc/mem/cache/prefetch/xs_stream.ccsrc/mem/cache/prefetch/xs_stream.hhsrc/mem/cache/prefetch/xs_stride.ccsrc/mem/cache/prefetch/xs_stride.hh
Keep one physical CMC recorder and allow only the oldest trigger's ContextID to train it. Preserve legacy trigger admission while retaining context-qualified storage, and expose fixed-cost counters for the CMC training and send path. Change-Id: Ic5e0d3a54cbc8677bfe4fde0656178ba94173ce3
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/mem/cache/prefetch/cmc.hh (1)
58-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename
nrEntryto ALL_CAPS.Line 58 declares a constant; rename it to
NR_ENTRYand update itscmc.ccreferences.Proposed fix
-static constexpr int nrEntry = 12; +static constexpr int NR_ENTRY = 12;As per coding guidelines, “Constants should use ALL_CAPS naming convention.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mem/cache/prefetch/cmc.hh` at line 58, Rename the static constant nrEntry to NR_ENTRY in cmc.hh, and update every corresponding reference in cmc.cc to use the new ALL_CAPS identifier.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/mem/cache/prefetch/cmc.hh`:
- Line 58: Rename the static constant nrEntry to NR_ENTRY in cmc.hh, and update
every corresponding reference in cmc.cc to use the new ALL_CAPS identifier.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1e77549b-1c6f-4403-b8ab-954d6288ca6f
📒 Files selected for processing (2)
src/mem/cache/prefetch/cmc.ccsrc/mem/cache/prefetch/cmc.hh
🚀 Coremark Smoke Test Results
✅ Difftest smoke test passed! |
|
[Generated by GEM5 Performance Robot] Standard PerformanceOverall Score
|
| re_act_entry = re_act.findEntry( | ||
| contextKey(entry->regionAddr, entry->contextId), entry->isSecure()); |
There was a problem hiding this comment.
It is a true problem,but it doesn't seem to affect the functionality.
| Addr page_key = contextKey(regionAddress(addr), context_id); | ||
| Addr block_key = contextKey(addr, context_id); |
There was a problem hiding this comment.
If these prefetchers were enabled, it would indeed be an issue. BOP and CDP prefetcher is enabled in L2.
| bool do_training = | ||
| !train_trigger && !trigger.empty() && nocovered; | ||
| !train_trigger && !trigger.empty() && nocovered && | ||
| trigger.front().contextId == context_id; |
There was a problem hiding this comment.
CMC currently does not support simultaneous training acorss 2 threads, this may be a problem when enable SMT.
Motivation
In SMT A+A runs, two independent processes may use the same virtual address and PC while translating to different physical pages. The downstream prefetch queue and translation path already preserve
ContextID, but upstream training tables and candidate filters still used VA/PC-only keys. One context could therefore train, hit, overwrite, or filter state belonging to the other before the context-aware queue stage.Approach
Table entry counts, replacement policies, PF-buffer arbitration, queue sizes, recorder capacity, and prefetch issue bandwidth remain shared across SMT contexts.
CMC regression root cause
The initial version replaced the original single 13-entry CMC
Recorderwith one recorder perContextID. It also changed trigger admission fromtrigger.empty() || match_entryto “this context has no trigger or storage matched.” Together these changes increased physical training concurrency and populated CMC storage with many additional trigger keys. Every storage hit sends a full temporal sequence, so the extra storage population amplified CMC generated/issued traffic and cache interference.The fix uses ContextID only as an ownership and namespace boundary; it does not create per-context physical capacity.
Validation
git diff --checkpython3 util/style.py -m src/mem/cache/prefetch/cmc.cc src/mem/cache/prefetch/cmc.hhscons build/RISCV/gem5.opt --gold-linker -j64mcf_12253SMT checkpoint run with difftest,--maxinsts=40000000, using the same checkpoint and instruction limit as the 0.3c SMT CI.Local
mcf_12253, 5M/thread differentialTraining completions slightly increase when legacy trigger admission is restored, while storage inserts and hits fall sharply. This distinguishes the second issue from simple throttling: per-context ordinary-trigger admission was creating many more distinct storage sequences.
Full 40M/thread measurement interval
The baseline and initial-PR columns are from the corresponding 0.3c SMT CI archives; the final-fix column is the local full-length run with the same checkpoint/configuration.
Final-fix CMC counters report 260,431 training completions, 1,394 storage inserts, 259,037 storage updates, 591,468 storage hits, and zero temporal data-queue drops. The full run exited normally at the per-thread instruction limit with difftest enabled.
SMT 0.3c CI
Fresh run: 30149844781, commit
265c06bb2e. All 148 slices completed and the workflow succeeded.The CMC regression is eliminated in the full suite. The largest remaining benchmark-level delta versus baseline is
omnetppat -4.05%; it no longer dominates the aggregate result.