Skip to content

[BUG] cbo.inval does not stall a following load to the same cache block #3432

Description

@oChunCai

Code of Conduct

  • I have searched the existing bug issues.
  • I am a human engaging in an interpersonal interaction. During this interaction, my words are my own and are not generated. If relevant, I provide links to my sources.

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Component:RTLFor issues in the RTL (e.g. for files in the rtl directory)Status:In ProgressWork on this issue has started, but is not complete.Type:BugFor bugs in the RTL, Documentation, Verification environment or Tool and Build system

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions