use super::FabricClass;
use super::wgsl::{Detector, Mutant};
pub const SOURCE: &str = include_str!("lanes64.cu");
pub const IMPLEMENTATION: &str = "cuda-lanes64";
pub const HOST_LAYOUT: u32 = 1;
pub const BLOCK: u32 = 256;
pub const GRID_MAX: u32 = 4096;
pub const COMPILE_OPTIONS: [&str; 2] = ["--std=c++17", "--fmad=false"];
const DOMAIN_IMPLEMENTATION: &[u8] = b"wai:quantum-fabric-cuda\x01";
const DOMAIN_MEMBER: &[u8] = b"wai:quantum-fabric-cuda-member\x01";
fn hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}
fn put(o: &mut Vec<u8>, bytes: &[u8]) {
o.extend_from_slice(&(bytes.len() as u64).to_be_bytes());
o.extend_from_slice(bytes);
}
pub fn implementation_id() -> String {
implementation_id_of(SOURCE)
}
pub fn implementation_id_of(source: &str) -> String {
let mut o = DOMAIN_IMPLEMENTATION.to_vec();
put(&mut o, source.as_bytes());
for option in COMPILE_OPTIONS {
put(&mut o, option.as_bytes());
}
o.extend_from_slice(&HOST_LAYOUT.to_be_bytes());
format!("{IMPLEMENTATION}/{}", hex(&blake3::hash(&o).as_bytes()[..8]))
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DeviceIdentity {
pub name: String,
pub uuid: String,
pub compute: (u32, u32),
pub pci: String,
pub driver: u32,
pub compiler: (u32, u32),
pub memory: u64,
}
impl DeviceIdentity {
pub fn class(&self) -> FabricClass {
FabricClass::Gpu
}
pub fn arch(&self) -> String {
format!("compute_{}{}", self.compute.0, self.compute.1)
}
pub fn member_id(&self) -> String {
let mut o = DOMAIN_MEMBER.to_vec();
put(&mut o, self.name.as_bytes());
put(&mut o, self.uuid.as_bytes());
o.extend_from_slice(&self.compute.0.to_be_bytes());
o.extend_from_slice(&self.compute.1.to_be_bytes());
put(&mut o, self.pci.as_bytes());
o.extend_from_slice(&self.driver.to_be_bytes());
o.extend_from_slice(&self.compiler.0.to_be_bytes());
o.extend_from_slice(&self.compiler.1.to_be_bytes());
o.extend_from_slice(&self.memory.to_be_bytes());
format!("local/gpu-cuda-{}", hex(&blake3::hash(&o).as_bytes()[..6]))
}
pub fn key(&self) -> String {
format!("gpu-cuda-sm{}{}", self.compute.0, self.compute.1)
}
}
pub const MUTANTS: [Mutant; 6] = [
Mutant { name: "C1", find: "((i64)a * (i64)b + ((i64)1 << 29)) >> 30;", replace: "((i64)a * (i64)b + ((i64)1 << 28)) >> 30;", detector: Detector::Probe },
Mutant { name: "C2", find: "((i64)a * (i64)b + ((i64)1 << 29)) >> 30;", replace: "((i64)a * (i64)b + ((i64)1 << 29)) >> 29;", detector: Detector::Probe },
Mutant { name: "C3", find: "u64 prod = (u64)((i64)c.x * (i64)c.y);", replace: "u64 prod = (u64)(unsigned int)(c.x * c.y);", detector: Detector::Probe },
Mutant { name: "C4", find: "if ((i & (u64)ctrl) != (u64)ctrl) {", replace: "if ((i & (u64)ctrl) == (u64)ctrl) {", detector: Detector::Certificate },
Mutant { name: "C5", find: "fx(m2, a1.x) - fx(m3, a1.y);", replace: "fx(m2, a1.x) + fx(m3, a1.y);", detector: Detector::Certificate },
Mutant { name: "C6", find: "if (!(fits32(o0r) && fits32(o0i) && fits32(o1r) && fits32(o1i))) {", replace: "if (false) {", detector: Detector::Range },
];
pub fn mutate(m: &Mutant) -> String {
let n = SOURCE.matches(m.find).count();
assert_eq!(n, 1, "mutant {}: `{}` occurs {n} times in the kernel", m.name, m.find);
SOURCE.replacen(m.find, m.replace, 1)
}
#[cfg(test)]
mod tests {
use super::*;
fn identity() -> DeviceIdentity {
DeviceIdentity {
name: "a device".into(),
uuid: "00112233445566778899aabbccddeeff".into(),
compute: (8, 9),
pci: "0000:01:00".into(),
driver: 13020,
compiler: (12, 8),
memory: 6 << 30,
}
}
#[test]
fn every_field_of_the_identity_is_in_the_member_id() {
let base = identity();
let id = base.member_id();
assert!(id.starts_with("local/gpu-cuda-") && id.len() == "local/gpu-cuda-".len() + 12, "{id}");
assert!(id.as_str() > "local/cpu-x86_64" && id.as_str() > "local/cpu-aarch64", "sorts after every CPU reference");
let variants = [
DeviceIdentity { name: "another".into(), ..identity() },
DeviceIdentity { uuid: "ff".into(), ..identity() },
DeviceIdentity { compute: (9, 0), ..identity() },
DeviceIdentity { compute: (8, 6), ..identity() },
DeviceIdentity { pci: "0000:02:00".into(), ..identity() },
DeviceIdentity { driver: 12080, ..identity() },
DeviceIdentity { compiler: (13, 0), ..identity() },
DeviceIdentity { compiler: (12, 9), ..identity() },
DeviceIdentity { memory: 8 << 30, ..identity() },
];
for v in variants {
assert_ne!(v.member_id(), id, "{v:?}");
}
assert_eq!(base.key(), "gpu-cuda-sm89");
assert_eq!(base.arch(), "compute_89");
assert_eq!(base.class(), FabricClass::Gpu);
}
#[test]
fn the_implementation_id_follows_the_kernel_text() {
let id = implementation_id();
assert!(id.starts_with("cuda-lanes64/") && id.len() == "cuda-lanes64/".len() + 16, "{id}");
for m in &MUTANTS {
assert_ne!(implementation_id_of(&mutate(m)), id, "mutant {}", m.name);
}
}
#[test]
fn every_mutant_edits_the_kernel_once_and_names_distinct_edits() {
let mut seen = std::collections::BTreeSet::new();
for m in &MUTANTS {
let edited = mutate(m);
assert_ne!(edited, SOURCE, "mutant {} changes nothing", m.name);
assert!(seen.insert(edited), "mutant {} duplicates another", m.name);
}
for d in [Detector::Probe, Detector::Certificate, Detector::Range] {
assert!(MUTANTS.iter().any(|m| m.detector == d), "no mutant for {d:?}");
}
}
}