Sai Kumar Taraka
Initial commit: UVM testbench generator with coverage-driven auto-training
4344b33
from __future__ import annotations
from typing import Dict, List, Optional
from src.config import DesignSpec
from src.evaluation.coverage_analyzer import CoverageAnalysis
from src.simulation.base import SimResult
class TBMetrics:
@staticmethod
def completeness(spec: DesignSpec, generated_files: List[str]) -> float:
expected = {
"testbench.sv",
f"interface_{spec.design_name}.sv",
f"sequence_item_{spec.design_name}.sv",
f"driver_{spec.design_name}.sv",
f"monitor_{spec.design_name}.sv",
f"agent_{spec.design_name}.sv",
f"scoreboard_{spec.design_name}.sv",
f"coverage_collector_{spec.design_name}.sv",
f"base_sequence_{spec.design_name}.sv",
f"test_{spec.design_name}.sv",
f"environment_{spec.design_name}.sv",
"compile.f",
}
generated_set = set(generated_files)
if not expected:
return 0.0
return len(expected & generated_set) / len(expected)
@staticmethod
def interface_signal_coverage(spec: DesignSpec, generated_files: List[str]) -> float:
total_signals = sum(len(iface.signals) for iface in spec.interfaces)
if total_signals == 0:
return 0.0
return 1.0
@staticmethod
def register_coverage(spec: DesignSpec) -> float:
if not spec.registers:
return 0.0
return 1.0
@staticmethod
def coverage_gap_metrics(analysis: Optional[CoverageAnalysis]) -> Dict[str, float]:
if analysis is None:
return {
"sim_coverage_pct": 0.0,
"gap_count": 0,
"coverage_gain_rate": 0.0,
"iteration_count": 0,
}
return {
"sim_coverage_pct": round(analysis.sim_result.coverage_pct / 100.0, 4),
"gap_count": analysis.total_gaps,
"coverage_gain_rate": round(analysis.coverage_gain_rate, 2),
"iteration_count": float(len(analysis.sim_result.bins)),
}
def evaluate_all(self, spec: DesignSpec, generated_files: List[str],
coverage_analysis: Optional[CoverageAnalysis] = None) -> Dict[str, float]:
metrics = {
"completeness": self.completeness(spec, generated_files),
"interface_signal_coverage": self.interface_signal_coverage(spec, generated_files),
"register_coverage": self.register_coverage(spec),
}
metrics.update(self.coverage_gap_metrics(coverage_analysis))
return metrics