blob: 72097f946ebe1b85f7d8eb3660ec679786aa8b7c [file] [log] [blame]
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//----------------------------------------------------------------------------
// Package: kelvin_cosim_checker_pkg
// Description: Package for the UVM component that manages co-simulation.
//----------------------------------------------------------------------------
package kelvin_cosim_checker_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
//----------------------------------------------------------------------------
// Class: kelvin_cosim_checker
// Description: Manages the MPACT simulator via DPI-C. It receives retired
// instruction info from the DUT (via RVVI) and sends that
// same instruction to the MPACT simulator to execute, enabling
// a trace-and-execute co-simulation flow.
//----------------------------------------------------------------------------
class kelvin_cosim_checker extends uvm_component;
`uvm_component_utils(kelvin_cosim_checker)
// Use fully parameterized virtual interface type
virtual rvviTrace #(
.ILEN(32), .XLEN(32), .FLEN(32), .VLEN(128), .NHART(1), .RETIRE(8)
) rvvi_vif;
// Event to wait on, which will be triggered by the RVVI monitor
uvm_event instruction_retired_event;
// Constructor
function new(string name = "kelvin_cosim_checker",
uvm_component parent = null);
super.new(name, parent);
endfunction
// Build phase: Get VIF handle, create and share event
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Get the RVVI virtual interface from the config_db (set by tb_top)
if (!uvm_config_db#(
virtual rvviTrace #(.ILEN(32), .XLEN(32), .FLEN(32), .VLEN(128),
.NHART(1), .RETIRE(8))
)::get(this, "", "rvvi_vif", rvvi_vif)) begin
`uvm_fatal(get_type_name(), "RVVI virtual interface not found!")
end
// Create the event that this component will wait on.
instruction_retired_event = new("instruction_retired_event");
// Pass the event to the monitor using an absolute path
uvm_config_db#(uvm_event)::set(null, "*.m_rvvi_agent.monitor",
"instruction_retired_event",
instruction_retired_event);
endfunction
// Run phase: Contains the main co-simulation loop
virtual task run_phase(uvm_phase phase);
// TODO: Initialize the MPACT simulator.
`uvm_info("COSIM_STUB", "MPACT simulator would be initialized now.",
UVM_MEDIUM);
// Main co-simulation loop
forever begin
// Wait for the RVVI monitor to signal an instruction retirement
instruction_retired_event.wait_trigger();
// This is a simplified example for one retirement channel (channel 0).
// A full implementation would loop through all NRET channels.
if (rvvi_vif.valid[0][0]) begin // Assuming NHART=1, check hart 0
// Get the retired instruction from the DUT's trace
logic [31:0] retired_instruction = rvvi_vif.insn[0][0];
`uvm_info("COSIM_STUB",
$sformatf("DUT retired instruction 0x%h",
retired_instruction), UVM_HIGH);
// TODO: Send this specific instruction to the MPACT simulator to
// execute, then call comparison task.
step_and_compare();
end
end
endtask
// Task to get state from DUT and MPACT simulator and compare them
virtual task step_and_compare();
// TODO: Implement the full state comparison.
// 1. Make DPI calls to get post-execution state (PC, GPRs, CSRs)
// from MPACT simulator.
// 2. Get the same post-execution state from the DUT via the RVVI
// virtual interface.
// 3. Compare the RTL state against the MPACT simulator state and
// report any mismatches.
endtask
endclass : kelvin_cosim_checker
endpackage : kelvin_cosim_checker_pkg