use super::*;
#[derive(Debug, Clone)]
pub enum Instruction {
Const { trg: TrgId, port: Port },
Link { a: TrgId, b: TrgId },
LinkConst { trg: TrgId, port: Port },
Ctr { lab: Lab, trg: TrgId, lft: TrgId, rgt: TrgId },
Op { op: Op, trg: TrgId, rhs: TrgId, out: TrgId },
OpNum { op: Op, trg: TrgId, rhs: Port, out: TrgId },
Mat { trg: TrgId, lft: TrgId, rgt: TrgId },
Wires { av: TrgId, aw: TrgId, bv: TrgId, bw: TrgId },
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TrgId {
pub(super) byte_offset: usize,
}
impl TrgId {
pub fn new(index: usize) -> Self {
TrgId { byte_offset: index * size_of::<Trg>() }
}
pub fn index(&self) -> usize {
self.byte_offset / size_of::<Trg>()
}
}
impl fmt::Display for TrgId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "t{}", self.index())
}
}
impl fmt::Debug for TrgId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TrgId({})", self.index())
}
}
impl<'a, M: Mode> Net<'a, M> {
#[inline(always)]
pub(crate) fn do_ctr(&mut self, lab: Lab, trg: Trg) -> (Trg, Trg) {
let port = trg.target();
#[allow(clippy::overly_complex_bool_expr)]
if !M::LAZY && port.tag() == Ctr && port.lab() == lab {
trace!(self.tracer, "fast");
self.free_trg(trg);
let node = port.consume_node();
self.rwts.anni += 1;
(Trg::wire(node.p1), Trg::wire(node.p2))
} else if false && !M::LAZY && (port.is_num() || port.tag() == Ref && lab >= port.lab()) {
self.rwts.comm += 1;
self.free_trg(trg);
(Trg::port(port.clone()), Trg::port(port))
} else {
let n = self.create_node(Ctr, lab);
self.link_trg_port(trg, n.p0);
(Trg::port(n.p1), Trg::port(n.p2))
}
}
#[inline(always)]
pub(crate) fn do_op(&mut self, op: Op, trg: Trg) -> (Trg, Trg) {
trace!(self.tracer, op, trg);
let port = trg.target();
if !M::LAZY && port.is_num() {
self.free_trg(trg);
let n = self.create_node(Op, op.swap().into());
n.p1.wire().set_target(port);
(Trg::port(n.p0), Trg::port(n.p2))
} else if !M::LAZY && port == Port::ERA {
self.free_trg(trg);
(Trg::port(Port::ERA), Trg::port(Port::ERA))
} else {
let n = self.create_node(Op, op.into());
self.link_trg_port(trg, n.p0);
(Trg::port(n.p1), Trg::port(n.p2))
}
}
#[inline(always)]
pub(crate) fn do_op_num(&mut self, op: Op, trg: Trg, rhs: Port) -> Trg {
let port = trg.target();
if !M::LAZY && port.is_num() {
self.rwts.oper += 1;
self.free_trg(trg);
let res = op.op(port.num(), rhs.num());
Trg::port(Port::new_num(if op.is_int() { Tag::Int } else { Tag::F32 }, res))
} else if !M::LAZY && port == Port::ERA {
self.free_trg(trg);
Trg::port(Port::ERA)
} else {
let n = self.create_node(Op, op.into());
self.link_trg_port(trg, n.p0);
n.p1.wire().set_target(rhs);
Trg::port(n.p2)
}
}
#[inline(always)]
pub(crate) fn do_mat(&mut self, trg: Trg) -> (Trg, Trg) {
let port = trg.target();
if !M::LAZY && port.tag() == Int {
self.rwts.oper += 1;
self.free_trg(trg);
let num = port.int();
let c1 = self.create_node(Ctr, 0);
if num == 0 {
self.link_port_port(c1.p2, Port::ERA);
(Trg::port(c1.p0), Trg::wire(self.create_wire_to(c1.p1)))
} else {
let c2 = self.create_node(Ctr, 0);
self.link_port_port(c1.p1, Port::ERA);
self.link_port_port(c1.p2, c2.p0);
self.link_port_port(c2.p1, Port::new_int(num - 1));
(Trg::port(c1.p0), Trg::wire(self.create_wire_to(c2.p2)))
}
} else if !M::LAZY && port == Port::ERA {
self.rwts.eras += 1;
self.free_trg(trg);
(Trg::port(Port::ERA), Trg::port(Port::ERA))
} else {
let m = self.create_node(Mat, 0);
self.link_trg_port(trg, m.p0);
(Trg::port(m.p1), Trg::port(m.p2))
}
}
#[inline(always)]
pub(crate) fn do_wires(&mut self) -> (Trg, Trg, Trg, Trg) {
let a = self.alloc();
let b = a.other_half();
(Trg::port(Port::new_var(a)), Trg::wire(Wire::new(a)), Trg::port(Port::new_var(b)), Trg::wire(Wire::new(b)))
}
#[inline(always)]
#[allow(unused)] pub(crate) fn do_mat_con_con(&mut self, trg: Trg, out: Trg) -> (Trg, Trg, Trg) {
let port = trg.target();
if !M::LAZY && trg.target().tag() == Int {
self.rwts.oper += 1;
self.free_trg(trg);
let num = port.int();
if num == 0 {
(out, Trg::port(Port::ERA), Trg::port(Port::ERA))
} else {
(Trg::port(Port::ERA), Trg::port(Port::new_int(num - 1)), out)
}
} else if !M::LAZY && port == Port::ERA {
self.link_trg_port(out, Port::ERA);
(Trg::port(Port::ERA), Trg::port(Port::ERA), Trg::port(Port::ERA))
} else {
let m = self.create_node(Mat, 0);
let c1 = self.create_node(Ctr, 0);
let c2 = self.create_node(Ctr, 0);
self.link_port_port(m.p1, c1.p0);
self.link_port_port(c1.p2, c2.p0);
self.link_trg_port(out, m.p2);
(Trg::port(c1.p1), Trg::port(c2.p1), Trg::port(c2.p2))
}
}
#[inline(always)]
#[allow(unused)] pub(crate) fn do_mat_con(&mut self, trg: Trg, out: Trg) -> (Trg, Trg) {
let port = trg.target();
if trg.target().tag() == Int {
self.rwts.oper += 1;
self.free_trg(trg);
let num = port.int();
if num == 0 {
(out, Trg::port(Port::ERA))
} else {
let c2 = self.create_node(Ctr, 0);
c2.p1.wire().set_target(Port::new_int(num - 1));
self.link_trg_port(out, c2.p2);
(Trg::port(Port::ERA), Trg::port(c2.p0))
}
} else if port == Port::ERA {
self.link_trg_port(out, Port::ERA);
(Trg::port(Port::ERA), Trg::port(Port::ERA))
} else {
let m = self.create_node(Mat, 0);
let c1 = self.create_node(Ctr, 0);
self.link_port_port(m.p1, c1.p0);
self.link_trg_port(out, m.p2);
self.link_trg_port(trg, m.p0);
(Trg::port(c1.p1), Trg::port(c1.p2))
}
}
}