Clean Prefetcher implementation - #297
Conversation
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Remove Prefetcher_test target and update comments for clarity. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
|
Can you create an arch that has the big core with the prefetcher enabled? Would be interesting to compare reports. |
Signed-off-by: pritish <pmdevops29@gmail.com>
Updated comments to reflect changes in flow control management and removed unused prefetcher queue credits. Signed-off-by: pritish <pmdevops29@gmail.com>
Removed unused prefetcher queue credit handling and initial credit sending functionality. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Updated DCache to only send acknowledgments for instruction-backed requests, ensuring proper handling of memory access information. Signed-off-by: pritish <pmdevops29@gmail.com>
this is the results I got after comparing `big_core` vs `big_core_with_prefetcher` using `dhry_riscv.zstf` (2M instructions) I got after comparing @klingaard also I also made changes to `DCache.cpp` to handle prefetch requests that have no `InstPtr` (they're synthetic requests from the prefetch engine). Can you review those?
|
| { | ||
| cout << "Testing NextLinePrefetchEngine..." << endl; | ||
|
|
||
| olympia::NextLinePrefetchEngine engine(2, 64); |
There was a problem hiding this comment.
Please comment on what 2 and 64 mean here
There was a problem hiding this comment.
I have added a comment for better clarity.
rajatbhatia1
left a comment
There was a problem hiding this comment.
This is extremely well written implementation of the prefetcher.
I have pointed a few places that may need improvement.
| EXPECT_TRUE(ret); | ||
| EXPECT_TRUE(engine.isPrefetchReady()); | ||
|
|
||
| // Consume any prefetches produced (engine controls Inst in prefetch MemoryAccessInfo) |
There was a problem hiding this comment.
We have tested that stride prefetcher is generating prefetches. However we should also check that correct prefetch addresses are generated
There was a problem hiding this comment.
What interface is used to restore prefetch_credits_?
There was a problem hiding this comment.
I have added restorePrefetchCredit() as a public method on Prefetcher. DCache calls it when a prefetch request completes (hit or miss resolved), which increments prefetcher_credits_ and re-schedules generation if the engine has pending prefetches.
| // FIX: stride_table_ MUST be initialized before prefetch_queue_ | ||
| stride_table_(table_size), | ||
| prefetch_queue_(num_lines_to_prefetch * 2) | ||
| { |
There was a problem hiding this comment.
Please add assertion on table size and cache line size to be positive
| if (current_stride == entry.last_stride && current_stride != 0) | ||
| { | ||
| // Stride matches - increase confidence | ||
| entry.confidence++; |
There was a problem hiding this comment.
I think we should limit the confidence to a max value, otherwise there is a risk of overflow.
Added assertions to ensure positive values for table_size and cache_line_size. Updated comments for clarity and added a cap to confidence increment. Signed-off-by: pritish <pmdevops29@gmail.com>
Added a new method to restore prefetch credits after servicing prefetch requests. Signed-off-by: pritish <pmdevops29@gmail.com>
Added a method to restore a prefetch credit and handle prefetch generation. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
|
@rajatbhatia1 I have done the changes you recommended. Can you check it if they are correct? |
|
Here is an example of how credit mechanism is used in Olympia On Producer side (see Dispatcher.cpp/hpp)
On Receiver side (e.g. see IssueQueue.hpp/cpp)
|
|
Hi @pm-ju, Thanks for the work on the prefetcher and the communication earlier today. core/prefetcher/
├── CMakeLists.txt
├── Prefetcher.cpp
├── Prefetcher.hpp
├── PrefetcherIF.hpp
└── engines/
├── NextLinePrefetchEngine.cpp
├── NextLinePrefetchEngine.hpp
├── StridePrefetchEngine.cpp
└── StridePrefetchEngine.hppImportant Notes:
Could you also point me to where the DCache is restoring the credits of the prefetcher, I was not able to find it. Or is it still a work in progress. Let me know if you run into any issue with restructuring or anything else. Thanks again for your contribution. |
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Removed prefetcher source files from the core library and added prefetcher as a separate subdirectory. Signed-off-by: pritish <pmdevops29@gmail.com>
Added an output port for sending credits to the Prefetcher. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Updated comments to reflect changes in prefetcher behavior and added new port connections. Signed-off-by: pritish <pmdevops29@gmail.com>
Removed credit restoration logic for pending requests and in-flight prefetches in handleFlush. Signed-off-by: pritish <pmdevops29@gmail.com>
Added credit return for prefetch requests before MSHR entry removal. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Removed prefetch credit handling for MSHR entries before erasure. Signed-off-by: pritish <pmdevops29@gmail.com>
Added handling for memory requests from the prefetcher in DCache. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Updated connections between prefetcher and DCache ports. Signed-off-by: pritish <pmdevops29@gmail.com>
|
Hey, I've pushed the latest changes which include both the file reorganization and the complete refactoring of the Prefetcher credit system to use a decoupled, port-based Sparta signaling architecture. Here is a summary of the structural changes implemented:
Current Status & Request for Help: Despite these structural improvements, the CI tests are still aborting ( Could I get some extra time to investigate this via the CI logs, or would someone from the team be able to shed some light on what might be triggering the remaining aborts? Any guidance or pointers on debugging this specific failure would be greatly appreciated! |
|
The above changes should clear all your prefetcher and regression tests, for example here is the __ olympia_arch_big_core_with_prefetcher_test__ . jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release/test/sim$ ctest -R olympia_arch_big_core_with_prefetcher_test --verbose
UpdateCTestConfiguration from :/home/jha/workspace/opensource/riscv-perf-model/release/test/sim/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/jha/workspace/opensource/riscv-perf-model/release/test/sim/DartConfiguration.tcl
Test project /home/jha/workspace/opensource/riscv-perf-model/release/test/sim
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 14
Start 14: olympia_arch_big_core_with_prefetcher_test
14: Test command: /home/jha/workspace/opensource/riscv-perf-model/release/olympia "-i500K" "--workload" "traces/dhry_riscv.zstf" "--arch" "big_core_with_prefetcher"
14: Working Directory: /home/jha/workspace/opensource/riscv-perf-model/release/test/sim
14: Test timeout computed to be: 10000000
14: # Name: Olympia RISC-V Perf Model
14: # Cmdline: /home/jha/workspace/opensource/riscv-perf-model/release/olympia -i500K --workload traces/dhry_riscv.zstf --arch big_core_with_prefetcher
14: # Exe: /home/jha/workspace/opensource/riscv-perf-model/release/olympia
14: # SimulatorVersion: v0.1.0
14: # Repro: Git SHA: 66d7060
14: # Start: Sunday Sun Apr 5 15:32:53 2026
14: # Elapsed: 0.002476s
14: # Sparta Version: map_v2.1.15
14: [PARAMETER INCLUDE NOTE] : Including "arches/big_core.yaml"
14: [PARAMETER INCLUDE NOTE] : Including "arches/medium_core.yaml"
14: [PARAMETER INCLUDE NOTE] : Including "arches/small_core.yaml"
14: [in] Arch Config: ArchCfg Node "" <- file: "/home/jha/workspace/opensource/riscv-perf-model/arches/big_core_with_prefetcher.yaml"
14:
14: Setting up Simulation Content...
14: Resources:
14: cpu
14: Building tree...
14: Configuring tree...
14: Finalizing tree...
14: Inst Allocator: 1238 Inst objects allocated/created
14: Inst Allocator: 1238 Inst objects allocated/created
14: Inst Allocator: 0 Inst objects allocated/created
14: Inst Allocator: 0 Inst objects allocated/created
14: Inst Allocator: 1238 Inst objects allocated/created
14: NOTE: unread optional unbound parameter: "top.cpu.core0.extension.core_extensions.exe_pipe_rename" from: "". value: "[[exe0,sys_pipe],[exe1,alu1_pipe],[exe2,alu2_pipe],[exe3,alu3_pipe],[exe4,alu4_pipe],[exe5,alu5_pipe],[exe6,fpu0_pipe],[exe7,fpu1_pipe],[exe8,br0_pipe],[exe9,br1_pipe],[exe10,vint_pipe]]". Path exists in tree up to: "top.cpu.core0"
14: NOTE: unread optional unbound parameter: "top.cpu.core0.extension.core_extensions.issue_queue_to_pipe_map" from: "". value: "[[0,1],[2,3],[4,5],[6,7],[8,9],[10]]". Path exists in tree up to: "top.cpu.core0"
14: NOTE: unread optional unbound parameter: "top.cpu.core0.extension.core_extensions.pipelines" from: "". value: "[[sys],[int,div],[int,mul],[int,mul,i2f,cmov],[int],[int,vset],[float,faddsub,fmac],[float,f2i],[br],[br],[vint,vdiv,vmul,vfixed,vmask,vmv,v2s,vfloat,vfdiv,vfmul,vpermute,vload,vstore]]". Path exists in tree up to: "top.cpu.core0"
14: Preparing to run...
14: Meta-Parameters:
14: architecture: big_core_with_prefetcher
14: is_final_config: false
14: Non-default model parameters: 17
14: Running...
14: olympia: STF file input detected
14: Running Complete
14: Simulation Performance : wall(31.7200), system(0.0600), user(32.6200)
14: Scheduler Tick Rate (KTPS): 18.1644 (1k ticks per second)
14: Scheduler Event Rate (KEPS): 645.636 KEPS (1k events per second)
14: Scheduler Events Fired: 21060649
14: Run Successful!
14: Saving reports...
14: Inst Allocator: 1238 Inst objects allocated/created
14: Inst Allocator: 1238 Inst objects allocated/created
14: Inst Allocator: 316 Inst objects allocated/created
1/1 Test #14: olympia_arch_big_core_with_prefetcher_test ... Passed 32.20 sec
The following tests passed:
olympia_arch_big_core_with_prefetcher_test
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 32.21 sec
jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release/test/sim$ |
|
The Dcache test is still failing, you can investigate it via going into the test/core/dcache folder and running the following command : jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release/test/core/dcache$ ctest --verbose
UpdateCTestConfiguration from :/home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache/DartConfiguration.tcl
Test project /home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: Dcache_test_arbitrate
1: Test command: /home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache/Dcache_test "arbitrate.out" "-c" "test_arches/1_src_Dcache.yaml" "--input-file" "next_lvl_cache_refill.json"
1: Working Directory: /home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache
1: Test timeout computed to be: 10000000
1: [in] Configuration: Node "" <- file: "test_arches/1_src_Dcache.yaml"
1:
1: Setting up Simulation Content...
1: Resources:
1:
1: Building tree...
1: Configuring tree...
1: Finalizing tree...
1: Inst Allocator: 1238 Inst objects allocated/created
1: Inst Allocator: 1238 Inst objects allocated/created
1: Inst Allocator: 0 Inst objects allocated/created
1: Inst Allocator: 0 Inst objects allocated/created
1: Inst Allocator: 1238 Inst objects allocated/created
1: olympia: JSON file input detected
1: Preparing to run...
1: Meta-Parameters:
1: architecture: NONE
1: is_final_config: false
1: Non-default model parameters: 5
1: Running...
1: Running Complete
1: *** Simulation Performance cannot be measured -- no user time detected. Did the simulator run long enough?
1: Scheduler Events Fired: 41
1: Run Successful!
1: Saving reports...
1: File comparison test between "arbitrate.out" and "expected_output/arbitrate.out.EXPECTED" FAILED on line 143 in file /home/jha/workspace/opensource/riscv-perf-model/test/core/dcache/Dcache_test.cpp
1: Exception: Files differed at pos 460 (line 2, col 58) with chars: 'A' != 'R'
1:
1: Inst Allocator: 1238 Inst objects allocated/created
1: Inst Allocator: 1238 Inst objects allocated/created
1: Inst Allocator: 2 Inst objects allocated/created
1:
1: 1 ERROR(S) found during test.
1:
1/1 Test #1: Dcache_test_arbitrate ............***Failed 0.19 sec
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.19 sec
The following tests FAILED:
1 - Dcache_test_arbitrate (Failed)
Errors while running CTest
Output from these tests are in: /home/jha/workspace/opensource/riscv-perf-model/release/test/core/dcache/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.But this is just a comparison between a new arbitrate.out and jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release/test/core/dcache$ diff arbitrate.out expected_output/arbitrate.out.EXPECTED
6,7c6,7
< #Start: Sunday Sun Apr 5 15:36:49 2026
< #Elapsed: 0.022949s
---
> #Start: Saturday Sat Oct 19 15:35:23 2024
> #Elapsed: 0.002073s
10c10
< {0000000000 00000000 top.dcache info} arbitrateL2LsuReq_: Arbitrating LSU request memptr: deadbeef uid:0 BEFORE_FETCH 0 pid:1 uopid:0 'lw 5,3'
---
> {0000000000 00000000 top.dcache info} arbitrateL2LsuReq_: Received LSU request memptr: deadbeef uid:0 BEFORE_FETCH 0 pid:1 uopid:0 'lw 5,3'
30c30
< {0000000007 00000007 top.dcache info} arbitrateL2LsuReq_: Arbitrating L2 Refill request memptr: deadbeef uid:0 BEFORE_FETCH 0 pid:1 uopid:0 'lw 5,3'
---
> {0000000007 00000007 top.dcache info} arbitrateL2LsuReq_: Received Refill request memptr: deadbeef uid:0 BEFORE_FETCH 0 pid:1 uopid:0 'lw 5,3'
37c37
< {0000000008 00000008 top.dcache info} arbitrateL2LsuReq_: Arbitrating LSU request memptr: deedbeef uid:1 BEFORE_FETCH 0 pid:2 uopid:0 'lw 5,3'
---
> {0000000008 00000008 top.dcache info} arbitrateL2LsuReq_: Received LSU request memptr: deedbeef uid:1 BEFORE_FETCH 0 pid:2 uopid:0 'lw 5,3'
63c63
< {0000000015 00000015 top.dcache info} arbitrateL2LsuReq_: Arbitrating L2 Refill request memptr: deedbeef uid:1 BEFORE_FETCH 0 pid:2 uopid:0 'lw 5,3'
---
> {0000000015 00000015 top.dcache info} arbitrateL2LsuReq_: Received Refill request memptr: deedbeef uid:1 BEFORE_FETCH 0 pid:2 uopid:0 'lw 5,3'
jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release/test/core/dcache$ You would have to do |
|
The tests should pass and here is the diff for your reference. Start 123: ICache_test_single_access
143/153 Test #125: ICache_test_random ....................................................... Passed 0.20 sec
Start 147: UNIT_TMPL_test
144/153 Test #123: ICache_test_single_access ................................................ Passed 0.03 sec
Start 124: ICache_test_simple
145/153 Test #147: UNIT_TMPL_test ........................................................... Passed 0.03 sec
Start 150: Prefetcher_test_nextline
146/153 Test #107: L2Cache_test_hit_case .................................................... Passed 0.25 sec
Start 151: Prefetcher_test_stride
147/153 Test #124: ICache_test_simple ....................................................... Passed 0.03 sec
Start 152: Prefetcher_test_edge_cases
148/153 Test #150: Prefetcher_test_nextline ................................................. Passed 0.02 sec
149/153 Test #151: Prefetcher_test_stride ................................................... Passed 0.01 sec
150/153 Test #152: Prefetcher_test_edge_cases ............................................... Passed 0.01 sec
151/153 Test #149: UNIT_TMPL_json_test ...................................................... Passed 0.17 sec
152/153 Test #108: Rename_test_Run_Small .................................................... Passed 0.78 sec
153/153 Test #24: olympia_arch_big_core_1_custom_core ...................................... Passed 48.38 sec
99% tests passed, 1 tests failed out of 153
Total Test time (real) = 1347.03 sec
The following tests FAILED:
126 - Dcache_test_arbitrate (Failed)
Errors while running CTest
Output from these tests are in: /home/jha/workspace/opensource/riscv-perf-model/release/test/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
make[3]: *** [test/CMakeFiles/regress.dir/build.make:70: regress] Error 8
make[2]: *** [CMakeFiles/Makefile2:2319: test/CMakeFiles/regress.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:2326: test/CMakeFiles/regress.dir/rule] Error 2
make: *** [Makefile:878: regress] Error 2
jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release$ git diff
diff --git a/core/prefetcher/Prefetcher.cpp b/core/prefetcher/Prefetcher.cpp
index cb3697e..b22b9ad 100644
--- a/core/prefetcher/Prefetcher.cpp
+++ b/core/prefetcher/Prefetcher.cpp
@@ -59,7 +59,10 @@ namespace olympia
{
// Queue incoming buffer
req_queue_.push(mem_access_info_ptr);
- ev_handle_incoming_req_.schedule(sparta::Clock::Cycle(0));
+ if(!ev_handle_incoming_req_.isScheduled())
+ {
+ ev_handle_incoming_req_.schedule(sparta::Clock::Cycle(0));
+ }
}
//! \brief Override handleMemoryAccess to use credit-based flow control
@@ -70,7 +73,7 @@ namespace olympia
if (getPrefetchEngine()->handleMemoryAccess(access))
{
// Don't send prefetches immediately — schedule credit-based generation
- if (prefetcher_credits_ > 0)
+ if (prefetcher_credits_ > 0 && !ev_gen_prefetch_.isScheduled())
{
ev_gen_prefetch_.schedule(sparta::Clock::Cycle(0));
}
@@ -91,9 +94,9 @@ namespace olympia
handleMemoryAccess(access);
}
- if (!req_queue_.empty())
+ if (!req_queue_.empty() && !ev_handle_incoming_req_.isScheduled())
{
- ev_handle_incoming_req_.schedule(sparta::Clock::Cycle(1));
+ ev_handle_incoming_req_.schedule(sparta::Clock::Cycle(0));
}
return;
}
jha@MAGICIAN:~/workspace/opensource/riscv-perf-model/release$Again, thanks for your work |
|
Thanks for jumping in, Aditya! Pritish, when you "deleted" the files, did you use |
|
Thanks @Ma-gi-cian for that commit, that sorted out the problem and sorry I am having my exams so couldn't give much time to this and @klingaard I had moved those files not by command but by manual work as something is wrong with my repo and if I use git commands it may pollute the whole branch like my last PR. |
|
@rajatbhatia1 please hold off merging this, although the tests are passing, the credit mechanism still has some bugs. The next_line prefetcher is working - it fetches aggressively but it works - ( the ipc in this went down ) but the stride prefetcher is not being run. Diff between normal big_core and big_core with stride prefetcher Report "top.cpu.core0.prefetcher" Report "top.cpu.core0.prefetcher"
cnt_req_rcvd = 376812 cnt_req_rcvd = 376812
cnt_prefetch_sent = 0 cnt_prefetch_sent = 0Maybe it is something to do with the confidence or something will update after fixing it - will also put a diff of the report. Thanks |
|
I have found a couple of issues for the stride prefetcher. The next line works
cnt_req_rcvd = 0
cnt_prefetch_sent = 0This is with the current stride prefetcher. I got around this via making these variables protected in the
Report "top.cpu.core0.prefetcher"
cnt_req_rcvd = 376812
cnt_prefetch_sent = 0 If anyone could look at this and provide with some guidance would be great. Thanks. |
|
@pm-ju can you address the issues that @Ma-gi-cian points out? |
Moved counters to protected section for derived class access. Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
Signed-off-by: pritish <pmdevops29@gmail.com>
|
Hey @Ma-gi-cian I have fixed those issue you were facing. Can you check ? |

Resolves #142
@klingaard @arupc @rajatbhatia1 can you review this one