Code of Conduct
CVA6 commit affected
88e810c
Bug Description
CBO.INVAL/CLEAN/FLUSH are decoded as fu=STORE (decoder.sv:474) and go through the store buffer, where the entry stays valid until data_rvalid (store_buffer.sv:182-191). The load/store hazard check compares addresses at 8-byte granularity (page_offset[11:3]) , but a CBO operates on a whole cache block. A younger load to the same block but a different 8-byte word is therefore not seen as a conflict, and is issued before the CBO completes.
Relevant spec:
For cache-block management instruction, the resulting invalidate, clean, and flush operations behave as stores in the PPO rules subject to one additional overlapping address rule: a is an invalidate, clean, or flush, b is a load, and a and b access overlapping memory addresses. The above rule ensures that a subsequent load in program order never appears in the global memory order before a preceding invalidate, clean, or flush operation to an overlapping address.
The access size for CMO instructions is equal to the size of the cache block.
Buggy Code
The hazard check compares [11:3] only, in all three places, and does not distinguish cbo_op:
for (int unsigned i = 0; i < DEPTH_COMMIT; i++) begin
// Check if the page offset matches and whether the entry is valid, for the commit queue
if ((page_offset_i[11:3] == commit_queue_q[i].address[11:3]) && commit_queue_q[i].valid) begin
page_offset_matches_o = 1'b1;
break;
end
end
The load unit issues the request as soon as there is no match:
if (!page_offset_matches_i) begin
// make a load request to memory
req_port_o.data_req = 1'b1;
...
end else begin
// wait for the store buffer to train and the page offset to not match anymore
state_d = WAIT_PAGE_OFFSET;
end
For cbo.inval 0(a0) with a0=0x1000, the store buffer holds 0x1000 (store_unit.sv:349 passes paddr_i through, no block alignment), so a following ld 8(a0) has [11:3]=1 while the CBO holds [11:3]=0; they differ, so the load is issued while the CBO is still pending. ld 0(a0) does match and takes WAIT_PAGE_OFFSET, so the mechanism itself works, the problem is the granularity is too fine for CBOs.
Prime the block into L1, then cbo.inval 0(a0) immediately followed by ld t1, 8(a0); the control case ld t1, 0(a0) should stall in WAIT_PAGE_OFFSET. I am debugging a directed test for the Verilator model and will attach an FST showing whether the load's data_rvalid arrives while the CBO entry is still valid in the commit queue.
Code of Conduct
CVA6 commit affected
88e810c
Bug Description
CBO.INVAL/CLEAN/FLUSHare decoded asfu=STORE(decoder.sv:474) and go through the store buffer, where the entry stays valid untildata_rvalid(store_buffer.sv:182-191). The load/store hazard check compares addresses at 8-byte granularity (page_offset[11:3]) , but a CBO operates on a whole cache block. A younger load to the same block but a different 8-byte word is therefore not seen as a conflict, and is issued before the CBO completes.Relevant spec:
Buggy Code
The hazard check compares
[11:3]only, in all three places, and does not distinguishcbo_op:The load unit issues the request as soon as there is no match:
For
cbo.inval 0(a0)witha0=0x1000, the store buffer holds0x1000(store_unit.sv:349passespaddr_ithrough, no block alignment), so a following ld 8(a0) has [11:3]=1 while the CBO holds [11:3]=0; they differ, so the load is issued while the CBO is still pending.ld 0(a0)does match and takesWAIT_PAGE_OFFSET, so the mechanism itself works, the problem is the granularity is too fine for CBOs.Prime the block into L1, then
cbo.inval 0(a0)immediately followed byld t1, 8(a0); the control caseld t1, 0(a0)should stall inWAIT_PAGE_OFFSET. I am debugging a directed test for the Verilator model and will attach an FST showing whether the load'sdata_rvalidarrives while the CBO entry is still valid in the commit queue.