Skip to content

Bank PCC to sustain issue through capability jumps#87

Draft
jonwoodruff wants to merge 11 commits into
zcherifrom
jdw57-double-pcc
Draft

Bank PCC to sustain issue through capability jumps#87
jonwoodruff wants to merge 11 commits into
zcherifrom
jdw57-double-pcc

Conversation

@jonwoodruff

Copy link
Copy Markdown
Collaborator

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.

@jonwoodruff jonwoodruff force-pushed the jdw57-double-pcc branch 3 times, most recently from 4e2ed62 to 1ac4195 Compare June 5, 2026 10:36
Comment thread core/branch_unit.sv Outdated
Comment thread core/branch_unit.sv
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)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we do this? Do we still need to mispredict when jumping to int mode with double-pcc?

Comment thread core/branch_unit.sv Outdated
Comment thread core/cva6.sv Outdated
Comment thread core/cva6.sv
Comment thread core/cva6.sv Outdated
.amo_resp_i (amo_resp),
.pcc_i (commit_pcc),
.pc_o (pc_commit),
.pc_o (),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this one is causing trouble. Need to investigate any changes in priority due to the move.

joncapltd and others added 10 commits June 23, 2026 17:12
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
@PRugg-Cap

Copy link
Copy Markdown
Collaborator

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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants