diff --git a/core/compiler/src/compile.rs b/core/compiler/src/compile.rs index 9f7458b..9db3f78 100644 --- a/core/compiler/src/compile.rs +++ b/core/compiler/src/compile.rs @@ -11,7 +11,7 @@ use arcstr::Substr; use enumify::enumify; use geometry::transform::{Rotation, TransformationMatrix}; use indexmap::{IndexMap, IndexSet}; -use itertools::Itertools; +use itertools::{Either, Itertools}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -1778,21 +1778,6 @@ pub enum CellArg { Seq(Vec), } -impl CellArg { - pub fn from_value(val: &Value, solver: &Solver) -> Option { - match val { - Value::Linear(v) => solver.eval_expr(v).map(CellArg::Float), - Value::Int(i) => Some(CellArg::Int(*i)), - Value::Seq(s) => s - .iter() - .map(|v| Self::from_value(v, solver)) - .collect::>>() - .map(CellArg::Seq), - _ => unreachable!(), - } - } -} - #[derive(Debug, Clone)] pub struct CompileInput<'a> { /// Full path to cell. @@ -1948,12 +1933,14 @@ struct CellState { fallback_constraints_used: Vec, unsolved_vars: Option>, constraint_span_map: IndexMap, + var_dependents: IndexMap>, } struct ExecPass<'a> { ast: &'a WorkspaceAst, cell_states: IndexMap, values: IndexMap>, + value_dependents: IndexMap>, frames: IndexMap, nil_value: ValueId, seq_nil_value: ValueId, @@ -2012,6 +1999,7 @@ impl<'a> ExecPass<'a> { (3, DeferValue::Ready(Value::Bool(false))), (4, DeferValue::Ready(Value::SeqNil)), ]), + value_dependents: IndexMap::new(), frames: IndexMap::from_iter([( 5, Frame { @@ -2187,6 +2175,7 @@ impl<'a> ExecPass<'a> { unsolved_vars: Default::default(), objects: Default::default(), constraint_span_map: IndexMap::new(), + var_dependents: IndexMap::new(), } ) .is_none() @@ -2243,19 +2232,33 @@ impl<'a> ExecPass<'a> { } } - let mut require_progress = false; - let mut progress = false; while { let state = self.cell_state(cell_id); !state.deferred.is_empty() || !state.solver.fully_solved() } { - let deferred = self.cell_state(cell_id).deferred.clone(); - progress = false; - for vid in deferred { - progress = progress || self.eval_partial(vid)?; + let mut progress = false; + while let Some(vid) = { + let state = self.cell_state_mut(cell_id); + state.deferred.pop() + } { + progress = self.eval_partial(cell_id, vid)? || progress; } - if require_progress && !progress { + let state = self.cell_state_mut(cell_id); + state.solve_iters += 1; + state.solver.solve(); + progress = !state.solver.updated_vars().is_empty() || progress; + for var in state.solver.updated_vars().clone() { + if let Some(deps) = state.var_dependents.get(&var) { + for dep in deps.clone() { + state.deferred.insert(dep); + } + } + } + let state = self.cell_state_mut(cell_id); + state.solver.clear_updated_vars(); + + if !progress { let state = self.cell_state_mut(cell_id); if state.unsolved_vars.is_none() { state.unsolved_vars = Some(state.solver.unsolved_vars().clone()); @@ -2287,22 +2290,9 @@ impl<'a> ExecPass<'a> { state.solver.force_solution(); } } - - require_progress = false; - - if !progress { - let state = self.cell_state_mut(cell_id); - state.solve_iters += 1; - state.solver.solve(); - require_progress = true; - } } let state = self.cell_state_mut(cell_id); - if progress { - state.solve_iters += 1; - state.solver.solve(); - } for constraint in state.solver.inconsistent_constraints().clone() { let span = self .cell_state(cell_id) @@ -2647,50 +2637,49 @@ impl<'a> ExecPass<'a> { .unwrap_or(self.nil_value) } + fn new_ready_value(&mut self, val: Value) -> ValueId { + let vid = self.value_id(); + self.values.insert(vid, Defer::Ready(val)); + vid + } + + // Takes in a closure so that the parent can be added to the stack first. + fn new_deferred_value( + &mut self, + loc: DynLoc, + state: impl FnOnce(&mut Self) -> PartialEvalState, + ) -> ValueId { + let vid = self.value_id(); + self.cell_state_mut(loc.cell).deferred.insert(vid); + let state = state(self); + self.values + .insert(vid, Defer::Deferred(PartialEval { state, loc })); + vid + } + fn visit_expr(&mut self, loc: DynLoc, expr: &Expr) -> ValueId { - let partial_eval_state = match expr { - Expr::Nil(_) => { - return self.nil_value; - } - Expr::SeqNil(_) => { - return self.seq_nil_value; - } - Expr::FloatLiteral(f) => { - let vid = self.value_id(); - self.values - .insert(vid, Defer::Ready(Value::Linear(LinearExpr::from(f.value)))); - return vid; - } - Expr::IntLiteral(i) => { - let vid = self.value_id(); - self.values.insert(vid, Defer::Ready(Value::Int(i.value))); - return vid; - } + match expr { + Expr::Nil(_) => self.nil_value, + Expr::SeqNil(_) => self.seq_nil_value, + Expr::FloatLiteral(f) => self.new_ready_value(Value::Linear(LinearExpr::from(f.value))), + Expr::IntLiteral(i) => self.new_ready_value(Value::Int(i.value)), Expr::BoolLiteral(b) => { - return if b.value { + if b.value { self.true_value } else { self.false_value - }; - } - Expr::StringLiteral(s) => { - let vid = self.value_id(); - self.values - .insert(vid, Defer::Ready(Value::String(s.value.to_string()))); - return vid; + } } + Expr::StringLiteral(s) => self.new_ready_value(Value::String(s.value.to_string())), Expr::IdentPath(path) => { if let Some(var_id) = path.metadata.0 { - return self.lookup(loc.frame, var_id).unwrap(); + self.lookup(loc.frame, var_id).unwrap() } else { // must be an enum value assert!(path.path.len() >= 2); - let vid = self.value_id(); - self.values.insert( - vid, - Defer::Ready(Value::EnumValue(path.path.last().unwrap().name.to_string())), - ); - return vid; + self.new_ready_value(Value::EnumValue( + path.path.last().unwrap().name.to_string(), + )) } } Expr::Emit(e) => { @@ -2701,27 +2690,29 @@ impl<'a> ExecPass<'a> { value, span, }); - return value; + value } Expr::Call(c) => { if BUILTINS.contains(&c.func.path.last().unwrap().name.as_str()) { - PartialEvalState::Call(Box::new(PartialCallExpr { - expr: c.clone(), - state: CallExprState { - posargs: c - .args - .posargs - .iter() - .map(|arg| self.visit_expr(loc, arg)) - .collect(), - kwargs: c - .args - .kwargs - .iter() - .map(|arg| self.visit_expr(loc, &arg.value)) - .collect(), - }, - })) + self.new_deferred_value(loc, |this| { + PartialEvalState::Call(Box::new(PartialCallExpr { + expr: c.clone(), + state: CallExprState { + posargs: c + .args + .posargs + .iter() + .map(|arg| this.visit_expr(loc, arg)) + .collect(), + kwargs: c + .args + .kwargs + .iter() + .map(|arg| this.visit_expr(loc, &arg.value)) + .collect(), + }, + })) + }) } else { let arg_vals = c .args @@ -2769,46 +2760,50 @@ impl<'a> ExecPass<'a> { ); let fid = self.frame_id(); self.frames.insert(fid, call_frame); - return self.visit_scope_expr_inner(loc.cell, fid, scope, &new_scope); + self.visit_scope_expr_inner(loc.cell, fid, scope, &new_scope) } - ValueRef::CellFn(_) => PartialEvalState::Call(Box::new(PartialCallExpr { - expr: c.clone(), - state: CallExprState { - posargs: arg_vals, - kwargs: c - .args - .kwargs - .iter() - .map(|arg| self.visit_expr(loc, &arg.value)) - .collect(), - }, - })), + ValueRef::CellFn(_) => self.new_deferred_value(loc, |this| { + PartialEvalState::Call(Box::new(PartialCallExpr { + expr: c.clone(), + state: CallExprState { + posargs: arg_vals, + kwargs: c + .args + .kwargs + .iter() + .map(|arg| this.visit_expr(loc, &arg.value)) + .collect(), + }, + })) + }), _ => todo!("cannot call value: not a function or cell generator"), } } } Expr::If(if_expr) => { let cond = self.visit_expr(loc, &if_expr.cond); - PartialEvalState::If(Box::new(PartialIfExpr { - expr: (**if_expr).clone(), - state: IfExprState::Cond(cond), - })) + self.new_deferred_value(loc, |_| { + PartialEvalState::If(Box::new(PartialIfExpr { + expr: (**if_expr).clone(), + state: IfExprState::Cond(cond), + })) + }) } - Expr::Match(match_expr) => { - let scrutinee = self.visit_expr(loc, &match_expr.scrutinee); + Expr::Match(match_expr) => self.new_deferred_value(loc, |this| { + let scrutinee = this.visit_expr(loc, &match_expr.scrutinee); PartialEvalState::Match(Box::new(PartialMatchExpr { expr: (**match_expr).clone(), state: MatchExprState::Scrutinee(scrutinee), })) - } - Expr::Comparison(comparison_expr) => { - let left = self.visit_expr(loc, &comparison_expr.left); - let right = self.visit_expr(loc, &comparison_expr.right); + }), + Expr::Comparison(comparison_expr) => self.new_deferred_value(loc, |this| { + let left = this.visit_expr(loc, &comparison_expr.left); + let right = this.visit_expr(loc, &comparison_expr.right); PartialEvalState::Comparison(Box::new(PartialComparisonExpr { expr: (**comparison_expr).clone(), state: ComparisonExprState { left, right }, })) - } + }), Expr::Scope(s) => { let scope = self.create_exec_scope_at_loc( loc, @@ -2819,74 +2814,112 @@ impl<'a> ExecPass<'a> { }, self.span(&loc, s.span), ); - return self.visit_scope_expr_inner(loc.cell, loc.frame, scope, s); + self.visit_scope_expr_inner(loc.cell, loc.frame, scope, s) } - Expr::FieldAccess(f) => { - let base = self.visit_expr(loc, &f.base); + Expr::FieldAccess(f) => self.new_deferred_value(loc, |this| { + let base = this.visit_expr(loc, &f.base); PartialEvalState::FieldAccess(Box::new(PartialFieldAccessExpr { expr: (**f).clone(), state: FieldAccessExprState { base }, })) - } - Expr::Index(i) => { - let base = self.visit_expr(loc, &i.base); - let index = self.visit_expr(loc, &i.index); + }), + Expr::Index(i) => self.new_deferred_value(loc, |this| { + let base = this.visit_expr(loc, &i.base); + let index = this.visit_expr(loc, &i.index); PartialEvalState::Index(Box::new(PartialIndexExpr { expr: (**i).clone(), state: IndexExprState { base, index }, })) - } - Expr::BinOp(b) => { - let lhs = self.visit_expr(loc, &b.left); - let rhs = self.visit_expr(loc, &b.right); + }), + Expr::BinOp(b) => self.new_deferred_value(loc, |this| { + let lhs = this.visit_expr(loc, &b.left); + let rhs = this.visit_expr(loc, &b.right); PartialEvalState::BinOp(PartialBinOp { lhs, rhs, op: b.op, expr: b.clone(), }) - } - Expr::UnaryOp(u) => { - let operand = self.visit_expr(loc, &u.operand); + }), + Expr::UnaryOp(u) => self.new_deferred_value(loc, |this| { + let operand = this.visit_expr(loc, &u.operand); PartialEvalState::UnaryOp(PartialUnaryOp { operand, op: u.op, expr: u.clone(), }) - } - Expr::Cast(cast) => { - let value = self.visit_expr(loc, &cast.value); + }), + Expr::Cast(cast) => self.new_deferred_value(loc, |this| { + let value = this.visit_expr(loc, &cast.value); PartialEvalState::Cast(PartialCast { value, ty: cast.metadata.clone(), }) - } - }; - let vid = self.value_id(); - self.cell_state_mut(loc.cell).deferred.insert(vid); - self.values.insert( - vid, - DeferValue::Deferred(PartialEval { - state: partial_eval_state, - loc, }), - ); - vid + } } - fn eval_partial(&mut self, vid: ValueId) -> Result { - let v = self.values.swap_remove(&vid); - if v.is_none() { - return Ok(false); + fn add_value_dependent(&mut self, vid: ValueId, dependent: ValueId) { + self.value_dependents + .entry(vid) + .or_default() + .insert(dependent); + } + + fn add_var_dependent(&mut self, cell_id: CellId, var: Var, dependent: ValueId) { + self.cell_state_mut(cell_id) + .var_dependents + .entry(var) + .or_default() + .insert(dependent); + } + + pub fn cell_arg_from_value( + &mut self, + cell_id: CellId, + dependent_vid: ValueId, + val: &Value, + ) -> Option { + match val { + Value::Linear(v) => { + if let Some(f) = self.cell_state_mut(cell_id).solver.eval_expr(v) { + Some(CellArg::Float(f)) + } else { + for (_, var) in v.coeffs.clone() { + self.add_var_dependent(cell_id, var, dependent_vid); + } + None + } + } + Value::Int(i) => Some(CellArg::Int(*i)), + Value::Seq(s) => s + .iter() + .map(|v| self.cell_arg_from_value(cell_id, dependent_vid, v)) + .collect::>>() + .map(CellArg::Seq), + _ => unreachable!(), } - let mut v = v.unwrap(); - let vref = v.as_mut(); - if vref.is_ready() { - self.values.insert(vid, v); + } + + fn eval_partial(&mut self, cell_id: CellId, vid: ValueId) -> Result { + let v = self.values.get(&vid); + if v.is_none() { return Ok(false); } - let vref = vref.unwrap_deferred(); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let vref = v.as_ref().unwrap(); + let mut vref = match &vref { + Defer::Ready(_) => { + if let Some(deps) = self.value_dependents.get(&vid) { + for dep_vid in deps.clone() { + self.cell_state_mut(cell_id).deferred.insert(dep_vid); + } + } + return Ok(true); + } + Defer::Deferred(v) => v.clone(), + }; + let cell_id = vref.loc.cell; + let state = self.cell_states.get_mut(&cell_id).unwrap(); let progress = match &mut vref.state { PartialEvalState::Call(c) => match c.expr.func.path.last().unwrap().name.as_str() { f @ "crect" | f @ "rect" => { @@ -2897,18 +2930,22 @@ impl<'a> ExecPass<'a> { .iter() .zip(c.state.kwargs.iter()) .find(|(k, _)| k.name.name == "layer") - .map(|(_, vid)| { - self.values[vid] - .as_ref() - .get_ready() - .map(|layer| layer.as_ref().unwrap_string().clone()) + .map(|(_, arg_vid)| { + if let Defer::Ready(layer) = &self.values[arg_vid] { + Some(layer.as_ref().unwrap_string().clone()) + } else { + self.add_value_dependent(*arg_vid, vid); + None + } }) } else { - c.state.posargs.first().map(|vid| { - self.values[vid] - .as_ref() - .get_ready() - .map(|layer| layer.as_ref().unwrap_string().clone()) + c.state.posargs.first().map(|arg_vid| { + if let Defer::Ready(layer) = &self.values[arg_vid] { + Some(layer.as_ref().unwrap_string().clone()) + } else { + self.add_value_dependent(*arg_vid, vid); + None + } }) }; let layer = match layer { @@ -2919,7 +2956,7 @@ impl<'a> ExecPass<'a> { if let Some(layer) = layer { let id = self.object_id(); let span = self.span(&vref.loc, c.expr.span); - let state = self.cell_state_mut(vref.loc.cell); + let state = self.cell_state_mut(cell_id); let rect = Rect { id, layer, @@ -2985,21 +3022,15 @@ impl<'a> ExecPass<'a> { x => unreachable!("unsupported kwarg `{x}`"), }; let span = self.span(&vref.loc, kwarg.span); - let defer = self.value_id(); - self.values.insert( - defer, - DeferValue::Deferred(PartialEval { - state: PartialEvalState::Constraint(PartialConstraint { - lhs, - rhs: *rhs, - fallback: kwarg.name.name.ends_with('i'), - priority, - span, - }), - loc: vref.loc, - }), - ); - self.cell_state_mut(vref.loc.cell).deferred.insert(defer); + self.new_deferred_value(vref.loc, |_| { + PartialEvalState::Constraint(PartialConstraint { + lhs, + rhs: *rhs, + fallback: kwarg.name.name.ends_with('i'), + priority, + span, + }) + }); } true } else { @@ -3007,17 +3038,19 @@ impl<'a> ExecPass<'a> { } } "text" => { - let args = c - .state - .posargs - .iter() - .map(|vid| self.values[vid].get_ready()) - .collect::>>(); - if let Some(mut args) = args { + let (mut args, unready): (Vec<_>, Vec<_>) = + c.state.posargs.iter().partition_map(|v| { + if let Defer::Ready(v) = &self.values[v] { + Either::Left(v) + } else { + Either::Right(*v) + } + }); + if unready.is_empty() { assert_eq!(args.len(), 4); let id = object_id(&mut self.next_id); let span = self.span(&vref.loc, c.expr.span); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let state = self.cell_states.get_mut(&cell_id).unwrap(); let y = args.pop().unwrap().as_ref().unwrap_linear().clone(); let x = args.pop().unwrap().as_ref().unwrap_linear().clone(); let layer = args.pop().unwrap().as_ref().unwrap_string().clone(); @@ -3039,6 +3072,9 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(Value::Nil)); true } else { + for arg_vid in unready { + self.add_value_dependent(arg_vid, vid); + } false } } @@ -3055,6 +3091,7 @@ impl<'a> ExecPass<'a> { .map(|r| r.transform(i.reflect, i.angle)), ) } else { + self.add_value_dependent(i.cell, vid); None } } @@ -3062,7 +3099,7 @@ impl<'a> ExecPass<'a> { _ => { self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3071,7 +3108,7 @@ impl<'a> ExecPass<'a> { if let Some(r) = r { if let Some(r) = r { let id = object_id(&mut self.next_id); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let state = self.cell_states.get_mut(&cell_id).unwrap(); let orect = Rect { id, layer: None, @@ -3094,11 +3131,11 @@ impl<'a> ExecPass<'a> { // default to a zero rectangle self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::EmptyBbox, }); let id = object_id(&mut self.next_id); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let state = self.cell_states.get_mut(&cell_id).unwrap(); let orect = Rect { id, layer: None, @@ -3117,6 +3154,7 @@ impl<'a> ExecPass<'a> { false } } else { + self.add_value_dependent(c.state.posargs[0], vid); false } } @@ -3146,6 +3184,8 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(Value::Nil)); true } else { + self.add_value_dependent(c.state.posargs[0], vid); + self.add_value_dependent(c.state.posargs[1], vid); false } } @@ -3167,7 +3207,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, c.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3176,23 +3216,30 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(Value::Seq(val))); true } else { + self.add_value_dependent(c.state.posargs[0], vid); + self.add_value_dependent(c.state.posargs[1], vid); false } } "list" => { - let vals = c - .state - .posargs - .iter() - .map(|v| self.values[v].get_ready()) - .collect::>>(); - if let Some(vals) = vals { + let (ready, unready): (Vec<_>, Vec<_>) = + c.state.posargs.iter().partition_map(|v| { + if let Defer::Ready(v) = &self.values[v] { + Either::Left(v) + } else { + Either::Right(*v) + } + }); + if unready.is_empty() { self.values.insert( vid, - Defer::Ready(Value::Seq(vals.iter().map(|v| (*v).clone()).collect())), + Defer::Ready(Value::Seq(ready.iter().map(|v| (*v).clone()).collect())), ); true } else { + for arg_vid in unready { + self.add_value_dependent(arg_vid, vid); + } false } } @@ -3205,7 +3252,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, c.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3214,6 +3261,7 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(val)); true } else { + self.add_value_dependent(c.state.posargs[0], vid); false } } @@ -3226,7 +3274,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, c.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3235,21 +3283,24 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(val)); true } else { + self.add_value_dependent(c.state.posargs[0], vid); false } } "dimension" => { - let args = c - .state - .posargs - .iter() - .map(|vid| self.values[vid].get_ready()) - .collect::>>(); - if let Some(mut args) = args { + let (mut args, unready): (Vec<_>, Vec<_>) = + c.state.posargs.iter().partition_map(|v| { + if let Defer::Ready(v) = &self.values[v] { + Either::Left(v) + } else { + Either::Right(*v) + } + }); + if unready.is_empty() { assert_eq!(args.len(), 7); let id = object_id(&mut self.next_id); let span = self.span(&vref.loc, c.expr.span); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let state = self.cell_states.get_mut(&cell_id).unwrap(); let horiz = *args.pop().unwrap().as_ref().unwrap_bool(); let mut arg = || args.pop().unwrap().as_ref().unwrap_linear().clone(); let (nstop, pstop, coord, value, n, p) = @@ -3278,6 +3329,9 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(Value::Nil)); true } else { + for arg_vid in unready { + self.add_value_dependent(arg_vid, vid); + } false } } @@ -3288,14 +3342,14 @@ impl<'a> ExecPass<'a> { .kwargs .iter() .zip(c.state.kwargs.iter()) - .find_map(|(kwarg, vid)| { + .find_map(|(kwarg, arg_vid)| { if kwarg.name.name == "reflect" { - Some( - self.values[vid] - .as_ref() - .get_ready() - .map(|refl| *refl.as_ref().unwrap_bool()), - ) + Some(if let Defer::Ready(refl) = &self.values[arg_vid] { + Some(*refl.as_ref().unwrap_bool()) + } else { + self.add_value_dependent(*arg_vid, vid); + None + }) } else { None } @@ -3311,11 +3365,11 @@ impl<'a> ExecPass<'a> { .kwargs .iter() .zip(c.state.kwargs.iter()) - .find_map(|(kwarg, vid)| { + .find_map(|(kwarg, arg_vid)| { if kwarg.name.name == "angle" { let span = self.span(&vref.loc, kwarg.value.span()); - Some(self.values[vid].as_ref().get_ready().map(|refl| { - match ((*refl.as_ref().unwrap_int() % 360) + 360) % 360 { + Some(if let Defer::Ready(refl) = &self.values[arg_vid] { + Some(match ((*refl.as_ref().unwrap_int() % 360) + 360) % 360 { 0 => Rotation::R0, 90 => Rotation::R90, 180 => Rotation::R180, @@ -3323,13 +3377,16 @@ impl<'a> ExecPass<'a> { _ => { self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidRotation, }); Rotation::R0 } - } - })) + }) + } else { + self.add_value_dependent(*arg_vid, vid); + None + }) } else { None } @@ -3345,14 +3402,14 @@ impl<'a> ExecPass<'a> { .kwargs .iter() .zip(c.state.kwargs.iter()) - .find_map(|(kwarg, vid)| { + .find_map(|(kwarg, arg_vid)| { if kwarg.name.name == "construction" { - Some( - self.values[vid] - .as_ref() - .get_ready() - .map(|v| *v.as_ref().unwrap_bool()), - ) + Some(if let Defer::Ready(v) = &self.values[arg_vid] { + Some(*v.as_ref().unwrap_bool()) + } else { + self.add_value_dependent(*arg_vid, vid); + None + }) } else { None } @@ -3367,7 +3424,7 @@ impl<'a> ExecPass<'a> { { let id = object_id(&mut self.next_id); let span = self.span(&vref.loc, c.expr.span); - let state = self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let state = self.cell_states.get_mut(&cell_id).unwrap(); let inst = Instance { id, x: state.solver.new_var().into(), @@ -3400,21 +3457,15 @@ impl<'a> ExecPass<'a> { _ => continue, }; let span = self.span(&vref.loc, kwarg.span); - let defer = self.value_id(); - self.values.insert( - defer, - DeferValue::Deferred(PartialEval { - state: PartialEvalState::Constraint(PartialConstraint { - lhs, - rhs: *rhs, - fallback: kwarg.name.name.ends_with('i'), - priority, - span, - }), - loc: vref.loc, - }), - ); - self.cell_state_mut(vref.loc.cell).deferred.insert(defer); + self.new_deferred_value(vref.loc, |_| { + PartialEvalState::Constraint(PartialConstraint { + lhs, + rhs: *rhs, + fallback: kwarg.name.name.ends_with('i'), + priority, + span, + }) + }); } self.values.insert(vid, Defer::Ready(Value::Inst(inst))); true @@ -3425,17 +3476,19 @@ impl<'a> ExecPass<'a> { _ => { // Must be calling a cell generator. // User functions are never deferred. - let arg_vals = c - .state - .posargs - .iter() - .map(|v| { - self.values[v] - .get_ready() - .and_then(|v| CellArg::from_value(v, &state.solver)) - }) - .collect::>>(); - if let Some(arg_vals) = arg_vals { + let (arg_vals, unready): (Vec<_>, Vec<_>) = + c.state.posargs.iter().partition_map(|arg_vid| { + if let Defer::Ready(v) = self.values[arg_vid].clone() { + if let Some(arg) = self.cell_arg_from_value(cell_id, *arg_vid, &v) { + Either::Left(arg) + } else { + Either::Right(*arg_vid) + } + } else { + Either::Right(*arg_vid) + } + }); + if unready.is_empty() { let cell = self.execute_cell( c.expr.metadata.0.unwrap(), arg_vals, @@ -3447,6 +3500,9 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(Value::Cell(cell))); true } else { + for arg_vid in unready { + self.add_value_dependent(arg_vid, vid); + } false } } @@ -3461,15 +3517,33 @@ impl<'a> ExecPass<'a> { BinOp::Add => Some(vl.clone() + vr.clone()), BinOp::Sub => Some(vl.clone() - vr.clone()), BinOp::Mul => { - match (state.solver.eval_expr(vl), state.solver.eval_expr(vr)) { + let res = match ( + state.solver.eval_expr(vl), + state.solver.eval_expr(vr), + ) { (Some(vl), Some(vr)) => Some((vl * vr).into()), (Some(vl), None) => Some(vr.clone() * vl), (None, Some(vr)) => Some(vl.clone() * vr), (None, None) => None, + }; + if res.is_none() { + for (_, var) in + vl.coeffs.clone().into_iter().chain(vr.coeffs.clone()) + { + self.add_var_dependent(cell_id, var, vid); + } } + res } BinOp::Div => { - state.solver.eval_expr(vr).map(|rhs| vl.clone() / rhs) + let res = + state.solver.eval_expr(vr).map(|rhs| vl.clone() / rhs); + if res.is_none() { + for (_, var) in vr.coeffs.clone() { + self.add_var_dependent(cell_id, var, vid); + } + } + res } }; if let Some(res) = res { @@ -3494,13 +3568,15 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, bin_op.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); } } } else { + self.add_value_dependent(bin_op.lhs, vid); + self.add_value_dependent(bin_op.rhs, vid); false } } @@ -3521,7 +3597,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, unary_op.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3538,7 +3614,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, unary_op.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3550,6 +3626,7 @@ impl<'a> ExecPass<'a> { _ => todo!(), } } else { + self.add_value_dependent(unary_op.operand, vid); false } } @@ -3570,7 +3647,7 @@ impl<'a> ExecPass<'a> { self.span(&vref.loc, if_.expr.then.span), ); let then = self.visit_scope_expr_inner( - vref.loc.cell, + cell_id, vref.loc.frame, scope, &if_.expr.then, @@ -3590,15 +3667,18 @@ impl<'a> ExecPass<'a> { self.span(&vref.loc, if_.expr.else_.span), ); let else_ = self.visit_scope_expr_inner( - vref.loc.cell, + cell_id, vref.loc.frame, scope, &if_.expr.else_, ); if_.state = IfExprState::Else(else_); } + self.values.insert(vid, Defer::Deferred(vref)); + self.cell_state_mut(cell_id).deferred.insert(vid); true } else { + self.add_value_dependent(cond, vid); false } } @@ -3607,6 +3687,7 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(val.clone())); true } else { + self.add_value_dependent(then, vid); false } } @@ -3615,6 +3696,7 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(val.clone())); true } else { + self.add_value_dependent(else_, vid); false } } @@ -3631,8 +3713,11 @@ impl<'a> ExecPass<'a> { .unwrap(); let value = self.visit_expr(vref.loc, &arm.expr); match_.state = MatchExprState::Value(value); + self.values.insert(vid, Defer::Deferred(vref)); + self.cell_state_mut(cell_id).deferred.insert(vid); true } else { + self.add_value_dependent(scrutinee, vid); false } } @@ -3641,6 +3726,7 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, Defer::Ready(val.clone())); true } else { + self.add_value_dependent(value, vid); false } } @@ -3670,6 +3756,11 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, DeferValue::Ready(Value::Bool(res))); true } else { + for (_, var) in + vl.coeffs.clone().into_iter().chain(vr.coeffs.clone()) + { + self.add_var_dependent(cell_id, var, vid); + } false } } @@ -3724,6 +3815,8 @@ impl<'a> ExecPass<'a> { _ => unreachable!(), } } else { + self.add_value_dependent(comparison_expr.state.left, vid); + self.add_value_dependent(comparison_expr.state.right, vid); false } } @@ -3746,7 +3839,7 @@ impl<'a> ExecPass<'a> { self.span(&vref.loc, field_access_expr.expr.span); self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidRotation, }); Value::String("".to_string()) @@ -3756,7 +3849,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, field_access_expr.expr.span); self.errors.push(ExecError { span: Some(span.clone()), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3771,13 +3864,12 @@ impl<'a> ExecPass<'a> { "y" => Some(Value::Linear(inst.y.clone())), field => { if let Defer::Ready(cell) = &self.values[&inst.cell] { - let cell_id = *cell.as_ref().unwrap_cell(); + let inst_cell_id = *cell.as_ref().unwrap_cell(); // When a cell is ready, it must have been fully // solved/compiled, and therefore it will be in the // compiled cell map. - let cell = &self.compiled_cells[&cell_id]; - let state = - self.cell_states.get_mut(&vref.loc.cell).unwrap(); + let cell = &self.compiled_cells[&inst_cell_id]; + let state = self.cell_states.get_mut(&cell_id).unwrap(); let obj_id = &mut self.next_id; Some(Value::from_array(cell.field(field).unwrap().map( &mut move |v| match v { @@ -3850,6 +3942,7 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, DeferValue::Ready(val)); true } else { + self.add_value_dependent(inst.cell, vid); false } } @@ -3857,13 +3950,14 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, field_access_expr.expr.span); self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); } } } else { + self.add_value_dependent(field_access_expr.state.base, vid); false } } @@ -3880,7 +3974,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, index_expr.expr.span); self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::IndexOutOfBounds, }); return Err(()); @@ -3889,7 +3983,7 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, index_expr.expr.index.span()); self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); @@ -3898,12 +3992,14 @@ impl<'a> ExecPass<'a> { let span = self.span(&vref.loc, index_expr.expr.base.span()); self.errors.push(ExecError { span: Some(span), - cell: vref.loc.cell, + cell: cell_id, kind: ExecErrorKind::InvalidType, }); return Err(()); } } else { + self.add_value_dependent(index_expr.state.base, vid); + self.add_value_dependent(index_expr.state.index, vid); false } } @@ -3927,6 +4023,8 @@ impl<'a> ExecPass<'a> { self.values.insert(vid, DeferValue::Ready(Value::Nil)); true } else { + self.add_value_dependent(c.lhs, vid); + self.add_value_dependent(c.rhs, vid); false } } @@ -3937,10 +4035,18 @@ impl<'a> ExecPass<'a> { Some(Value::Linear(LinearExpr::from(*x as f64))) } (x @ Value::Int(_), Ty::Int) => Some(x.clone()), - (Value::Linear(expr), Ty::Int) => state - .solver - .eval_expr(expr) - .map(|val| Value::Int(val as i64)), + (Value::Linear(expr), Ty::Int) => { + let res = state + .solver + .eval_expr(expr) + .map(|val| Value::Int(val as i64)); + if res.is_none() { + for (_, var) in expr.coeffs.clone() { + self.add_var_dependent(cell_id, var, vid); + } + } + res + } (expr @ Value::Linear(_), Ty::Float) => Some(expr.clone()), _ => unreachable!("invalid cast"), }; @@ -3951,15 +4057,18 @@ impl<'a> ExecPass<'a> { false } } else { + self.add_value_dependent(c.value, vid); false } } }; - let cell_id = vref.loc.cell; - self.values.entry(vid).or_insert(v); - if self.values[&vid].is_ready() { - self.cell_state_mut(cell_id).deferred.swap_remove(&vid); + if self.values[&vid].is_ready() + && let Some(deps) = self.value_dependents.get(&vid) + { + for dep_vid in deps.clone() { + self.cell_state_mut(cell_id).deferred.insert(dep_vid); + } } Ok(progress) } diff --git a/core/compiler/src/solver.rs b/core/compiler/src/solver.rs index 691e3ec..d68e58c 100644 --- a/core/compiler/src/solver.rs +++ b/core/compiler/src/solver.rs @@ -20,6 +20,7 @@ pub struct Solver { // Solved and unsolved vars are separate to reduce overhead of many solved variables. solved_vars: IndexMap, unsolved_vars: IndexSet, + updated_vars: IndexSet, back_substitute_stack: Vec, inconsistent_constraints: IndexSet, invalid_rounding: IndexSet, @@ -60,6 +61,16 @@ impl Solver { &self.inconsistent_constraints } + #[inline] + pub fn updated_vars(&self) -> &IndexSet { + &self.updated_vars + } + + #[inline] + pub fn clear_updated_vars(&mut self) { + self.updated_vars.clear() + } + #[inline] pub fn invalid_rounding(&self) -> &IndexSet { &self.invalid_rounding @@ -70,7 +81,10 @@ impl Solver { } pub fn solve_var(&mut self, var: Var, val: f64) { - self.solved_vars.insert(var, val); + let old = self.solved_vars.insert(var, val); + if old.is_none() { + self.updated_vars.insert(var); + } self.unsolved_vars.swap_remove(&var); } @@ -101,7 +115,9 @@ impl Solver { && let Some(constraint) = self.constraints.get_mut(&id) { constraint.simplify(&self.solved_vars); - if constraint.coeffs.is_empty() && !relative_eq!(constraint.constant, 0.) { + if constraint.coeffs.is_empty() + && !relative_eq!(constraint.constant, 0., epsilon = EPSILON) + { self.inconsistent_constraints.insert(id); self.constraints.swap_remove(&id); return; @@ -167,7 +183,6 @@ impl Solver { self.constraints.len(), self.constraints.values().map(|c| -c.constant), ); - let svd = a.clone().svd(true, true); let vt = svd.v_t.as_ref().expect("No V^T matrix"); let r = svd.rank(EPSILON); @@ -181,7 +196,12 @@ impl Solver { let i = unsolved_vars.get_index_of(var).unwrap(); let recons = (vt_recons.transpose() * vt_recons.column(i))[(i, 0)]; if relative_eq!(recons, 1., epsilon = EPSILON) { - self.solve_var(*var, sol[(i, 0)]); + let val = sol[(i, 0)]; + let rounded_val = round(val); + if relative_ne!(val, rounded_val, epsilon = EPSILON) { + self.invalid_rounding.insert(*var); + } + self.solve_var(*var, rounded_val); } } for (id, constraint) in self.constraints.iter_mut() { @@ -192,16 +212,6 @@ impl Solver { self.inconsistent_constraints.insert(*id); } } - for i in 0..self.next_var { - if let Some(val) = self.solved_vars.get_mut(&Var(i)) { - let rounded_val = round(*val); - if relative_ne!(*val, rounded_val, epsilon = EPSILON) { - self.invalid_rounding.insert(Var(i)); - } else { - *val = rounded_val; - } - } - } self.constraints .retain(|_, constraint| !constraint.coeffs.is_empty()); } diff --git a/examples/sky130_inverter/Argon.toml b/examples/sky130_inverter/Argon.toml deleted file mode 100644 index bc1ab4f..0000000 --- a/examples/sky130_inverter/Argon.toml +++ /dev/null @@ -1,4 +0,0 @@ -lyp = "../../../../pdks/sky130/sky130.lyp" - -[mods] -sky130 = "../../../../pdks/sky130" diff --git a/examples/sky130_inverter/lib.ar b/examples/sky130_inverter/lib.ar deleted file mode 100644 index 57c079d..0000000 --- a/examples/sky130_inverter/lib.ar +++ /dev/null @@ -1,72 +0,0 @@ -cell inverter(nw: Float, pw: Float) { - let ndiff = rect("diff.drawing", x0=0., y0=0., y1=nw); - let poly = rect("poly.drawing", y0=ndiff.y0-130.); - eq(poly.x0 + poly.x1, ndiff.x0 + ndiff.x1); - eq(poly.x1 - poly.x0, 150.); - eq(ndiff.x0, poly.x0 - 55. - 170. - 130.); - eq(ndiff.x1, poly.x1 + 55. + 170. + 130.); - let nsdm = rect("nsdm.drawing", x0=ndiff.x0-130., x1=ndiff.x1+130., y0=ndiff.y0-130., y1=ndiff.y1+130.); - let vss_s = rect("li1.drawing", x1=poly.x0-55.); - eq(vss_s.x1 - vss_s.x0, 170.); - eq(vss_s.y1, ndiff.y1 + 100.); - - let vss_ptap = rect("li1.drawing"); - eq(vss_ptap.x1 - vss_ptap.x0, 800.); - eq(vss_ptap.y1 - vss_ptap.y0, 800.); - let ptap = rect("tap.drawing", x0=vss_ptap.x0-40., x1=vss_ptap.x1+40., y0=vss_ptap.y0-65., y1=vss_ptap.y1+65.); - let psdm = rect("psdm.drawing", x0=ptap.x0-130., x1=ptap.x1+130., y0=ptap.y0-130., y1=ptap.y1+130.); - eq(nsdm.y0 - psdm.y1, 20.); - eq(nsdm.x0+nsdm.x1, psdm.x0+psdm.x1); - eq(vss_s.y0, vss_ptap.y0); - - let pdiff = rect("diff.drawing", x0=ndiff.x0, x1=ndiff.x1); - eq(pdiff.y1 - pdiff.y0, pw); - eq(poly.y1, pdiff.y1 + 130.); - let psdm = rect("psdm.drawing", x0=pdiff.x0-130., x1=pdiff.x1+130., y0=pdiff.y0-130., y1=pdiff.y1+130.); - eq(psdm.y0, nsdm.y1 + 170.+350.+170.+60.); - let vdd_s = rect("li1.drawing", x1=poly.x0-55.); - eq(vdd_s.x1 - vdd_s.x0, 170.); - eq(vdd_s.y0, pdiff.y0 - 100.); - - let vdd_ntap = rect("li1.drawing"); - eq(vdd_ntap.x1 - vdd_ntap.x0, 800.); - eq(vdd_ntap.y1 - vdd_ntap.y0, 800.); - let ntap = rect("tap.drawing", x0=vdd_ntap.x0-40., x1=vdd_ntap.x1+40., y0=vdd_ntap.y0-65., y1=vdd_ntap.y1+65.); - let nsdm = rect("nsdm.drawing", x0=ntap.x0-130., x1=ntap.x1+130., y0=ntap.y0-130., y1=ntap.y1+130.); - eq(nsdm.y0 - psdm.y1, 20.); - eq(nsdm.x0+nsdm.x1, psdm.x0+psdm.x1); - eq(vdd_s.y1, vdd_ntap.y1); - - let vout = rect("li1.drawing", x0=poly.x1+55., y0=ndiff.y0-100., y1=pdiff.y1+100.); - eq(vout.x1 - vout.x0, 170.); - - let poly_gcon = rect("poly.drawing", x1=poly.x1); - eq(poly_gcon.y1 - poly_gcon.y0, 350.); - eq(poly_gcon.x1 - poly_gcon.x0, 430.); - eq(poly_gcon.y0 + poly_gcon.y1, vss_s.y1 + vdd_s.y0); - - let licon_gate = rect("licon1.drawing", x0=vss_s.x0, x1=vss_s.x1); - eq(licon_gate.y1 - licon_gate.y0, 170.); - eq(licon_gate.y0 + licon_gate.y1, poly_gcon.y0 + poly_gcon.y1); - rect("npc.drawing", x0=licon_gate.x0-100., x1=licon_gate.x1+100., y0=licon_gate.y0-100., y1=licon_gate.y1+100.); - let vin = rect("li1.drawing", x0=licon_gate.x0, x1=licon_gate.x1); - eq(vin.y1 - vin.y0, 380.); - eq(vin.y0 + vin.y1, licon_gate.y0 + licon_gate.y1); - - let nwell = rect("nwell.drawing", x0=ntap.x0-180., x1=ntap.x1+180., y0=pdiff.y0-180., y1=ntap.y1+180.); - - let licon = crect(layer="licon1.drawing", x0=0., x1=170., y0=0., y1=170.); - let cons = crect(x0=vdd_s.x0, x1=vdd_s.x1, y0=pdiff.y0+40., y1=pdiff.y1-40.); - #scope1 std::center_rects(cons, #scope0 std::max_array(licon, cons.w, cons.h, 340., 340.)); - let cons = crect(x0=vout.x0, x1=vout.x1, y0=pdiff.y0+40., y1=pdiff.y1-40.); - #scope3 std::center_rects(cons, #scope2 std::max_array(licon, cons.w, cons.h, 340., 340.)); - let cons = crect(x0=vout.x0, x1=vout.x1, y0=ndiff.y0+40., y1=ndiff.y1-40.); - #scope5 std::center_rects(cons, #scope4 std::max_array(licon, cons.w, cons.h, 340., 340.)); - let cons = crect(x0=vss_s.x0, x1=vss_s.x1, y0=ndiff.y0+40., y1=ndiff.y1-40.); - #scope7 std::center_rects(cons, #scope6 std::max_array(licon, cons.w, cons.h, 340., 340.)); - let cons = crect(x0=vss_ptap.x0, x1=vss_ptap.x1, y0=vss_ptap.y0+80., y1=vss_ptap.y1-80.); - #scope9 std::center_rects(cons, #scope8 std::max_array(licon, cons.w, cons.h, 340., 340.)); - let cons = crect(x0=vdd_ntap.x0, x1=vdd_ntap.x1, y0=vdd_ntap.y0+80., y1=vdd_ntap.y1-80.); - let r = #scope10 std::max_array(licon, cons.w, cons.h, 340., 340.); - #scope11 std::center_rects(r, cons); -}