[BUG] CV-X-IF result transaction is ignored for offloaded instruction not writing back to the RF
Bug Description
While testing CV32E20 with a coprocessor supporting multiple in-flight instructions, I noticed that the CV-X-IF Result transaction is ignore in those cases where the offloaded instruction does not write back a value to the core's register file (i.e., x_issue_resp_i.writeback not asserted). For such instructions, the x_issue_resp_i.writeback signal is used to allow the processor to proceed to the next instruction at issue time (cve2_id_stage.sv#L292).
While this allows the core to execute new instructions in parallel to the offloaded one(s), it has some undesired side effects, detailed in the following sections.
1. Multiple offloaded in-flight instructions with the same ID
The mechanism described above allows two coprocessor instructions to be in-flight inside the coprocessor at the same time, provided that:
- The first instruction does not write back to the register file (
x_issue_resp_i.writeback == 1'b0). - The second instruction is successfully offloaded (
x_issue_ready_i && x_issue_resp_i.accept) before the first one has completed execution (x_result_valid_i).
However, the two in-flight instructions are tagged with the same ID (0), since the x_issue_req_o.id is hardwired to '0 in cve2_id_stage.sv#L297. This violates the CV-X-IF "Identification" specs:
The id values for in-flight offloaded instructions are required to be unique.
and:
An id ends being in-flight when one of the following scenarios apply:
the corresponding issue request transaction is retracted.
the corresponding issue request transaction is not accepted and the corresponding commit handshake has been performed.
the corresponding result transaction has been performed.
Because the second instruction is offloaded before the Result transaction from the first instruction is received, it should be tagged with a different, unique ID (e.g., 1). This is usually easy to workaround in coprocessors since CVE2 always sends the commit transaction for the instruction being offloaded together with the issue transaction. However, this is suboptimal in those cases where the coprocessor keeps track of in-flight instructions with a scoreboard directly indexed by the instruction ID from the issue and commit interfaces.
2. The core does not always wait for coprocessor instructions completion
Not stalling the core when offloading instructions with no writeback events causes the result transaction from such instructions to be ignored, allowing the core to proceed indefinitely. This might lead to unwanted behaviour. An example is that a wfi instruction issued after a coprocessor instruction with no writeback value might cause the core to enter sleep before the coprocessor completes the execution of all the offloaded instructions. Another side consequence is that exceptions or interrupts may be processed before before the coprocessor (and potentially connected modules) is in a clean state.
Proposed Solution
A possible lightweight solution was drafted with the help of @davideschiavone, and consists in the following additions to the core:
- An
[X_ID_WIDTH-1:0]counter to increment the ID every time an instruction is offloaded. The ID is propagated in thex_issue_req_oandx_commit_ointerfaces at issue time. - An ID-indexed single-bit scoreboard to track in-flight offloaded instructions. The ID-th scoreboard entry is set upon successful instruction offloading (issue interface) and reset when the corresponding result transaction is used. Exceptions, interrupts,
wfiinstructions and similar events are allowed to proceed only once the scoreboard is empty.
Working on this solution is currently a low-priority for us, but we plan to open a PR to solve the issue as soon as we have the time.