From 587ec912f0df19908f53b9c2178a36446049c22f Mon Sep 17 00:00:00 2001 From: AnastasiyaChernikova Date: Thu, 23 Apr 2026 14:37:21 +0000 Subject: [PATCH] [dv] Add RV32ZC handling to ISA strings Use the RV32ZC configuration parameter when constructing the ISA string passed to the cosimulator. This lets DV runs distinguish between Zca, ZcaZcb, ZcaZcmp and ZcaZcbZcmp configurations. --- dv/uvm/core_ibex/scripts/ibex_cmd.py | 25 ++++++++++++++++--- dv/uvm/core_ibex/tb/core_ibex_tb_top.sv | 7 ++++++ dv/uvm/core_ibex/tests/core_ibex_base_test.sv | 22 ++++++++++++++-- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/dv/uvm/core_ibex/scripts/ibex_cmd.py b/dv/uvm/core_ibex/scripts/ibex_cmd.py index 0d8c5346e2..c4ec6f25e7 100644 --- a/dv/uvm/core_ibex/scripts/ibex_cmd.py +++ b/dv/uvm/core_ibex/scripts/ibex_cmd.py @@ -91,13 +91,27 @@ def get_config(cfg_name: str) -> Config: return parse_config(cfg_name, yaml_path) +def _rv32zc_isa_parts(rv32zc: str) -> list[str]: + mapping = { + 'ibex_pkg::RV32Zca': ['zicsr', 'zifencei', 'zca'], + 'ibex_pkg::RV32ZcaZcb': ['zicsr', 'zifencei', 'zca', 'zcb'], + 'ibex_pkg::RV32ZcaZcmp': ['zicsr', 'zifencei', 'zca', 'zcmp'], + 'ibex_pkg::RV32ZcaZcbZcmp': ['zicsr', 'zifencei', 'zca', 'zcb', 'zcmp'], + } + part = mapping.get(rv32zc) + if part is None: + raise ValueError(f'Unknown RV32ZC value ({rv32zc}) in config YAML') + return part + + def get_isas_for_config(cfg: Config) -> Tuple[str, str]: """Get ISA and ISS_ISA keys for the given Ibex config.""" # NOTE: This logic should match the code in the get_isa_string() function # in core_ibex/tests/core_ibex_base_test.sv: keep them in sync! has_multiplier = cfg.rv32m != 'ibex_pkg::RV32MNone' - base_isa = 'rv32{}{}c'.format('e' if cfg.rv32e else 'i', - 'm' if has_multiplier else '') + + base_isa = 'rv32{}{}'.format('e' if cfg.rv32e else 'i', + 'm' if has_multiplier else '') bitmanip_mapping = { 'ibex_pkg::RV32BNone': [], @@ -113,9 +127,12 @@ def get_isas_for_config(cfg: Config) -> Tuple[str, str]: raise ValueError(f'Unknown RV32B value ({cfg.rv32b}) in config YAML') has_bitmanip = cfg.rv32b != 'ibex_pkg::RV32BNone' - toolchain_isa = base_isa + ('b' if has_bitmanip else '') + # Keep the toolchain ISA using the legacy C extension spelling, but build + # the ISS ISA from the explicit RV32ZC subset below. + toolchain_isa = base_isa + 'c' + ('b' if has_bitmanip else '') + iss_isa = '_'.join([base_isa] + _rv32zc_isa_parts(cfg.rv32zc) + bitmanip_isa) - return (toolchain_isa, '_'.join([base_isa] + bitmanip_isa)) + return (toolchain_isa, iss_isa) _TestEntry = Dict[str, object] diff --git a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv index a2658d1239..0e13f4ab7e 100644 --- a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv +++ b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv @@ -52,6 +52,10 @@ module core_ibex_tb_top; `define IBEX_CFG_RegFile ibex_pkg::RegFileFF `endif + `ifndef IBEX_CFG_RV32ZC + `define IBEX_CFG_RV32ZC ibex_pkg::RV32ZcaZcbZcmp + `endif + // Ibex Parameters parameter bit PMPEnable = 1'b0; parameter int unsigned PMPGranularity = 0; @@ -62,6 +66,7 @@ module core_ibex_tb_top; parameter ibex_pkg::rv32m_e RV32M = `IBEX_CFG_RV32M; parameter ibex_pkg::rv32b_e RV32B = `IBEX_CFG_RV32B; parameter ibex_pkg::regfile_e RegFile = `IBEX_CFG_RegFile; + parameter ibex_pkg::rv32zc_e RV32ZC = `IBEX_CFG_RV32ZC; parameter bit BranchTargetALU = 1'b0; parameter bit WritebackStage = 1'b0; parameter bit ICache = 1'b0; @@ -103,6 +108,7 @@ module core_ibex_tb_top; .RV32E (RV32E ), .RV32M (RV32M ), .RV32B (RV32B ), + .RV32ZC (RV32ZC ), .RegFile (RegFile ), .BranchTargetALU (BranchTargetALU ), .WritebackStage (WritebackStage ), @@ -370,6 +376,7 @@ module core_ibex_tb_top; uvm_config_db#(bit)::set(null, "*", "RV32E", RV32E); uvm_config_db#(ibex_pkg::rv32m_e)::set(null, "*", "RV32M", RV32M); uvm_config_db#(ibex_pkg::rv32b_e)::set(null, "*", "RV32B", RV32B); + uvm_config_db#(ibex_pkg::rv32zc_e)::set(null, "*", "RV32ZC", RV32ZC); if (PMPEnable) begin uvm_config_db#(bit [31:0])::set(null, "*", "PMPNumRegions", PMPNumRegions); diff --git a/dv/uvm/core_ibex/tests/core_ibex_base_test.sv b/dv/uvm/core_ibex/tests/core_ibex_base_test.sv index 47847ad671..7782961a1a 100644 --- a/dv/uvm/core_ibex/tests/core_ibex_base_test.sv +++ b/dv/uvm/core_ibex/tests/core_ibex_base_test.sv @@ -47,12 +47,26 @@ class core_ibex_base_test extends uvm_test; irq_collected_port = new("irq_collected_port_test", this); endfunction + function automatic string rv32zc_isa_suffix(rv32zc_e rv32zc); + case (rv32zc) + RV32Zca: return "_zicsr_zifencei_zca"; + RV32ZcaZcb: return "_zicsr_zifencei_zca_zcb"; + RV32ZcaZcmp: return "_zicsr_zifencei_zca_zcmp"; + RV32ZcaZcbZcmp: return "_zicsr_zifencei_zca_zcb_zcmp"; + default: begin + `uvm_fatal(`gfn, $sformatf("Unknown RV32ZC value: %0d", rv32zc)) + return ""; + end + endcase + endfunction + // NOTE: This logic should match the code in the get_isas_for_config() function in - // core_ibex/scripts/scripts_lib.py: keep them in sync! + // core_ibex/scripts/ibex_cmd.py: keep them in sync! function string get_isa_string(); bit RV32E; rv32m_e RV32M; rv32b_e RV32B; + rv32zc_e RV32ZC; string isa; if (!uvm_config_db#(bit)::get(null, "", "RV32E", RV32E)) begin @@ -64,12 +78,16 @@ class core_ibex_base_test extends uvm_test; if (!uvm_config_db#(rv32b_e)::get(null, "", "RV32B", RV32B)) begin `uvm_fatal(`gfn, "Cannot get RV32B parameter") end + if (!uvm_config_db#(rv32zc_e)::get(null, "", "RV32ZC", RV32ZC)) begin + `uvm_fatal(`gfn, "Cannot get RV32ZC parameter") + end // Construct the right ISA string for the cosimulator by looking at top-level testbench // parameters. isa = {"rv32", RV32E ? "e" : "i"}; if (RV32M != RV32MNone) isa = {isa, "m"}; - isa = {isa, "c"}; + isa = {isa, rv32zc_isa_suffix(RV32ZC)}; + case (RV32B) RV32BNone: ;