diff --git a/src/autorouter/anterouter.rs b/src/autorouter/anterouter.rs index 9893666..ccced61 100644 --- a/src/autorouter/anterouter.rs +++ b/src/autorouter/anterouter.rs @@ -11,17 +11,18 @@ use specctra_core::mesadata::AccessMesadata; use crate::{ autorouter::{ratline::RatlineIndex, Autorouter}, + board::edit::BoardEdit, drawing::{ dot::FixedDotIndex, graph::{GetMaybeNet, MakePrimitiveRef}, primitive::MakePrimitiveShape, }, - geometry::GetLayer, + geometry::{GenericNode, GetLayer}, graph::{GenericIndex, GetIndex, MakeRef}, layout::{ poly::{MakePolygon, PolyWeight}, via::ViaWeight, - CompoundWeight, LayoutEdit, + CompoundWeight, }, math::Circle, }; @@ -53,15 +54,23 @@ impl Anterouter { let endpoint_indices = ratline.ref_(autorouter).endpoint_indices(); let endpoint_dots = ratline.ref_(autorouter).endpoint_dots(); + autorouter + .ratsnest + .assign_layer_to_ratline(*ratline, *layer); + if let Some(terminating_scheme) = self .plan .ratline_endpoint_dot_to_terminating_scheme .get(&endpoint_dots.0) { match terminating_scheme { - TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter - .ratsnest - .assign_terminating_dot_to_ratvertex(endpoint_indices.0, *terminating_dot), + TerminatingScheme::ExistingFixedDot(terminating_dot) => { + autorouter.ratsnest.assign_terminating_dot_to_ratvertex( + endpoint_indices.0, + *layer, + *terminating_dot, + ) + } TerminatingScheme::Anteroute(pin_bbox_to_anchor) => self .anteroute_dot_to_anchor( autorouter, @@ -79,9 +88,13 @@ impl Anterouter { .get(&endpoint_dots.1) { match terminating_scheme { - TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter - .ratsnest - .assign_terminating_dot_to_ratvertex(endpoint_indices.1, *terminating_dot), + TerminatingScheme::ExistingFixedDot(terminating_dot) => { + autorouter.ratsnest.assign_terminating_dot_to_ratvertex( + endpoint_indices.1, + *layer, + *terminating_dot, + ) + } TerminatingScheme::Anteroute(pin_bbox_to_anchor) => self .anteroute_dot_to_anchor( autorouter, @@ -170,10 +183,10 @@ impl Anterouter { //let via_bbox_to_anchor = [-pin_bbox_to_anchor[0], -pin_bbox_to_anchor[1]]; - let mut layout_edit = LayoutEdit::new(); + let mut board_edit = BoardEdit::new(); - if let Ok((.., dots)) = autorouter.board.layout_mut().add_via( - &mut layout_edit, + if let Ok((.., dots)) = autorouter.board.add_via( + &mut board_edit, ViaWeight { from_layer: std::cmp::min(pin_layer, to_layer), to_layer: std::cmp::max(pin_layer, to_layer), @@ -183,6 +196,10 @@ impl Anterouter { }, maybe_net: pin_maybe_net, }, + autorouter + .board() + .node_pinname(&GenericNode::Primitive(dot.into())) + .cloned(), ) { let terminating_dot = dots .iter() @@ -193,9 +210,11 @@ impl Anterouter { .layer() }) .unwrap(); - autorouter - .ratsnest - .assign_terminating_dot_to_ratvertex(ratvertex, *terminating_dot); + autorouter.ratsnest.assign_terminating_dot_to_ratvertex( + ratvertex, + to_layer, + *terminating_dot, + ); } /*let bbox = if let Some(poly) = autorouter.board().layout().drawing().geometry().compounds(dot).find(|(_, compound_weight)| { matches!(compound_weight, CompoundWeight::Poly(..)) diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 55e76a1..8bfe03d 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -7,12 +7,12 @@ use geo::Point; use petgraph::graph::NodeIndex; use serde::{Deserialize, Serialize}; use spade::InsertionError; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeSet; use thiserror::Error; use crate::{ autorouter::{ - anterouter::AnterouterPlan, multilayer_autoroute::MultilayerAutorouteExecutionStepper, + multilayer_autoroute::MultilayerAutorouteExecutionStepper, permutator::PlanarAutorouteExecutionPermutator, planner::Planner, }, board::{AccessMesadata, Board}, @@ -213,22 +213,22 @@ impl Autorouter { active_layer, allowed_edges, ratlines.into_iter().filter_map(|ratline| { - let (source, target) = ratline.ref_(self).terminating_dots(); + let (origin, destination) = ratline.ref_(self).terminating_dots(); if navmesh .as_ref() - .node_data(&NavmeshIndex::Primal(source)) + .node_data(&NavmeshIndex::Primal(origin)) .is_none() || navmesh .as_ref() - .node_data(&NavmeshIndex::Primal(target)) + .node_data(&NavmeshIndex::Primal(destination)) .is_none() { // e.g. due to wrong active layer return None; } - if self.board.band_between_nodes(source, target).is_some() { + if self.board.band_between_nodes(origin, destination).is_some() { // already connected return None; } @@ -236,8 +236,8 @@ impl Autorouter { got_any_valid_goals = true; Some(ng::Goal { - source, - target, + source: origin, + target: destination, width, }) }), diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index 741a699..7e1273c 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -86,7 +86,7 @@ impl ExecutionStepper { for (ep, band) in &autoroute.last_bands { let (source, target) = ep.end_points.into(); autorouter.board.try_set_band_between_nodes( - &mut autoroute.last_recorder.data_edit, + &mut autoroute.last_recorder.board_data_edit, source, target, *band, diff --git a/src/autorouter/planar_autoroute.rs b/src/autorouter/planar_autoroute.rs index 64a26fa..113a578 100644 --- a/src/autorouter/planar_autoroute.rs +++ b/src/autorouter/planar_autoroute.rs @@ -207,7 +207,7 @@ impl Step, Option, PlanarAutorouteCo self.curr_ratline_index += 1; if let Some(new_ratline) = self.ratlines.get(self.curr_ratline_index) { - let (source, target) = new_ratline.ref_(autorouter).terminating_dots(); + let (origin, destination) = new_ratline.ref_(autorouter).terminating_dots(); let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options); @@ -216,8 +216,8 @@ impl Step, Option, PlanarAutorouteCo self.route = Some(router.route( recorder, - source, - target, + origin, + destination, self.options.router_options.routed_band_width, )?); } diff --git a/src/autorouter/planner.rs b/src/autorouter/planner.rs index 3430a3e..9aef925 100644 --- a/src/autorouter/planner.rs +++ b/src/autorouter/planner.rs @@ -99,7 +99,7 @@ impl Planner { None } }) - .map_or(TerminatingScheme::Anteroute([-1.0, -1.0]), |dot| { + .map_or(TerminatingScheme::Anteroute([-2.0, 0.0]), |dot| { TerminatingScheme::ExistingFixedDot(dot) }), ) diff --git a/src/autorouter/ratline.rs b/src/autorouter/ratline.rs index 9bb9f02..623d29c 100644 --- a/src/autorouter/ratline.rs +++ b/src/autorouter/ratline.rs @@ -12,7 +12,7 @@ use crate::{ dot::FixedDotIndex, graph::{GetMaybeNet, MakePrimitiveRef, PrimitiveIndex}, }, - geometry::{shape::MeasureLength, GetLayer}, + geometry::shape::MeasureLength, graph::MakeRef, triangulation::GetTrianvertexNodeIndex, }; @@ -23,6 +23,7 @@ pub type RatlineIndex = EdgeIndex; #[derive(Debug, Default, Clone, Copy)] pub struct RatlineWeight { + pub layer: usize, pub band_termseg: Option, } @@ -102,7 +103,9 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { .graph() .node_weight(source) .unwrap() - .maybe_terminating_dot + .layer_terminating_dots + .get(&self.layer()) + .copied() .unwrap_or(self.endpoint_dots().0); let target_dot = self .autorouter @@ -110,17 +113,25 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { .graph() .node_weight(target) .unwrap() - .maybe_terminating_dot + .layer_terminating_dots + .get(&self.layer()) + .copied() .unwrap_or(self.endpoint_dots().1); (source_dot, target_dot) } pub fn layer(&self) -> usize { - self.endpoint_dots() - .0 - .primitive_ref(self.autorouter.board().layout().drawing()) - .layer() + self.autorouter + .ratsnest() + .graph() + .edge_weight(self.index) + .unwrap() + .layer + /*self.endpoint_dots() + .0 + .primitive_ref(self.autorouter.board().layout().drawing()) + .layer()*/ } pub fn net(&self) -> usize { diff --git a/src/autorouter/ratsnest.rs b/src/autorouter/ratsnest.rs index a285c0c..1fd2659 100644 --- a/src/autorouter/ratsnest.rs +++ b/src/autorouter/ratsnest.rs @@ -48,11 +48,11 @@ impl From for crate::layout::NodeIndex { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct RatvertexWeight { vertex: RatvertexNodeIndex, pub pos: Point, - pub maybe_terminating_dot: Option, + pub layer_terminating_dots: BTreeMap, } impl GetTrianvertexNodeIndex for RatvertexWeight { @@ -118,11 +118,11 @@ impl Ratsnest { let mut triangulations = BTreeMap::new(); - this.add_layer_to_ratsnest(board, &mut triangulations, principal_layer); + this.add_layer_to_ratsnest_triangulations(board, &mut triangulations, principal_layer); for layer in 0..board.layout().drawing().layer_count() { if layer != principal_layer { - this.add_layer_to_ratsnest(board, &mut triangulations, layer); + this.add_layer_to_ratsnest_triangulations(board, &mut triangulations, layer); } } @@ -158,7 +158,7 @@ impl Ratsnest { Ok(this) } - fn add_layer_to_ratsnest( + fn add_layer_to_ratsnest_triangulations( &mut self, board: &Board, triangulations: &mut BTreeMap< @@ -190,7 +190,7 @@ impl Ratsnest { triangulation.add_vertex(RatvertexWeight { vertex, pos, - maybe_terminating_dot: None, + layer_terminating_dots: BTreeMap::new(), })?; Ok(()) }; @@ -229,12 +229,18 @@ impl Ratsnest { pub fn assign_terminating_dot_to_ratvertex( &mut self, node_index: NodeIndex, + layer: usize, terminating_dot: FixedDotIndex, ) { self.graph .node_weight_mut(node_index) .unwrap() - .maybe_terminating_dot = Some(terminating_dot) + .layer_terminating_dots + .insert(layer, terminating_dot); + } + + pub fn assign_layer_to_ratline(&mut self, ratline: RatlineIndex, layer: usize) { + self.graph.edge_weight_mut(ratline).unwrap().layer = layer; } pub fn assign_band_termseg_to_ratline( diff --git a/src/board/edit.rs b/src/board/edit.rs index 0c6c227..af12b00 100644 --- a/src/board/edit.rs +++ b/src/board/edit.rs @@ -29,7 +29,7 @@ impl Edit for BoardDataEdit { #[derive(Debug, Clone, Default)] pub struct BoardEdit { - pub data_edit: BoardDataEdit, + pub board_data_edit: BoardDataEdit, pub layout_edit: LayoutEdit, } @@ -40,7 +40,7 @@ impl BoardEdit { pub fn new_from_edits(data_edit: BoardDataEdit, layout_edit: LayoutEdit) -> Self { Self { - data_edit, + board_data_edit: data_edit, layout_edit, } } @@ -48,12 +48,12 @@ impl BoardEdit { impl Edit for BoardEdit { fn reverse_inplace(&mut self) { - self.data_edit.reverse_inplace(); + self.board_data_edit.reverse_inplace(); self.layout_edit.reverse_inplace(); } fn merge(&mut self, edit: Self) { - self.data_edit.merge(edit.data_edit); + self.board_data_edit.merge(edit.board_data_edit); self.layout_edit.merge(edit.layout_edit); } } diff --git a/src/board/mod.rs b/src/board/mod.rs index 77d17f1..23e27b8 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -21,11 +21,11 @@ use crate::{ dot::{FixedDotIndex, FixedDotWeight}, graph::PrimitiveIndex, seg::{FixedSegIndex, FixedSegWeight}, - DrawingException, + DrawingException, Infringement, }, geometry::{edit::ApplyGeometryEdit, GenericNode, GetLayer}, graph::{GenericIndex, MakeRef}, - layout::{poly::PolyWeight, CompoundWeight, Layout, NodeIndex}, + layout::{poly::PolyWeight, via::ViaWeight, CompoundWeight, Layout, NodeIndex}, router::ng::EtchedPath, }; @@ -105,6 +105,24 @@ impl Board { } impl Board { + pub fn add_via( + &mut self, + recorder: &mut BoardEdit, + weight: ViaWeight, + maybe_pin: Option, + ) -> Result<(GenericIndex, Vec), Infringement> { + let (weight, dots) = self.layout.add_via(&mut recorder.layout_edit, weight)?; + + if let Some(pin) = maybe_pin { + for dot in dots.clone() { + self.pinname_nodes + .insert(pin.clone(), GenericNode::Primitive(dot.into())); + } + } + + Ok((weight, dots)) + } + /// Adds a new fixed dot with an optional pin name. /// /// Inserts the dot into the layout and, if a pin name is provided, maps it to the created dot's node. @@ -295,7 +313,7 @@ impl Board { } recorder - .data_edit + .board_data_edit .bands .insert(bandname, (maybe_band, None)); @@ -328,7 +346,7 @@ impl Board { } pub fn apply_edit(&mut self, edit: &BoardEdit) { - for (bandname, (maybe_old_band_uid, ..)) in &edit.data_edit.bands { + for (bandname, (maybe_old_band_uid, ..)) in &edit.board_data_edit.bands { if maybe_old_band_uid.is_some() { self.band_bandname.remove_by_right(bandname); } @@ -336,7 +354,7 @@ impl Board { self.layout_mut().apply(&edit.layout_edit); - for (bandname, (.., maybe_new_band_uid)) in &edit.data_edit.bands { + for (bandname, (.., maybe_new_band_uid)) in &edit.board_data_edit.bands { if let Some(band_uid) = maybe_new_band_uid { self.band_bandname.insert(*band_uid, bandname.clone()); } diff --git a/src/geometry/geometry.rs b/src/geometry/geometry.rs index 36fcfe1..176b455 100644 --- a/src/geometry/geometry.rs +++ b/src/geometry/geometry.rs @@ -308,7 +308,7 @@ impl< pub fn remove_primitive(&mut self, primitive: PI) { let maybe_removed = self.graph.remove_node(primitive.index().into()); - debug_assert!(maybe_removed.is_some()); + assert!(maybe_removed.is_some()); } pub fn move_dot(&mut self, dot: DI, to: Point) { @@ -356,7 +356,7 @@ impl< .find(|edge| matches!(edge.weight(), GeometryLabel::Outer)) { let maybe_removed = self.graph.remove_edge(old_inner_edge.id()); - debug_assert!(maybe_removed.is_some()); + assert!(maybe_removed.is_some()); } if let Some(new_inner) = maybe_new_inner { @@ -656,7 +656,7 @@ impl, DW, SW, BW, CW: Clone, Cel: Copy, PI: Copy, D fn remove_compound(&mut self, compound: GenericIndex) { let maybe_removed = self.graph.remove_node(compound.index().into()); - debug_assert!(maybe_removed.is_some()); + assert!(maybe_removed.is_some()); } fn add_to_compound(&mut self, primitive: I, entry_label: Cel, compound: GenericIndex) diff --git a/src/router/prenavmesh.rs b/src/router/prenavmesh.rs index 5b07ad7..eaccc4e 100644 --- a/src/router/prenavmesh.rs +++ b/src/router/prenavmesh.rs @@ -192,6 +192,8 @@ impl Prenavmesh { let primitive = node.primitive_ref(layout.drawing()); let Some(primitive_net) = primitive.maybe_net() else { + assert_ne!(node, origin.into()); + assert_ne!(node, destination.into()); continue; }; @@ -215,6 +217,10 @@ impl Prenavmesh { // false positives in some cases, so in the future, instead of this, // create a fillet compound type and check for compound membership. if Self::is_fixed_dot_filleted(layout, dot) { + // FIXME: anteroute dot may get skipped here, which + // results in a panic. + assert_ne!(origin, dot); + assert_ne!(destination, dot); continue; }