Skip to content

Fix Zcmt JVT index calculation - #3451

Open
124107157-KV wants to merge 2 commits into
openhwgroup:masterfrom
124107157-KV:fix/3442-zcmt-jvt-index
Open

Fix Zcmt JVT index calculation#3451
124107157-KV wants to merge 2 commits into
openhwgroup:masterfrom
124107157-KV:fix/3442-zcmt-jvt-index

Conversation

@124107157-KV

@124107157-KV 124107157-KV commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
  • I have searched for similar pull requests
  • 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.

Why this PR is needed

This PR fixes the Zcmt JVT address calculation reported in #3442.

The Zcmt table-jump index is encoded in instruction bits [9:2], providing an 8-bit index for 256 JVT entries. For RV32, the JVT entry address is calculated as:

table_address = jvt.base + (index << 2)

The current implementation uses only instr_i[7:2]:

table_address = {jvt_i.base, 6'b000000}
              + {24'h0, instr_i[7:2], 2'b00};

This retains only six index bits. Therefore, indices 64–255 lose their upper two bits and alias entries 0–63.

This PR changes the address calculation to use the complete 8-bit index:

table_address = {jvt_i.base, 6'b000000}
              + {22'h0, instr_i[9:2], 2'b00};

This is also consistent with the existing Zcmt instruction classification, which already uses instr_i[9:2].

For a JVT base of 0x80100000:

Index Expected offset Correct address Previous address
0 0x000 0x80100000 0x80100000
63 0x0fc 0x801000fc 0x801000fc
64 0x100 0x80100100 0x80100000
127 0x1fc 0x801001fc 0x801000fc
128 0x200 0x80100200 0x80100000
255 0x3fc 0x801003fc 0x801000fc

Index 64 is the first value that exposes the truncation bug. Its correct offset is 0x100, while the previous six-bit calculation wraps the index to zero and produces offset 0x000.

Changes

This PR:

  • updates core/zcmt_decoder.sv to use instr_i[9:2] for the JVT address calculation;
  • adds a focused zcmt_decoder Verilator regression;
  • checks JVT indices 0, 31, 32, 63, 64, 127, 128, and 255;
  • adds a standalone Makefile for the focused decoder test;
  • invokes the regression from verif/regress/issue-tests.sh;
  • propagates a failing regression result before the remaining issue-test flow continues.

The values below 64 verify that the existing behavior before the truncation boundary remains unchanged.

Index 64 verifies the first affected boundary, while 127, 128, and 255 exercise the upper portion of the complete 8-bit index range.

Regression results

Before the fix

The regression passes through index 63 and fails at index 64:

index=0 encoding=a002 actual=80100000 expected=80100000
index=31 encoding=a07e actual=8010007c expected=8010007c
index=32 encoding=a082 actual=80100080 expected=80100080
index=63 encoding=a0fe actual=801000fc expected=801000fc
index=64 encoding=a102 actual=80100000 expected=80100100

Assertion failed:
index 64: wrong table address: actual=80100000 expected=80100100

The pre-fix regression exits with a non-zero status.

After the fix

The same regression passes across the tested 8-bit index range:

index=0 encoding=a002 actual=80100000 expected=80100000
index=31 encoding=a07e actual=8010007c expected=8010007c
index=32 encoding=a082 actual=80100080 expected=80100080
index=63 encoding=a0fe actual=801000fc expected=801000fc
index=64 encoding=a102 actual=80100100 expected=80100100
index=127 encoding=a1fe actual=801001fc expected=801001fc
index=128 encoding=a202 actual=80100200 expected=80100200
index=255 encoding=a3fe actual=801003fc expected=801003fc

PASS: complete eight-bit Zcmt JVT index is used

Validation

The final branch was validated with:

  • Verilator 5.008;
  • focused tb_zcmt_decoder regression;
  • fail-before/pass-after verification using the same permanent regression;
  • verible-verilog-format --verify core/zcmt_decoder.sv;
  • verible-verilog-format --verify corev_apu/tb/tb_zcmt_decoder/hdl/tb.sv;
  • git diff upstream/master...HEAD --check;
  • rebase verification against the current upstream/master.

The working tree is clean after validation.

Full repository CI will run on the pull request.

Scope and limitations

This PR intentionally addresses only the JVT index truncation reported in #3442.

It changes the JVT table-entry address calculation and adds focused regression coverage for that calculation.

It does not modify unrelated Zcmt control-flow behavior, cache-response handling, or the TABLE_JUMP state machine.

No known limitation is introduced by the RTL change itself.

Fixes #3442

@cainria cainria left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the fix!

Should we add a new testbench or is there a way to trigger this issue with assembly code?

Comment thread corev_apu/tb/tb_zcmt_decoder/hdl/tb.sv Outdated
@124107157-KV

Copy link
Copy Markdown
Contributor Author

Thanks for the fix!

Should we add a new testbench or is there a way to trigger this issue with assembly code?

Thanks! Yes, it should be possible to trigger this with an assembly test. I found the existing Zcmt assembly tests under verif/tests/custom/zcmt/, including cm_jalt_long.S.

I’ll check whether I can adapt one of those to use index 64, which is the first value affected by this bug, and make the test self-checking so that an incorrect jump is detected. If that works cleanly, I can use the assembly regression instead of adding a separate decoder testbench.

@124107157-KV
124107157-KV force-pushed the fix/3442-zcmt-jvt-index branch from e6a8a01 to 939e2b5 Compare August 12, 2026 14:28
Use the complete eight-bit cm.jt/cm.jalt table index when
calculating the JVT entry address.

Add a focused zcmt_decoder regression covering the index-64
boundary and upper table indices.

Fixes openhwgroup#3442
Replace the standalone zcmt_decoder testbench with a directed
assembly regression using cm.jalt index 64.

Register the test in the issue testlist and run it with RVZCMT
enabled so the original six-bit calculation fails while the fixed
eight-bit calculation passes.
@124107157-KV
124107157-KV force-pushed the fix/3442-zcmt-jvt-index branch from 939e2b5 to de119c6 Compare August 13, 2026 10:02
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.

[BUG] JVT address calculation truncates the 8-bit table index

2 participants