use sva_samples::{Extent, NodeRenderer, Slot};
use super::lowered_node::leaves;
use super::segments::Segments;
use super::value::{Kind, MachineRun, Value};
use super::values::Values;
#[derive(Clone, Debug, Default)]
pub(crate) struct Need {
pub(crate) hold: Segments,
pub(crate) compute: Segments,
pub(crate) restart: bool,
}
pub(crate) fn demand(values: &Values, asked: &[(usize, Extent)]) -> Vec<Need> {
let mut holds = vec![Segments::default(); values.span()];
for (v, asked_range) in asked {
holds[*v].add(*asked_range);
}
let mut needs = vec![Need::default(); values.span()];
for v in values.ordered().rev() {
let value = &values[v];
let mut hold = holds[v].intersect(value.support());
if let Some(period) = value.period {
hold = hold.folded(period);
}
let (compute, restart) = match &value.kind {
Kind::MachineRun(machine_run) if machine_run.stateful() => {
stateful(value, machine_run, &hold)
}
Kind::Frames { .. } | Kind::Istft => whole(value, &hold),
_ => (hold.minus(&value.holding()), false),
};
match &value.kind {
Kind::MachineRun(machine_run) => {
for segment in compute.iter() {
for (slot, image) in images(machine_run, segment).into_iter().enumerate() {
holds[value.reads[slot]].union(&image);
}
}
}
Kind::Resident { .. } => {
for read in &value.reads {
holds[*read].union(&compute);
}
}
Kind::Frames { .. } | Kind::Istft if !compute.is_empty() => {
let source = value.reads[0];
holds[source].add(values[source].support());
}
_ => {}
}
needs[v] = Need {
hold,
compute,
restart,
};
}
needs
}
pub(crate) fn reach(values: &Values, asked: &[(usize, Extent)]) -> Vec<Segments> {
let mut reach = vec![Segments::default(); values.span()];
for (v, asked_range) in asked {
reach[*v].add(*asked_range);
}
for v in values.ordered().rev() {
let value = &values[v];
let held = reach[v].intersect(value.support());
match &value.kind {
Kind::MachineRun(machine_run) => {
for segment in held.iter() {
for (slot, image) in images(machine_run, segment).into_iter().enumerate() {
reach[value.reads[slot]].union(&image);
}
}
}
Kind::Resident { .. } => {
for read in &value.reads {
reach[*read].union(&held);
}
}
_ => {}
}
reach[v] = held;
}
reach
}
fn stateful(value: &Value, machine_run: &MachineRun, hold: &Segments) -> (Segments, bool) {
if hold.is_empty() {
return (Segments::default(), false);
}
let first = hold.hull().start;
let start = machine_run
.start
.expect("a stateful machine run")
.min(first);
let last = hold.hull().end;
let (from, restart) = match value.end() {
None => (start, true),
Some(end) => {
let before = hold.intersect(Extent::new(i64::MIN, end));
match value.holding().covers(&before) {
true => (end, false),
false => (start, true),
}
}
};
match from < last {
true => (Segments::of(Extent::new(from, last)), restart),
false => (Segments::default(), false),
}
}
fn whole(value: &Value, hold: &Segments) -> (Segments, bool) {
debug_assert!(value.support().is_bounded(), "a whole value's support ends");
match hold.is_empty() || !value.holding().is_empty() {
true => (Segments::default(), false),
false => (Segments::of(value.support()), false),
}
}
pub(crate) fn images(machine_run: &MachineRun, over: Extent) -> Vec<Segments> {
let mut out = vec![Segments::default(); machine_run.layout.read_widths.len()];
for span in machine_run.spanned.spans() {
let met = over.intersect(Extent::new(span.from, span.to));
if met.is_empty() {
continue;
}
leaves(&span.renderer, &mut |leaf| match leaf {
NodeRenderer::Read {
slot: Slot::Read(at),
map,
} => out[at.0 as usize].add(map.image(met)),
NodeRenderer::Indexed {
slot: Slot::Read(at),
reach,
..
} => {
let (least, most) = reach.unwrap_or((i64::MIN, i64::MAX));
let from = met.start.saturating_add(least);
let to = met.end.saturating_add(most).max(from);
out[at.0 as usize].add(Extent::new(from, to));
}
_ => {}
});
}
out
}