Files
retroSoC/tests/test_lp_irq.py
T
maksyuki 9a3bf4a6ca feat: enhance GA2D RTL and Test Infrastructure
- Updated resource_controller_tb.sv to include additional checks for IRQ handling and lifecycle states for GA2D resource.
- Modified soc_irq_topology_tb.sv to accommodate 64-bit IRQ vector handling and updated expectations for IRQ routing.
- Introduced test_ga2d.py for directed verification of GA2D Phase 3 APB4 shell functionality.
- Revised test_ga2d_platform.py to reflect changes in GA2D integration and ensure proper IRQ routing.
- Added test_ga2d_register_parity.py to synchronize GA2D RTL and SDK register constants.
- Updated test_lp_irq.py to reflect changes in IRQ allocation and metadata for GA2D.
- Enhanced test_memory_map.py to verify GA2D MMIO region presence in the memory map.
- Adjusted test_publication_software.py to include GA2D in application results.
- Modified test_soc_topology.py to ensure correct topology generation for GA2D, including IRQ and APB bindings.
2026-09-14 09:49:08 +08:00

170 lines
6.3 KiB
Python

"""Phase 1 LP interrupt vector, metadata, and SDK backend tests."""
from __future__ import annotations
import re
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
TOPOLOGY = ROOT / "rtl/mini/integration/soc_topology.json"
GENERATOR = ROOT / "rtl/mini/integration/generate_soc_topology.py"
MEMORY_MAP = ROOT / "rtl/mini/address_map/memory_map.json"
def generate(output_dir: Path, *, external_irq_count: int = 62) -> None:
subprocess.run(
[
sys.executable,
str(GENERATOR),
"--map",
str(TOPOLOGY),
"--memory-map",
str(MEMORY_MAP),
"--output-dir",
str(output_dir),
"--external-irq-count",
str(external_irq_count),
],
check=True,
)
def test_phase1_generates_64bit_vector_and_sdk_metadata(tmp_path: Path) -> None:
generate(tmp_path)
irq_config = (tmp_path / "rtl/soc_irq_config.svh").read_text(encoding="utf-8")
irq_wiring = (tmp_path / "rtl/soc_irq_wiring.svh").read_text(encoding="utf-8")
irq_sva = (tmp_path / "rtl/soc_irq_sva.svh").read_text(encoding="utf-8")
metadata = (
tmp_path / "include/retrosoc/generated/irq_metadata.h"
).read_text(encoding="utf-8")
assert "`define SOC_IRQ_VECTOR_WIDTH 64" in irq_config
assert "`define SOC_USER_IRQ_MASK 64'h00000000004EFBFC" in irq_config
assert "s_irq[31] = s_apb4_periph_irq[23];" in irq_wiring
assert "s_irq[32] = s_apb4_periph_irq[24];" in irq_wiring
assert "irq_i[32] == apb4_periph_irq_i[24]" in irq_sva
assert "irq_i[63] == 1'b0" in irq_sva
assert "RS_SOC_IRQ_VECTOR_WIDTH UINT32_C(64)" in metadata
assert "RS_SOC_EXTERNAL_IRQ_COUNT UINT32_C(62)" in metadata
assert "RS_SOC_ALLOCATED_IRQ_COUNT UINT32_C(31)" in metadata
assert "RS_SOC_EXT_IRQ_APU UINT32_C(29)" in metadata
assert "RS_SOC_IRQ_GA2D UINT32_C(32)" in metadata
assert "RS_SOC_EXT_IRQ_GA2D UINT32_C(30)" in metadata
def test_phase1_supports_32bit_compatibility_metadata(tmp_path: Path) -> None:
generate(tmp_path, external_irq_count=30)
metadata = (
tmp_path / "include/retrosoc/generated/irq_metadata.h"
).read_text(encoding="utf-8")
assert "RS_SOC_IRQ_VECTOR_WIDTH UINT32_C(64)" in metadata
assert "RS_SOC_EXTERNAL_IRQ_COUNT UINT32_C(30)" in metadata
def test_csr_disabled_external_irq_api_is_a_polling_stub(tmp_path: Path) -> None:
compiler = shutil.which("cc")
if compiler is None:
return
source = tmp_path / "irq_nocsr_test.c"
source.write_text(
"""
#include <retrosoc/core/irq.h>
static void handler(uintptr_t mcause, uintptr_t stack_pointer) {
(void)mcause;
(void)stack_pointer;
}
int main(void) {
return (rs_irq_register_external(0U, handler) == RS_ENOTSUP &&
rs_irq_enable_external(61U, handler) == RS_ENOTSUP &&
rs_irq_disable_external(61U) == RS_ENOTSUP &&
rs_irq_set_external_priority(61U, 3U) == RS_ENOTSUP) ? 0 : 1;
}
""",
encoding="utf-8",
)
executable = tmp_path / "irq_nocsr_test"
subprocess.run(
[
compiler,
"-std=gnu11",
"-Wall",
"-Wextra",
"-I",
str(ROOT / "crt/include"),
str(ROOT / "crt/src/core/irq_nocsr.c"),
str(source),
"-o",
str(executable),
],
check=True,
)
subprocess.run([str(executable)], check=True)
def test_phase1_wrapper_and_backend_contracts() -> None:
wrapper = (ROOT / "rtl/mini/top/core_wrapper.sv").read_text(encoding="utf-8")
management = (ROOT / "rtl/mini/top/mgmt_core_wrapper.sv").read_text(encoding="utf-8")
top = (ROOT / "rtl/mini/top/retrosoc.sv").read_text(encoding="utf-8")
handler = (ROOT / "crt/src/core/system_irq_handler.c").read_text(encoding="utf-8")
csr = (ROOT / "crt/include/retrosoc/arch/riscv/system_csr.h").read_text(encoding="utf-8")
firmware = (ROOT / "app/apps/ci_smoke/main.c").read_text(encoding="utf-8")
assert "parameter int ExternalIrqCount = 30" in wrapper
assert "parameter int ExternalIrqCount = 30" in management
assert ".NUM_IRQS (ExternalIrqCount)" in management
assert ".IRQ_INPUT_BYPASS ({ExternalIrqCount{1'b0}})" in management
assert "localparam int ManagementExternalIrqCount = `SOC_IRQ_VECTOR_WIDTH - 2" in top
assert ".ExternalIrqCount(ManagementExternalIrqCount)" in top
assert "assign s_management_irq = s_irq[ManagementExternalIrqCount+1:0]" in top
assert ".irq_i (s_management_irq)" in top
assert "RS_EXTERNAL_IRQ_COUNT RS_SOC_EXTERNAL_IRQ_COUNT" in handler
assert "rs_irq_dispatch_external(mcause, stack_pointer)" in handler
assert "CSR_HAZARD3_MEIEA 0xbe0" in csr
assert "CSR_HAZARD3_MEINEXT 0xbe4" in csr
assert "CSR_HAZARD3_MEICONTEXT 0xbe5" in csr
assert "static const uint32_t tested_ordinals[]" in firmware
assert re.search(r"29U,\s*RS_SOC_EXT_IRQ_GA2D,\s*31U", firmware) is not None
assert "rs_irq_register_external(62U" in firmware
assert "rs_irq_set_external_priority(29U, UINT8_C(0))" in firmware
assert "rs_irq_set_external_priority(RS_SOC_EXT_IRQ_GA2D, UINT8_C(1))" in firmware
assert "rs_irq_set_external_priority(31U, UINT8_C(2))" in firmware
assert "rs_irq_set_external_priority(32U, UINT8_C(3))" in firmware
assert "rs_irq_set_external_priority(15U, UINT8_C(3))" in firmware
assert "rs_irq_set_external_priority(15U, UINT8_C(4))" in firmware
assert "rs_ci_smoke_timer_irq_handler" in firmware
assert "rs_ci_smoke_software_irq_handler" in firmware
def test_phase1_generated_irq_routing_simulates(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
generate(tmp_path / "topology")
simulation = tmp_path / "soc_irq_topology_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-I",
str(tmp_path / "topology/rtl"),
"-s",
"soc_irq_topology_tb",
"-o",
str(simulation),
str(ROOT / "tests/rtl/soc_irq_topology_tb.sv"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], check=True, capture_output=True, text=True)
assert "SoC topology IRQ routing test passed" in result.stdout