aetheric-gpu 0.1.0-alpha

Aetheric Silicon: turn this host's RAM into a Digital GPU endpoint
//! Example: how to boot a Digital GPU and use it.
//!
//! Run with: `cargo run -p digital-gpu --example run`
//!
//! What it does:
//!   1. Boots a Digital GPU with 32 GB effective VRAM from 2 GB physical RAM
//!   2. Queries the slow-hill curve at various effective capacities
//!   3. Allocates 4 GB of virtual VRAM via 32× binary GEMM compression
//!   4. Reports the live state

use digital_gpu::{CompressionMode, GpuHandle, GpuSpec};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
        .init();

    println!("Aetheric Silicon — Digital GPU Example\n");

    println!("Step 1: Boot a Digital GPU with 2 GB RAM → 32 GB VRAM");
    let mut spec = GpuSpec::new()
        .effective_gb(32)
        .compression(CompressionMode::BinaryGemm)
        .physical_gb(2);
    spec.validate(detect_host_ram_gb())?;

    let (effective_gb, physical_gb, compression) = (
        spec.effective_gb,
        spec.physical_gb.unwrap_or(1),
        spec.compression,
    );

    println!(
        "  - Spec: effective={} GB, physical={} GB, compression={:?}{} expansion)",
        effective_gb, physical_gb, compression, compression.expansion_ratio()
    );

    let gpu = GpuHandle::boot(spec)?;

    println!(
        "  ✓ Booted: {}/{} GB effective",
        gpu.effective_capacity_gb(),
        effective_gb
    );

    println!("\nStep 2: Query the slow-hill curve");
    for vgb in &[1u64, 4, 8, 16, 32] {
        let bytes = vgb * 1024 * 1024 * 1024;
        let bw = gpu.bandwidth_at_effective(bytes);
        let phys = (bytes as f32 / compression.expansion_ratio()) as u64;
        println!(
            "  - {} GB effective → {:.1} GiB/s ({})",
            vgb, bw, gpu.curve().tier_name_at(phys)
        );
    }

    println!("\nStep 3: Allocate 4 GB of virtual VRAM via 32× compression");
    if let Some(arena) = gpu.compressed_arena() {
        let alloc = arena.allocate_effective(4 * 1024 * 1024 * 1024)?;
        println!(
            "  ✓ Allocated: virtual={} GB, physical={} MB, tier={:?}, bandwidth={:.1} GiB/s",
            alloc.effective_bytes() / (1024 * 1024 * 1024),
            alloc.physical_bytes() / (1024 * 1024),
            alloc.deepest_tier(),
            alloc.bandwidth_gib_s()
        );
    }

    println!("\nStep 4: Sample the slow-hill curve");
    for p in gpu.curve_sample(32 * 1024 * 1024 * 1024, 8) {
        println!(
            "  - {} GiB virtual → {:.1} GiB/s ({})",
            p.bytes / (1024 * 1024 * 1024),
            p.bandwidth_gib_s,
            p.tier
        );
    }

    println!("\nDone. The Digital GPU is live.");
    Ok(())
}

fn detect_host_ram_gb() -> u64 {
    #[cfg(target_os = "macos")]
    {
        if let Ok(out) = std::process::Command::new("sysctl")
            .args(["-n", "hw.memsize"])
            .output()
        {
            if let Ok(s) = std::str::from_utf8(&out.stdout) {
                if let Ok(n) = s.trim().parse::<u64>() {
                    return n / (1024 * 1024 * 1024);
                }
            }
        }
    }
    #[cfg(target_os = "linux")]
    {
        if let Ok(s) = std::fs::read_to_string("/proc/meminfo") {
            for line in s.lines() {
                if let Some(rest) = line.strip_prefix("MemTotal:") {
                    if let Some(kib) = rest.trim().split_whitespace().next() {
                        if let Ok(n) = kib.parse::<u64>() {
                            return (n * 1024) / (1024 * 1024 * 1024);
                        }
                    }
                }
            }
        }
    }
    16
}