From 4c1a72dc1d7fbf73a78132b91d3fd724e58b0a74 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Mon, 13 Oct 2025 00:32:53 +0200 Subject: [PATCH] refactor(autorouter/autorouter): Put ratsnest in wrapper, mostly transparent for now --- crates/topola-egui/src/displayer.rs | 3 +- src/autorouter/anterouter.rs | 30 ++++++++-------- src/autorouter/autorouter.rs | 55 ++++++++++++++++++----------- src/autorouter/mod.rs | 1 + src/autorouter/permuter.rs | 6 ++-- src/autorouter/planar_autoroute.rs | 11 +++--- src/autorouter/presorter.rs | 2 +- src/autorouter/ratline.rs | 40 ++++++++++++--------- src/autorouter/ratsnests.rs | 24 +++++++++++++ src/autorouter/scc.rs | 6 ++-- 10 files changed, 118 insertions(+), 60 deletions(-) create mode 100644 src/autorouter/ratsnests.rs diff --git a/crates/topola-egui/src/displayer.rs b/crates/topola-egui/src/displayer.rs index 1874e24..6e7661c 100644 --- a/crates/topola-egui/src/displayer.rs +++ b/crates/topola-egui/src/displayer.rs @@ -167,7 +167,8 @@ impl<'a> Displayer<'a> { .interactor .invoker() .autorouter() - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph(); for edge in graph.edge_references() { if edge.weight().band_termseg.is_some() { diff --git a/src/autorouter/anterouter.rs b/src/autorouter/anterouter.rs index fe7a22a..4eab2d3 100644 --- a/src/autorouter/anterouter.rs +++ b/src/autorouter/anterouter.rs @@ -66,7 +66,8 @@ impl Anterouter { let endpoint_dots = ratline.ref_(autorouter).endpoint_dots(); autorouter - .ratsnest + .ratsnests + .on_principal_layer_mut(0) .assign_layer_to_ratline(*ratline, *layer); if let Some(terminating_scheme) = self @@ -75,13 +76,14 @@ impl Anterouter { .get(&endpoint_dots.0) { match terminating_scheme { - TerminatingScheme::ExistingFixedDot(terminating_dot) => { - autorouter.ratsnest.assign_terminating_dot_to_ratvertex( + TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter + .ratsnests + .on_principal_layer_mut(0) + .assign_terminating_dot_to_ratvertex( endpoint_indices.0, *layer, *terminating_dot, - ) - } + ), TerminatingScheme::Fanout => self.anteroute_fanout( autorouter, endpoint_indices.0, @@ -99,13 +101,14 @@ impl Anterouter { .get(&endpoint_dots.1) { match terminating_scheme { - TerminatingScheme::ExistingFixedDot(terminating_dot) => { - autorouter.ratsnest.assign_terminating_dot_to_ratvertex( + TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter + .ratsnests + .on_principal_layer_mut(0) + .assign_terminating_dot_to_ratvertex( endpoint_indices.1, *layer, *terminating_dot, - ) - } + ), TerminatingScheme::Fanout => self.anteroute_fanout( autorouter, endpoint_indices.1, @@ -430,11 +433,10 @@ impl Anterouter { .layer() }) .unwrap(); - autorouter.ratsnest.assign_terminating_dot_to_ratvertex( - ratvertex, - target_layer, - *terminating_dot, - ); + autorouter + .ratsnests + .on_principal_layer_mut(0) + .assign_terminating_dot_to_ratvertex(ratvertex, target_layer, *terminating_dot); Ok((via, dots)) } else { Err(()) diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 3c54e7a..71f4544 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -15,6 +15,7 @@ use crate::{ multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions}, permutator::PlanarAutorouteExecutionPermutator, planner::Planner, + ratsnests::Ratsnests, }, board::{AccessMesadata, Board}, drawing::band::BandTermsegIndex, @@ -31,7 +32,7 @@ use super::{ planar_autoroute::PlanarAutorouteExecutionStepper, pointroute::PointrouteExecutionStepper, ratline::RatlineIndex, - ratsnest::{Ratsnest, RatvertexNodeIndex}, + ratsnest::RatvertexNodeIndex, remove_bands::RemoveBandsExecutionStepper, selection::{BandSelection, PinSelection}, }; @@ -72,13 +73,13 @@ pub enum AutorouterError { #[derive(Getters)] pub struct Autorouter { pub(super) board: Board, - pub(super) ratsnest: Ratsnest, + pub(super) ratsnests: Ratsnests, } impl Autorouter { pub fn new(board: Board) -> Result { - let ratsnest = Ratsnest::new(&board)?; - Ok(Self { board, ratsnest }) + let ratsnests = Ratsnests::new(&board)?; + Ok(Self { board, ratsnests }) } pub fn pointroute( @@ -89,7 +90,8 @@ impl Autorouter { ) -> Result { let ratvertex = self.find_selected_ratvertex(selection).unwrap(); let origin_dot = match self - .ratsnest + .ratsnests + .on_principal_layer_mut(0) .graph() .node_weight(ratvertex) .unwrap() @@ -302,20 +304,28 @@ impl Autorouter { } pub(super) fn selected_ratlines(&self, selection: &PinSelection) -> Vec { - self.ratsnest + self.ratsnests() + .on_principal_layer(0) .graph() .edge_indices() .filter(|ratline| { - let (source, target) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap(); + let (source, target) = self + .ratsnests() + .on_principal_layer(0) + .graph() + .edge_endpoints(*ratline) + .unwrap(); let source_ratvertex = self - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(source) .unwrap() .node_index(); let to_ratvertex = self - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(target) .unwrap() @@ -328,16 +338,21 @@ impl Autorouter { } fn find_selected_ratvertex(&self, selection: &PinSelection) -> Option> { - self.ratsnest.graph().node_indices().find(|ratvertex| { - selection.contains_node( - &self.board, - self.ratsnest - .graph() - .node_weight(*ratvertex) - .unwrap() - .node_index() - .into(), - ) - }) + self.ratsnests() + .on_principal_layer(0) + .graph() + .node_indices() + .find(|ratvertex| { + selection.contains_node( + &self.board, + self.ratsnests() + .on_principal_layer(0) + .graph() + .node_weight(*ratvertex) + .unwrap() + .node_index() + .into(), + ) + }) } } diff --git a/src/autorouter/mod.rs b/src/autorouter/mod.rs index 4cfa123..022c01f 100644 --- a/src/autorouter/mod.rs +++ b/src/autorouter/mod.rs @@ -21,6 +21,7 @@ pub mod pointroute; pub mod presorter; pub mod ratline; pub mod ratsnest; +pub mod ratsnests; pub mod remove_bands; pub mod scc; pub mod selection; diff --git a/src/autorouter/permuter.rs b/src/autorouter/permuter.rs index 62ac4bd..70497d0 100644 --- a/src/autorouter/permuter.rs +++ b/src/autorouter/permuter.rs @@ -87,14 +87,16 @@ impl PermuteRatlines for SccPermutationsRatlinePermuter { for ratline in self.original_ratlines.iter() { if scc.node_indices().contains( &autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(*ratline) .unwrap() .0, ) && scc.node_indices().contains( &autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(*ratline) .unwrap() diff --git a/src/autorouter/planar_autoroute.rs b/src/autorouter/planar_autoroute.rs index 015ef1b..82575ac 100644 --- a/src/autorouter/planar_autoroute.rs +++ b/src/autorouter/planar_autoroute.rs @@ -185,10 +185,13 @@ impl Step, Option, PlanarAutorouteCo .find_loose_band_uid(band_termseg.into()) .expect("a completely routed band should've Seg's as ends"); - autorouter.ratsnest.assign_band_termseg_to_ratline( - self.ratlines[self.curr_ratline_index], - band_termseg, - ); + autorouter + .ratsnests + .on_principal_layer_mut(0) + .assign_band_termseg_to_ratline( + self.ratlines[self.curr_ratline_index], + band_termseg, + ); let mut board_data_edit = BoardDataEdit::new(); diff --git a/src/autorouter/presorter.rs b/src/autorouter/presorter.rs index fb0da51..13f3f4f 100644 --- a/src/autorouter/presorter.rs +++ b/src/autorouter/presorter.rs @@ -40,7 +40,7 @@ impl SccIntersectionsAndLengthPresorter { params: &PresortParams, ) -> Self { // FIXME: Unnecessary copy. - let mut filtered_ratsnest = autorouter.ratsnest().graph().clone(); + let mut filtered_ratsnest = autorouter.ratsnests().on_principal_layer(0).graph().clone(); filtered_ratsnest.retain_edges(|_g, i| ratlines.contains(&i)); let mut sccs: Vec<_> = tarjan_scc(&filtered_ratsnest) diff --git a/src/autorouter/ratline.rs b/src/autorouter/ratline.rs index 623d29c..241626c 100644 --- a/src/autorouter/ratline.rs +++ b/src/autorouter/ratline.rs @@ -46,7 +46,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { pub fn band_termseg(&self) -> BandTermsegIndex { self.autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_weight(self.index) .unwrap() @@ -57,14 +58,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { pub fn endpoint_dots(&self) -> (FixedDotIndex, FixedDotIndex) { let (source, target) = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(self.index) .unwrap(); let source_dot = match self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(source) .unwrap() @@ -76,7 +79,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { let target_dot = match self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(target) .unwrap() @@ -92,14 +96,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { pub fn terminating_dots(&self) -> (FixedDotIndex, FixedDotIndex) { let (source, target) = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(self.index) .unwrap(); let source_dot = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(source) .unwrap() @@ -109,7 +115,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { .unwrap_or(self.endpoint_dots().0); let target_dot = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(target) .unwrap() @@ -123,15 +130,12 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { pub fn layer(&self) -> usize { self.autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_weight(self.index) .unwrap() .layer - /*self.endpoint_dots() - .0 - .primitive_ref(self.autorouter.board().layout().drawing()) - .layer()*/ } pub fn net(&self) -> usize { @@ -164,7 +168,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { let self_line_segment = self.line_segment(); self.autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_indices() .filter(move |other| { @@ -195,14 +200,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { let (source, target) = self.endpoint_indices(); let source_pos = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(source) .unwrap() .pos; let target_pos = self .autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .node_weight(target) .unwrap() @@ -213,7 +220,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> { pub fn endpoint_indices(&self) -> (NodeIndex, NodeIndex) { self.autorouter - .ratsnest + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(self.index) .unwrap() diff --git a/src/autorouter/ratsnests.rs b/src/autorouter/ratsnests.rs new file mode 100644 index 0000000..fcdb22e --- /dev/null +++ b/src/autorouter/ratsnests.rs @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2025 Topola contributors +// +// SPDX-License-Identifier: MIT + +use spade::InsertionError; +use specctra_core::mesadata::AccessMesadata; + +use crate::{autorouter::ratsnest::Ratsnest, board::Board}; + +pub struct Ratsnests(Box<[Ratsnest]>); + +impl Ratsnests { + pub fn new(board: &Board) -> Result { + Ok(Self(Box::new([Ratsnest::new(board)?]))) + } + + pub fn on_principal_layer(&self, principal_layer: usize) -> &Ratsnest { + &self.0[principal_layer] + } + + pub fn on_principal_layer_mut(&mut self, principal_layer: usize) -> &mut Ratsnest { + &mut self.0[principal_layer] + } +} diff --git a/src/autorouter/scc.rs b/src/autorouter/scc.rs index 833e002..f8b8a84 100644 --- a/src/autorouter/scc.rs +++ b/src/autorouter/scc.rs @@ -78,7 +78,8 @@ impl<'a, M: AccessMesadata> SccRef<'a, M> { self.scc.node_indices().contains( &self .autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(ratline) .unwrap() @@ -86,7 +87,8 @@ impl<'a, M: AccessMesadata> SccRef<'a, M> { ) && self.scc.node_indices().contains( &self .autorouter - .ratsnest() + .ratsnests() + .on_principal_layer(0) .graph() .edge_endpoints(ratline) .unwrap()