# Portable fast-sim runtime check for customers.
# Detects Icarus / Verilator / cocotb / Python from PATH plus common install
# directories, and gives a clear 3-way install guide. It NEVER auto-launches an
# installer GUI; an AI agent should let the user choose how to install.
#
# Runtimes (user-installed, open source):
#   - Icarus Verilog (iverilog / vvp): REQUIRED core simulator
#       https://bleyer.org/icarus/
#   - Python 3.13 + cocotb: only for cocotb/Python testbench flows
#       (cocotb 2.0.x supports up to Python 3.13, not 3.14)
#   - Verilator (optional): https://www.verilator.org/
#   - C++ toolchain (optional, for Verilator C++): make + g++/clang
#
# This file is ASCII-only so it parses cleanly on any Windows PowerShell
# codepage (no UTF-8 BOM dependency).
#
# Usage:
#   powershell -File check_fast_sim.ps1
#   powershell -File check_fast_sim.ps1 -IverilogDir "C:\iverilog\bin"
#   powershell -File check_fast_sim.ps1 -VerilatorDir "D:\tools\verilator\bin"

param(
    [string]$IverilogDir = "",      # bin dir where iverilog.exe/vvp.exe live (already installed, not on PATH)
    [string]$VerilatorDir = "",     # bin dir where verilator.exe lives (already installed, not on PATH)
    [string]$CocotbDir = ""         # a Python home/bin that has cocotb (optional)
)

$script:missing = @()

function Report($status, $text) {
    if ($status -eq "OK") { Write-Host "[OK]   $text" }
    elseif ($status -eq "WARN") { Write-Host "[WARN] $text" }
    else { Write-Host "[MISS] $text"; $script:missing += $text }
}

# Locate an executable by name: on PATH first, then in user-provided dirs,
# then in a set of common install locations. Returns the full path or "".
function Find-Tool([string]$name, [string]$providedDir, [string[]]$commonDirs) {
    $cmd = Get-Command $name -ErrorAction SilentlyContinue
    if ($cmd) { return $cmd.Source }
    if ($providedDir) {
        $c = Join-Path $providedDir $name
        if (Test-Path -LiteralPath $c) { return $c }
    }
    foreach ($d in $commonDirs) {
        $c = Join-Path $d $name
        if (Test-Path -LiteralPath $c) { return $c }
    }
    return ""
}

$programFiles = @($env:ProgramFiles, ${env:ProgramFiles(x86)}, $env:LOCALAPPDATA) | Where-Object { $_ }

Write-Host "`n=== Fast Simulation Runtime Check ==="

# ---- Python + cocotb ----
Write-Host "`n[Python / cocotb]"
$py = Get-Command python -ErrorAction SilentlyContinue
if (-not $py -and $CocotbDir) { $py = Get-Command (Join-Path $CocotbDir "python.exe") -ErrorAction SilentlyContinue }
if ($py) {
    Report "OK" "python -> $($py.Source)"
    $pyver = & $py.Source -c "import sys; print('%d.%d' % (sys.version_info[0], sys.version_info[1]))" 2>$null
    $cocotb = & $py.Source -c "import importlib.util; print('1' if importlib.util.find_spec('cocotb') else '')" 2>$null
    if ($cocotb -match '1') {
        Report "OK" "cocotb installed"
    } else {
        Report "MISS" "cocotb - python -m pip install cocotb"
        if ($pyver -match '^3\.1[45]') {
            Write-Host "       NOTE: cocotb 2.0.x supports up to Python 3.13; Python $pyver cannot install it."
            Write-Host "       Use Python 3.13 for cocotb flows, or skip cocotb - pure-Verilog testbenches only need iverilog."
        }
    }
} else {
    Report "MISS" "python - optional (only needed for cocotb flows)"
}

# ---- Icarus Verilog (required) ----
Write-Host "`n[Icarus Verilog (required)]"
$iverilogCommon = @("C:\iverilog\bin", "C:\iverilog") + @($programFiles | ForEach-Object { Join-Path $_ "iverilog\bin" })
$iverilog = Find-Tool "iverilog.exe" $IverilogDir $iverilogCommon
$vvp = Find-Tool "vvp.exe" $IverilogDir $iverilogCommon
if ($iverilog -and $vvp) {
    Report "OK" "iverilog -> $iverilog"
    Report "OK" "vvp -> $vvp"
} else {
    if ($IverilogDir) { Report "WARN" "iverilog not found at -IverilogDir=$IverilogDir" }
    Report "MISS" "Icarus Verilog (iverilog / vvp) - REQUIRED"
    Write-Host ""
    Write-Host "  Install one of these ways (AI must NOT auto-launch a GUI installer):"
    Write-Host "  [A] Manual: download from https://bleyer.org/icarus/, run the installer,"
    Write-Host "      then tell the AI the install path OR re-run this check."
    Write-Host "  [B] Silent (authorized): winget install -e --id Icaros.iverilog   (or: choco install iverilog)"
    Write-Host "  [C] Already installed but not on PATH: pass -IverilogDir with the bin dir"
    Write-Host "      e.g. powershell -File check_fast_sim.ps1 -IverilogDir C:\iverilog\bin"
}

# ---- Verilator (optional) ----
Write-Host "`n[Verilator (optional)]"
$verilatorCommon = @("C:\verilator\bin") + @($programFiles | ForEach-Object { Join-Path $_ "verilator\bin" })
$verilator = Find-Tool "verilator.exe" $VerilatorDir $verilatorCommon
if ($verilator) { Report "OK" "verilator -> $verilator" } else { Report "MISS" "Verilator (optional)" }
$yosys = Find-Tool "yosys.exe" "" $verilatorCommon
if ($yosys) { Report "OK" "yosys -> $yosys" } else { Report "MISS" "Yosys (optional)" }

# ---- C++ toolchain (optional) ----
Write-Host "`n[Build Tools (optional, for Verilator C++)]"
foreach ($pair in @(@("make","make"), @("mingw32-make","mingw32-make"), @("g++","g++"), @("clang++","clang++"))) {
    $cmd = Get-Command $pair[0] -ErrorAction SilentlyContinue
    if ($cmd) { Report "OK" "$($pair[1]) -> $($cmd.Source)" } else { Report "MISS" "$($pair[1]) (optional)" }
}

# ---- Summary ----
Write-Host "`n=== Summary ==="
$coreMissing = @($script:missing | Where-Object { $_ -match 'Icarus' })
if ($coreMissing.Count -eq 0) {
    Write-Host "Icarus Verilog found. Fast simulation is usable for pure-Verilog testbenches."
    if ($script:missing.Count -gt 0) {
        Write-Host "Optional missing: $($script:missing -join ', ')"
    }
    Write-Host "Example: powershell -File tools\simulation_acceleration\scripts\run_smoke_counter.ps1"
    exit 0
} else {
    Write-Host "REQUIRED runtime missing: Icarus Verilog. See the install guide above."
    Write-Host "Missing (optional): $($script:missing -join ', ')"
    Write-Host "Re-run this check after installing, or pass -IverilogDir with the install bin dir."
    exit 1
}
