use rlx_ir::op::Activation;
use rlx_ir::{DType, Graph, Philox4x32, Shape};
use rlx_opscope::optimize::{mine_opportunities, report};
use rlx_opscope::{Recorder, StatConfig, inject_matmul_stats, write_site_costs};
use rlx_runtime::{Device, Session};
const S: usize = 32;
fn sh(d: &[usize]) -> Shape {
Shape::new(d, DType::F32)
}
fn pyramid_mlp(widths: &[(usize, usize)]) -> Graph {
let mut g = Graph::new("pyramid");
let mut x = g.input("x", sh(&[S, widths[0].0]));
for (i, &(din, dout)) in widths.iter().enumerate() {
let w = g.param(format!("W{i}"), sh(&[din, dout]));
let h = g.matmul(x, w, sh(&[S, dout]));
x = g.activation(Activation::Relu, h, sh(&[S, dout]));
}
g.set_outputs(vec![x]);
g
}
fn main() -> std::io::Result<()> {
let steps: u64 = std::env::args()
.nth(1)
.and_then(|s| s.parse().ok())
.unwrap_or(20);
let pool: usize = std::env::args()
.nth(2)
.and_then(|s| s.parse().ok())
.unwrap_or(4);
let out = std::env::args()
.nth(3)
.unwrap_or_else(|| "opscope_replay.csv".into());
let widths = [(64usize, 128usize), (128, 64), (64, 512), (512, 64)];
let d0 = widths[0].0;
let (g, specs) = inject_matmul_stats(&pyramid_mlp(&widths), &StatConfig::default());
let mut c = Session::new(Device::Cpu).compile(g);
let mut rng = Philox4x32::new(0xA11CE);
for (i, &(din, dout)) in widths.iter().enumerate() {
let mut w = vec![0f32; din * dout];
rng.fill_normal(&mut w);
let scale = (2.0 / din as f32).sqrt();
for v in &mut w {
*v *= scale;
}
c.set_param(&format!("W{i}"), &w);
}
let walk = pool == 0;
let inputs: Vec<Vec<f32>> = if walk {
Vec::new()
} else {
(0..pool)
.map(|_| {
let mut v = vec![0f32; S * d0];
rng.fill_normal(&mut v);
v
})
.collect()
};
let mut cur = vec![0f32; S * d0];
rng.fill_normal(&mut cur);
let mut rec = Recorder::create(&out)?;
for step in 0..steps {
if walk && step > 0 {
let mut n = vec![0f32; S * d0];
rng.fill_normal(&mut n);
for (c, dn) in cur.iter_mut().zip(&n) {
*c += 0.03 * dn; }
}
let x: &[f32] = if walk {
&cur
} else {
&inputs[(rng.next_u32() as usize) % pool]
};
let outs = c.run(&[("x", x)]);
rec.record(0, step, "cpu", "replay", S, d0, 0, &specs, &outs)?;
}
rec.flush()?;
let sidecar = format!("{out}.sites");
write_site_costs(&sidecar, &specs)?;
eprintln!(
"[opscope] replayed {steps} steps over a pool of {pool} inputs → {out} (+{sidecar})\n"
);
let opps = mine_opportunities(&out, &sidecar)?;
report(&opps);
Ok(())
}