diff --git a/starlight/src/epoch.rs b/starlight/src/epoch.rs index 9cd5ca8b..d2174f9c 100644 --- a/starlight/src/epoch.rs +++ b/starlight/src/epoch.rs @@ -66,7 +66,7 @@ thread_local!( ); /// Gets the thread-local `TDag`. Note: do not get recursively. -pub fn get_tdag T>(f: F) -> T { +pub fn get_tdag T>(mut f: F) -> T { EPOCH_DATA_TOP.with(|top| { let top = top.borrow(); f(&top.tdag) @@ -74,7 +74,7 @@ pub fn get_tdag T>(f: F) -> T { } /// Gets the thread-local `TDag`. Note: do not get recursively. -pub fn get_tdag_mut T>(f: F) -> T { +pub fn get_tdag_mut T>(mut f: F) -> T { EPOCH_DATA_TOP.with(|top| { let mut top = top.borrow_mut(); f(&mut top.tdag) diff --git a/starlight/src/eval.rs b/starlight/src/eval.rs index 70eba0b1..5a364115 100644 --- a/starlight/src/eval.rs +++ b/starlight/src/eval.rs @@ -1,6 +1,6 @@ -use awint::awint_dag::{triple_arena::Ptr, PState, EvalError}; +use awint::awint_dag::{triple_arena::Ptr, EvalError, PState}; -use crate::{PBack, TDag, Value}; +use crate::{PBack, Referent, TDag, Value}; impl TDag { /// This does not update the visit number @@ -12,7 +12,7 @@ impl TDag { struct DfsLvl { p_init: PBack, p_back: PBack, - p_state: Option, + p_state: Option<(PState, usize)>, found_t_node: bool, } let mut path = vec![DfsLvl { @@ -22,7 +22,31 @@ impl TDag { found_t_node: false, }]; loop { - let Some(lvl) = path.last() else { break }; + let Some(lvl) = path.last_mut() else { break }; + + // TODO + //self.backrefs.get_val_mut(lvl.p_back).unwrap().visit + + match self.backrefs.get_key(lvl.p_back).unwrap() { + Referent::ThisEquiv => (), + Referent::ThisTNode(p_tnode) => { + lvl.found_t_node = true; + let tnode = self.tnodes.get(*p_tnode).unwrap(); + path.push(DfsLvl { + p_init: tnode.p_self, + p_back: tnode.p_self, + p_state: None, + found_t_node: false, + }); + continue + } + Referent::ThisStateBit(p_state, i) => { + lvl.p_state = Some((*p_state, *i)); + } + Referent::Input(_) => (), + Referent::LoopDriver(_) => (), + Referent::Note(_) => (), + } // if the value is set in the middle, this picks it up let (referent, equiv) = self.backrefs.get(lvl.p_back).unwrap(); @@ -36,8 +60,12 @@ impl TDag { if p_next == lvl.p_init { // at this point, nothing has set a value but we may have a state to lower if !lvl.found_t_node { - if let Some(p_state) = lvl.p_state { + if let Some((p_state, i)) = lvl.p_state { self.lower_state(p_state).unwrap(); + self.lower_state_to_tnodes(p_state).unwrap(); + // reset TODO prevent infinite + lvl.p_back = lvl.p_init; + continue } } path.pop(); diff --git a/starlight/src/lazy_awi.rs b/starlight/src/lazy_awi.rs index 7fb979db..62acfaea 100644 --- a/starlight/src/lazy_awi.rs +++ b/starlight/src/lazy_awi.rs @@ -9,7 +9,7 @@ use awint::{ awint_dag::{ dag, smallvec::{smallvec, SmallVec}, - Lineage, PState, EvalError, + EvalError, Lineage, PState, }, awint_internals::forward_debug_fmt, }; diff --git a/starlight/src/lower.rs b/starlight/src/lower.rs index 0ac02e3a..be86797c 100644 --- a/starlight/src/lower.rs +++ b/starlight/src/lower.rs @@ -2,13 +2,13 @@ use std::{collections::HashMap, num::NonZeroUsize}; use awint::{ awint_dag::{ - lowering::{OpDag, PNode}, + lowering::{lower_state, LowerManagement, OpDag, PNode}, EvalError, - Op::*, + Op::{self, *}, PState, }, awint_macro_internals::triple_arena::Advancer, - Awi, + Awi, Bits, }; use crate::{Note, PBack, TDag, Value}; @@ -16,7 +16,125 @@ use crate::{Note, PBack, TDag, Value}; // TODO remove all old `OpDag` stuff impl TDag { + /// Used for forbidden meta psuedo-DSL techniques in which a single state is + /// replaced by more basic states. + pub fn graft(&mut self, p_state: PState, operands: &[PState]) -> Result<(), EvalError> { + #[cfg(debug_assertions)] + { + if (self.states[p_state].op.operands_len() + 1) != operands.len() { + return Err(EvalError::WrongNumberOfOperands) + } + for (i, op) in self.states[p_state].op.operands().iter().enumerate() { + let current_nzbw = operands[i + 1].get_nzbw(); + let current_is_opaque = operands[i + 1].get_op().is_opaque(); + if self.states[op].nzbw != current_nzbw { + return Err(EvalError::OtherString(format!( + "operand {}: a bitwidth of {:?} is trying to be grafted to a bitwidth of \ + {:?}", + i, current_nzbw, self.states[op].nzbw + ))) + } + if !current_is_opaque { + return Err(EvalError::ExpectedOpaque) + } + } + if self.states[p_state].nzbw != operands[0].get_nzbw() { + return Err(EvalError::WrongBitwidth) + } + } + + // TODO what do we do when we make multi-output things + // graft input + for i in 1..operands.len() { + let grafted = operands[i]; + let graftee = self.states.get(p_state).unwrap().op.operands()[i - 1]; + if let Some(grafted) = self.states.get_mut(grafted) { + // change the grafted `Opaque` into a `Copy` that routes to the graftee instead + // of needing to change all the operands of potentially many nodes + grafted.op = Copy([graftee]); + } else { + // dec graftee rc + } + } + + // graft output + let grafted = operands[0]; + self.states.get_mut(p_state).unwrap().op = Copy([grafted]); + // dec grafted rc? + + Ok(()) + } + pub fn lower_state(&mut self, p_state: PState) -> Result<(), EvalError> { + // TODO optimization to remove unused nodes early + //let epoch = StateEpoch::new(); + struct Tmp<'a> { + ptr: PState, + tdag: &'a mut TDag, + } + impl<'a> LowerManagement for Tmp<'a> { + fn graft(&mut self, operands: &[PState]) { + self.tdag.graft(self.ptr, operands).unwrap() + } + + fn get_nzbw(&self, p: PState) -> NonZeroUsize { + self.tdag.states.get(p).unwrap().nzbw + } + + fn get_op(&self, p: PState) -> &Op { + &self.tdag.states.get(p).unwrap().op + } + + fn get_op_mut(&mut self, p: PState) -> &mut Op { + &mut self.tdag.states.get_mut(p).unwrap().op + } + + fn lit(&self, p: PState) -> &Bits { + if let Op::Literal(ref lit) = self.tdag.states.get(p).unwrap().op { + lit + } else { + panic!() + } + } + + fn usize(&self, p: PState) -> usize { + if let Op::Literal(ref lit) = self.tdag.states.get(p).unwrap().op { + if lit.bw() != 64 { + panic!() + } + lit.to_usize() + } else { + panic!() + } + } + + fn bool(&self, p: PState) -> bool { + if let Op::Literal(ref lit) = self.tdag.states.get(p).unwrap().op { + if lit.bw() != 1 { + panic!() + } + lit.to_bool() + } else { + panic!() + } + } + + fn dec_rc(&mut self, _p: PState) { + // + } + } + let state = self.states.get(p_state).unwrap(); + let start_op = state.op.clone(); + let out_w = state.nzbw; + lower_state(p_state, start_op, out_w, Tmp { + ptr: p_state, + tdag: self, + })?; + Ok(()) + } + + pub fn lower_state_to_tnodes(&mut self, p_state: PState) -> Result<(), EvalError> { + // Ok(()) }