mod context_kv;
mod forward;
mod layer;
mod select;
pub(crate) use select::read_f16_rows;
use foundation::{LogitValue, TokenId};
use super::dflash::{DFLASH_MASK_TOKEN, DFLASH_RESIDUAL_SCALE};
use crate::real_forward::{RealForwardError, RealForwardRunner};
pub(crate) const DFLASH_THETA: f32 = 1e7;
pub(crate) const RESIDUAL_RESCALE: f32 = 1.0 / DFLASH_RESIDUAL_SCALE;
pub(crate) use crate::real_forward_utils::ring_spans;
impl RealForwardRunner {
pub fn dflash_prime_from_capture(&mut self, position: usize) -> Result<(), RealForwardError> {
let Some(d) = self.real_dflash.as_ref() else {
return Err(RealForwardError::Unsupported(
"no DFlash2 state; set TURBOSPARK_DFLASH_DRAFT before opening the model"
.to_string(),
));
};
if d.kv.position() != position {
return Err(RealForwardError::Unsupported(format!(
"DFlash2 prime at position {position} but its cache covers [0, {})",
d.kv.position()
)));
}
if d.capture_base != position || d.capture_rows < 1 {
return Err(RealForwardError::Unsupported(format!(
"DFlash2 prime at position {position} but the capture buffer holds {} rows at \
base {}",
d.capture_rows, d.capture_base
)));
}
self.dflash_context_write(1)
}
pub fn dflash_rewind_to(&mut self, position: usize) -> Result<(), RealForwardError> {
let Some(d) = self.real_dflash.as_mut() else {
return Err(RealForwardError::Unsupported(
"no DFlash2 state to rewind".to_string(),
));
};
let cursor = d.kv.position();
if position >= cursor {
return Ok(());
}
if cursor - position > d.kv.max_safe_rewind() {
return Err(RealForwardError::Unsupported(format!(
"DFlash2 rewind of {} rows exceeds the ring's slack {}",
cursor - position,
d.kv.max_safe_rewind()
)));
}
d.kv.rewind_by(cursor - position);
Ok(())
}
pub fn dflash_draft_block(
&mut self,
anchor: TokenId,
base: usize,
proposals: &mut Vec<TokenId>,
) -> Result<(), RealForwardError> {
let vocab = self.arch.vocab_size as usize;
let Some(d) = self.real_dflash.as_ref() else {
return Err(RealForwardError::Unsupported(
"no DFlash2 state; set TURBOSPARK_DFLASH_DRAFT before opening the model"
.to_string(),
));
};
let block = d.block;
proposals.clear();
if anchor < 0 || anchor as usize >= vocab || DFLASH_MASK_TOKEN as usize >= vocab {
return Err(RealForwardError::Unsupported(format!(
"DFlash2 needs token ids {anchor} (anchor) and {DFLASH_MASK_TOKEN} (mask) inside \
vocab {vocab}"
)));
}
gpu::autorelease_pool(|| {
let ctx_rows = {
let d = self.real_dflash.as_ref().expect("checked above");
let capture_end = d.capture_base + d.capture_rows;
if d.kv.position() > base {
return Err(RealForwardError::Unsupported(format!(
"the drafter's cursor {} is past the round's base {base}",
d.kv.position()
)));
}
if base < d.capture_base {
return Err(RealForwardError::Unsupported(format!(
"the round's base {base} is behind the capture base {}",
d.capture_base
)));
}
base.min(capture_end) - d.capture_base
};
if ctx_rows > 0 {
self.dflash_context_write(ctx_rows)?;
}
self.dflash_forward_block(anchor, base)
})?;
self.dflash_select(anchor, block, proposals)
}
pub fn dflash_probe_logits(
&self,
row: usize,
out: &mut [LogitValue],
) -> Result<(), RealForwardError> {
let Some(d) = self.real_dflash.as_ref() else {
return Err(RealForwardError::Unsupported(
"no DFlash2 state".to_string(),
));
};
let vocab = self.arch.vocab_size as usize;
if out.len() != vocab {
return Err(RealForwardError::Unsupported(format!(
"probe buffer {} vs vocab {vocab}",
out.len()
)));
}
gpu::read_buffer_f16_into(&d.logits, row * vocab * 2, out);
Ok(())
}
pub fn dflash_probe_buffers(&self) -> Vec<(&'static str, usize, f32, f32)> {
let Some(d) = self.real_dflash.as_ref() else {
return Vec::new();
};
let s = &d.shape;
let rows = d.block + 1;
let scan = |buf: &gpu::MetalBuffer, width: usize| {
let v = read_f16_rows(buf, rows, width);
let nans = v.iter().filter(|f| f.is_nan()).count();
let fin = || v.iter().copied().filter(|f| f.is_finite());
(
nans,
fin().fold(f32::INFINITY, f32::min),
fin().fold(f32::NEG_INFINITY, f32::max),
)
};
[
("capture", &d.capture, s.aux_count * s.hidden),
("ctx_combined", &d.ctx_combined, s.hidden),
("ctx_normed", &d.ctx_normed, s.hidden),
("x", &d.x, s.hidden),
("normed", &d.normed, s.hidden),
("coeffs", &d.coeffs, s.conv_rows),
("conv_p", &d.conv_p, s.hidden),
("q", &d.q, s.num_heads * s.head_dim),
("attn_out", &d.attn_out, s.num_heads * s.head_dim),
("sub_out", &d.sub_out, s.hidden),
("conv_f", &d.conv_f, s.hidden),
("ffn_gate", &d.ffn_gate, s.inter),
("ffn_up", &d.ffn_up, s.inter),
("ffn_act", &d.ffn_act, s.inter),
("hproj", &d.hproj, s.rank),
]
.into_iter()
.map(|(name, buf, width)| {
let (nans, min, max) = scan(buf, width);
(name, nans, min, max)
})
.collect()
}
}