Skip to content

Commit 81b7b02

Browse files
committed
cpu/cv32e41p: Keep standard variant on RV32IM
Issue #1364 reports litex_sim hanging with CV32E41P firmware built for RV32IMC. The analyzed failure is not in the LiteX wrapper: the archived CV32E41P RTL computes is_compressed_o in cv32e41p_merged_decoder.sv, but does not declare it as a decoder output port or connect it in cv32e41p_id_stage.sv. With permissive SystemVerilog handling, id_stage_i.is_compressed becomes an implicit undriven net. The ID-stage IMMB_PCINCR path can then use pc+4 instead of pc+2 for compressed instructions; c.jal writes the wrong return address, skips the caller return-address restore, and loops. A minimal CPU RTL fix was validated separately by declaring the decoder output, declaring logic is_compressed in the ID stage, and wiring .is_compressed_o(is_compressed). Since the CV32E41P repository is archived and the pythondata package tracks that RTL, keep LiteX on the known-good standard RV32IM variant and do not advertise an imc variant. Tests: python3 -m pytest -q test/test_cpu.py
1 parent 61bce27 commit 81b7b02

3 files changed

Lines changed: 35 additions & 2 deletions

File tree

litex/soc/cores/cpu/cv32e41p/core.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
# | |||/--- Single-Precision Floating-Point
3232
# | ||||/-- Double-Precision Floating-Point
3333
# i macfd
34-
"standard": "-march=rv32i2p0_mc -mabi=ilp32 ",
34+
# Keep software builds on RV32IM: the archived CV32E41P RTL has a broken
35+
# compressed-instruction flag path, which can corrupt c.jal link addresses.
36+
"standard": "-march=rv32i2p0_m -mabi=ilp32 ",
3537
}
3638

3739
# OBI / APB / Trace Layouts ------------------------------------------------------------------------

test/test_cpu.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#
2+
# This file is part of LiteX.
3+
#
4+
# Copyright (c) 2026 Florent Kermarrec <florent@enjoy-digital.fr>
5+
# SPDX-License-Identifier: BSD-2-Clause
6+
7+
import unittest
8+
9+
from litex.soc.cores.cpu.cv32e41p.core import CPU_VARIANTS, CV32E41P
10+
11+
12+
def _cv32e41p_gcc_flags(variant):
13+
cpu = CV32E41P.__new__(CV32E41P)
14+
cpu.variant = variant
15+
return cpu.gcc_flags
16+
17+
18+
class TestCV32E41P(unittest.TestCase):
19+
def test_only_standard_variant_is_advertised(self):
20+
self.assertEqual(CPU_VARIANTS, ["standard"])
21+
22+
def test_standard_variant_does_not_emit_compressed_instructions(self):
23+
flags = _cv32e41p_gcc_flags("standard")
24+
25+
self.assertIn("-march=rv32i2p0_m", flags)
26+
self.assertNotIn("-march=rv32i2p0_mc", flags)
27+
self.assertIn("-D__cv32e41p__", flags)
28+
29+
30+
if __name__ == "__main__":
31+
unittest.main()

test/test_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def test_linux_on_litex_rocket_nexys_video_generation(tmp_path):
262262
"blackparrot", # (riscv / softcore) -> Broken install?
263263
"cortex_m1", # (arm / softcore) -> Proprietary code.
264264
"cortex_m3", # (arm / softcore) -> Proprieraty code.
265-
"cv32e41p", # (riscv / softcore) -> Broken?
265+
"cv32e41p", # (riscv / softcore) -> Needs to be tested.
266266
"cva5", # (riscv / softcore) -> Needs to be tested.
267267
"cva6", # (riscv / softcore) -> Needs to be tested.
268268
"eos_s3", # (arm / hardcore) -> Hardcore.

0 commit comments

Comments
 (0)