| use std::collections::HashMap; |
|
|
| |
| |
| #[derive(Debug, Clone)] |
| struct CuTeLayout { |
| shape: Vec<usize>, |
| stride: Vec<usize>, |
| } |
|
|
| impl CuTeLayout { |
| fn get_offset(&self, coords: &[usize]) -> usize { |
| coords.iter().zip(&self.stride).map(|(c, s)| c * s).sum() |
| } |
| } |
|
|
| |
| |
| #[derive(Debug, Clone)] |
| enum SASSOp { |
| HMMA { m: usize, n: usize, k: usize, regs: Vec<u32> }, |
| LDG { addr: u64, dest_reg: u32 }, |
| STG { addr: u64, src_reg: u32 }, |
| } |
|
|
| |
| |
| struct TensorCoreHardware { |
| mac_units_per_cycle: usize, |
| pipeline_depth: usize, |
| clock_speed_ghz: f64, |
| registers: HashMap<u32, Vec<f32>>, |
| } |
|
|
| impl TensorCoreHardware { |
| fn new(macs: usize, depth: usize, speed: f64) -> Self { |
| Self { |
| mac_units_per_cycle: macs, |
| pipeline_depth: depth, |
| clock_speed_ghz: speed, |
| registers: HashMap::new(), |
| } |
| } |
|
|
| |
| fn execute_sass(&mut self, op: SASSOp) -> f64 { |
| match op { |
| SASSOp::HMMA { m, n, k, .. } => { |
| let total_ops = (m * n * k) as f64; |
| let cycles = (total_ops / self.mac_units_per_cycle as f64).ceil(); |
| let latency = cycles + self.pipeline_depth as f64; |
| |
| println!("[HW] Executing HMMA {}x{}x{} | Cycles: {:.2} | Latency: {:.2}ns", |
| m, n, k, cycles, latency / self.clock_speed_ghz); |
| |
| latency / self.clock_speed_ghz |
| } |
| SASSOp::LDG { .. } => { |
| println!("[HW] Memory Load (L1/L2 Cache Hit)"); |
| 20.0 |
| } |
| SASSOp::STG { .. } => { |
| println!("[HW] Memory Store"); |
| 10.0 |
| } |
| } |
| } |
| } |
|
|
| |
| struct NvidStack { |
| hw: TensorCoreHardware, |
| } |
|
|
| impl NvidStack { |
| fn run_tensor_op(&mut self, shape: (usize, usize, usize)) { |
| println!("--- Starting Stack Execution ---"); |
| |
| |
| let layout_a = CuTeLayout { shape: vec![shape.0, shape.2], stride: vec![shape.2, 1] }; |
| let layout_b = CuTeLayout { shape: vec![shape.2, shape.1], stride: vec![shape.1, 1] }; |
| println!("[Stack] Layouts Generated: A({:?}), B({:?})", layout_a, layout_b); |
|
|
| |
| let program = vec![ |
| SASSOp::LDG { addr: 0x1000, dest_reg: 0 }, |
| SASSOp::LDG { addr: 0x2000, dest_reg: 1 }, |
| SASSOp::HMMA { m: shape.0, n: shape.1, k: shape.2, regs: vec![0, 1, 2] }, |
| SASSOp::STG { addr: 0x3000, src_reg: 2 }, |
| ]; |
|
|
| |
| let mut total_time = 0.0; |
| for inst in program { |
| total_time += self.hw.execute_sass(inst); |
| } |
|
|
| println!("--- Stack Execution Complete ---"); |
| println!("Total Wall-Clock Time (Simulated): {:.4} ns", total_time); |
| } |
| } |
|
|
| fn main() { |
| |
| |
| let mut stack = NvidStack { |
| hw: TensorCoreHardware::new(512, 12, 2.1), |
| }; |
|
|
| |
| stack.run_tensor_op((16, 16, 16)); |
| } |