Bank PCC to sustain issue through capability jumps#87
Conversation
4e2ed62 to
1ac4195
Compare
| resolved_branch_o.is_pcc_change = 1'b1; | ||
| end | ||
| // If jumping into intmode, we must have been in capmode, so always mispredict | ||
| if (cva6_cheri_pkg::get_cap_reg_flags(target_address) == 1'b1) |
There was a problem hiding this comment.
Why do we do this? Do we still need to mispredict when jumping to int mode with double-pcc?
| .amo_resp_i (amo_resp), | ||
| .pcc_i (commit_pcc), | ||
| .pc_o (pc_commit), | ||
| .pc_o (), |
There was a problem hiding this comment.
What's this about? I guess upstream has a pc_o, so we're just leaving it, but we no longer use it? I guess upstream just turns the pc of the first instruction around, so you can read it from the outside? We should check that there's a good reason to change this structure.
| output logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack_o, | ||
| // Int mode flag in PCC register - ID_STAGE | ||
| output logic int_mode_o, | ||
| // PCC exception - Execute |
There was a problem hiding this comment.
Moving this one is causing trouble. Need to investigate any changes in priority due to the move.
1ac4195 to
2f9f6f9
Compare
This should improve IPC, as the pipeline can continue fetching after a PCC-changing jump. It may also improve timing, as we do not need to detect changes to PCC as aggressively. This commit was squashed from the following commits: Move to a vector of PCCs everywhere that matters. This one uses the 2nd PCC as the same "next_pcc" buffer that we used to have, and everyone reads [0], so it passes TestRIG, working the same way as it used to. Some progress toward propagating both PCCs throught the pipeline. This one fails testRig on preserving the mode bit on exception. Remove scheduling restriction for issuing instructions in the slot after a CJALR, as only AUIPCC and CJALR can observe the effect of a CJALR on the bounds of PCC, and they must also be scheduled in the Branch/CLU pipe, so they naturally get serialised. Remove PCC change check in execute. Leave wire reporting a change for now, unconditionally set on any CJALR. Always unseal branch target. Update PCC more quickly so that a following branch+link will reflect the new PCC. Reflect the int_mode in the pc_o to execute. Use upstream way of doing this. We had part of upstream, but it was just "dead code" in our implementation. Use the next version of PCC for PCC operand that will be latched. A perhaps-not-quite-right mechansim that allows multiple branches outstanding while blocking when a third one turns up. This one only resets to no branches outstanding when the backend is empty, which is overly conservative; should reset when the committed instruction has the generation 1. Handle PCC flow control more correctly. Stall when pcc_gen_q is 1 and we want to issue another CJALR until pcc_gen_q is 0 again. Don't stall for now on multiple outstanding writes, as there is some bug that leads to lockup. More closely following intended state machine of resetting to pcc_gen 0 at the ealiest appropriate moment, and also doing flow control that guarantees forward progress. Fix logic for resetting the PC to only every happen if pcc_gen_q is true. Improve the state machine. Thinking about the previous scheme revealed corner cases. Simplify pc_o assignment, getting rid of automitic use, which is the only use of automatic in the file. Try not changing the generation on exceptions or mispredictions, since the pipeline is flushing anyway. Block the second port from issuing when the first port has a CJAL to fit the limitation that we currently must insert instructions from the same generation into the scoreboard in a single cycle because we only have a single generation bit into the scoreboard. Pipe independent pcc generations through to the scoreboard so that instructions from different generations can issue together. Work in progress refactoring PCC bounds check to the writeback stage. Feed correct PCC to execute. Make scheduling for pcc_changing very conservative experimentally. Also, change from special pcc_is_changing signal to just using control-flow type field to decide to change PCC. A more robust sytem for tracking the pcc generation. There are still some corner cases that need to be worked out that are found by the caprandom TestRIG generator. Make jump conditions for swapping PCC_GEN consistent. Write new pcc on return as well. Reset pcc_gen on a mispredict. Fix pcc_gen flush signal not being reset (and remove unnecessary signal for pcc_gen_flush value.) Also, use latest value of pcc for operand of auipcc. Simply use the mispredict signal, as it needs to reset on branch as well. Don't clear pcc_changing before it has changed! Only guard CJALRs for PCC updates. Only indicate a branch if it is not throwing an exception. Experimentally remove the pcc checks. Mark is_mispredict false if branch throws an exception is_mispredict is read in various places without conditioning on the valid of resolved_branch_o. This fixes several counterexamples from a (very) deep TestRIG run
issue_ack is independent per issue way, and issue_ack_o then ands each way with the previous way. Use issue_ack_o for making pcc_gen decisions instead.
I'm not quite sure what difference these would make, but we haven't used them elsewhere
Every branch can safely write to PCC, on the basis that either: 1) It is a PCC-changing CJALR, so needs to update PCC for the immediately following instructions, and is the first one writing to the new generation 2) It is a non-PCC changing branch or JAL/JALR, so will not be changing the PCC metadata, making the update harmless
2f9f6f9 to
ce4dd01
Compare
|
Note that while this now works, it fails timing by an uncomfortable margin. We've been discussing moving the PCC check into execute, which should break the path through commit that's critical currently. |
This improvement addresses issue #58 .
There is a certain amount of refactoring here as well to reduce unnecessary wiring changes with respect to the baseline.