use std::fmt::{self, Debug, Formatter};
use crate::util::{AsUsize, ArrayMap, CommaSeparated};
use super::{Dep, Op, Cost, op_cost};
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Node(std::num::NonZeroUsize) {
debug_name: "Node",
UInt: usize,
}
}
struct NodeAdapter<'a> {
dataflow: &'a Dataflow,
node: Node,
}
impl<'a> Debug for NodeAdapter<'a> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{:?} <- {:?} ({:?})",
self.node,
self.dataflow.op(self.node),
CommaSeparated(|| self.dataflow.ins(self.node)),
)?;
Ok(())
}
}
#[derive(Clone)]
struct Info {
op: Op,
deps: &'static [Dep],
cost: &'static Cost,
start_in: usize,
}
#[derive(Clone)]
pub struct Dataflow {
inputs: Box<[Node]>,
nodes: Vec<Info>,
ins: Vec<Node>,
}
impl Dataflow {
pub fn new(num_inputs: usize) -> Self {
let mut ret = Dataflow {
inputs: (0..(num_inputs+1)).map(|i| Node::new(i).unwrap()).collect(),
nodes: Vec::new(),
ins: Vec::new(),
};
for i in 0..(num_inputs+1) {
let node = ret.add_node(Op::Input, &[]);
assert_eq!(node, ret.inputs[i]);
}
ret
}
pub fn undefined(&self) -> Node {
self.inputs[0]
}
pub fn inputs(&self) -> &[Node] {
&self.inputs[1..]
}
fn info(&self, node: Node) -> &Info {
&self.nodes[node.as_usize()]
}
pub fn op(&self, node: Node) -> Op {
self.info(node).op
}
pub fn cost(&self, node: Node) -> &'static Cost {
self.info(node).cost
}
pub fn ins(&self, node: Node) -> &[Node] {
let info = self.info(node);
&self.ins[info.start_in..][..info.deps.len()]
}
pub fn each_input(&self, node: Node, mut callback: impl FnMut(Node, Dep)) {
let info = self.info(node);
for (&dep, &in_) in info.deps.iter().zip(&self.ins[info.start_in..]) {
callback(in_, dep);
}
}
pub fn discriminant(&self, guard: Node) -> Node {
let info = self.info(guard);
assert_eq!(info.op, Op::Guard);
self.ins[info.start_in + 1]
}
pub fn has_out(&self, node: Node) -> bool {
self.cost(node).latency != 0xFF
}
pub fn add_node(&mut self, op: Op, ins: &[Node]) -> Node {
let deps = op.deps();
assert_eq!(ins.len(), deps.len());
for (&in_, &dep) in ins.iter().zip(deps) {
if dep.is_value() { assert!(self.has_out(in_)); }
}
let cost = op_cost(op);
let start_in = self.ins.len();
let node = Node::new(self.nodes.len()).unwrap();
self.ins.extend(ins);
self.nodes.push(Info {op, deps, cost, start_in});
node
}
pub fn node_map<V: Default>(&self) -> ArrayMap<Node, V> {
ArrayMap::new(self.nodes.len())
}
pub fn all_nodes(&self) -> impl Iterator<Item=Node> {
(0..self.nodes.len()).map(|i| Node::new(i).unwrap())
}
}
impl Debug for Dataflow {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str("Dataflow")?;
f.debug_list().entries(self.all_nodes().map(
|n| NodeAdapter {dataflow: self, node: n}
)).finish()
}
}