refactor(autorouter/autorouter): Put ratsnest in wrapper, mostly transparent for now

This commit is contained in:
Mikolaj Wielgus 2025-10-13 00:32:53 +02:00
parent 60cf00e014
commit 4c1a72dc1d
10 changed files with 118 additions and 60 deletions

View File

@ -167,7 +167,8 @@ impl<'a> Displayer<'a> {
.interactor .interactor
.invoker() .invoker()
.autorouter() .autorouter()
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph(); .graph();
for edge in graph.edge_references() { for edge in graph.edge_references() {
if edge.weight().band_termseg.is_some() { if edge.weight().band_termseg.is_some() {

View File

@ -66,7 +66,8 @@ impl Anterouter {
let endpoint_dots = ratline.ref_(autorouter).endpoint_dots(); let endpoint_dots = ratline.ref_(autorouter).endpoint_dots();
autorouter autorouter
.ratsnest .ratsnests
.on_principal_layer_mut(0)
.assign_layer_to_ratline(*ratline, *layer); .assign_layer_to_ratline(*ratline, *layer);
if let Some(terminating_scheme) = self if let Some(terminating_scheme) = self
@ -75,13 +76,14 @@ impl Anterouter {
.get(&endpoint_dots.0) .get(&endpoint_dots.0)
{ {
match terminating_scheme { match terminating_scheme {
TerminatingScheme::ExistingFixedDot(terminating_dot) => { TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter
autorouter.ratsnest.assign_terminating_dot_to_ratvertex( .ratsnests
.on_principal_layer_mut(0)
.assign_terminating_dot_to_ratvertex(
endpoint_indices.0, endpoint_indices.0,
*layer, *layer,
*terminating_dot, *terminating_dot,
) ),
}
TerminatingScheme::Fanout => self.anteroute_fanout( TerminatingScheme::Fanout => self.anteroute_fanout(
autorouter, autorouter,
endpoint_indices.0, endpoint_indices.0,
@ -99,13 +101,14 @@ impl Anterouter {
.get(&endpoint_dots.1) .get(&endpoint_dots.1)
{ {
match terminating_scheme { match terminating_scheme {
TerminatingScheme::ExistingFixedDot(terminating_dot) => { TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter
autorouter.ratsnest.assign_terminating_dot_to_ratvertex( .ratsnests
.on_principal_layer_mut(0)
.assign_terminating_dot_to_ratvertex(
endpoint_indices.1, endpoint_indices.1,
*layer, *layer,
*terminating_dot, *terminating_dot,
) ),
}
TerminatingScheme::Fanout => self.anteroute_fanout( TerminatingScheme::Fanout => self.anteroute_fanout(
autorouter, autorouter,
endpoint_indices.1, endpoint_indices.1,
@ -430,11 +433,10 @@ impl Anterouter {
.layer() .layer()
}) })
.unwrap(); .unwrap();
autorouter.ratsnest.assign_terminating_dot_to_ratvertex( autorouter
ratvertex, .ratsnests
target_layer, .on_principal_layer_mut(0)
*terminating_dot, .assign_terminating_dot_to_ratvertex(ratvertex, target_layer, *terminating_dot);
);
Ok((via, dots)) Ok((via, dots))
} else { } else {
Err(()) Err(())

View File

@ -15,6 +15,7 @@ use crate::{
multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions}, multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions},
permutator::PlanarAutorouteExecutionPermutator, permutator::PlanarAutorouteExecutionPermutator,
planner::Planner, planner::Planner,
ratsnests::Ratsnests,
}, },
board::{AccessMesadata, Board}, board::{AccessMesadata, Board},
drawing::band::BandTermsegIndex, drawing::band::BandTermsegIndex,
@ -31,7 +32,7 @@ use super::{
planar_autoroute::PlanarAutorouteExecutionStepper, planar_autoroute::PlanarAutorouteExecutionStepper,
pointroute::PointrouteExecutionStepper, pointroute::PointrouteExecutionStepper,
ratline::RatlineIndex, ratline::RatlineIndex,
ratsnest::{Ratsnest, RatvertexNodeIndex}, ratsnest::RatvertexNodeIndex,
remove_bands::RemoveBandsExecutionStepper, remove_bands::RemoveBandsExecutionStepper,
selection::{BandSelection, PinSelection}, selection::{BandSelection, PinSelection},
}; };
@ -72,13 +73,13 @@ pub enum AutorouterError {
#[derive(Getters)] #[derive(Getters)]
pub struct Autorouter<M> { pub struct Autorouter<M> {
pub(super) board: Board<M>, pub(super) board: Board<M>,
pub(super) ratsnest: Ratsnest, pub(super) ratsnests: Ratsnests,
} }
impl<M: AccessMesadata> Autorouter<M> { impl<M: AccessMesadata> Autorouter<M> {
pub fn new(board: Board<M>) -> Result<Self, InsertionError> { pub fn new(board: Board<M>) -> Result<Self, InsertionError> {
let ratsnest = Ratsnest::new(&board)?; let ratsnests = Ratsnests::new(&board)?;
Ok(Self { board, ratsnest }) Ok(Self { board, ratsnests })
} }
pub fn pointroute( pub fn pointroute(
@ -89,7 +90,8 @@ impl<M: AccessMesadata> Autorouter<M> {
) -> Result<PointrouteExecutionStepper, AutorouterError> { ) -> Result<PointrouteExecutionStepper, AutorouterError> {
let ratvertex = self.find_selected_ratvertex(selection).unwrap(); let ratvertex = self.find_selected_ratvertex(selection).unwrap();
let origin_dot = match self let origin_dot = match self
.ratsnest .ratsnests
.on_principal_layer_mut(0)
.graph() .graph()
.node_weight(ratvertex) .node_weight(ratvertex)
.unwrap() .unwrap()
@ -302,20 +304,28 @@ impl<M: AccessMesadata> Autorouter<M> {
} }
pub(super) fn selected_ratlines(&self, selection: &PinSelection) -> Vec<RatlineIndex> { pub(super) fn selected_ratlines(&self, selection: &PinSelection) -> Vec<RatlineIndex> {
self.ratsnest self.ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_indices() .edge_indices()
.filter(|ratline| { .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 let source_ratvertex = self
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(source) .node_weight(source)
.unwrap() .unwrap()
.node_index(); .node_index();
let to_ratvertex = self let to_ratvertex = self
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(target) .node_weight(target)
.unwrap() .unwrap()
@ -328,16 +338,21 @@ impl<M: AccessMesadata> Autorouter<M> {
} }
fn find_selected_ratvertex(&self, selection: &PinSelection) -> Option<NodeIndex<usize>> { fn find_selected_ratvertex(&self, selection: &PinSelection) -> Option<NodeIndex<usize>> {
self.ratsnest.graph().node_indices().find(|ratvertex| { self.ratsnests()
selection.contains_node( .on_principal_layer(0)
&self.board, .graph()
self.ratsnest .node_indices()
.graph() .find(|ratvertex| {
.node_weight(*ratvertex) selection.contains_node(
.unwrap() &self.board,
.node_index() self.ratsnests()
.into(), .on_principal_layer(0)
) .graph()
}) .node_weight(*ratvertex)
.unwrap()
.node_index()
.into(),
)
})
} }
} }

View File

@ -21,6 +21,7 @@ pub mod pointroute;
pub mod presorter; pub mod presorter;
pub mod ratline; pub mod ratline;
pub mod ratsnest; pub mod ratsnest;
pub mod ratsnests;
pub mod remove_bands; pub mod remove_bands;
pub mod scc; pub mod scc;
pub mod selection; pub mod selection;

View File

@ -87,14 +87,16 @@ impl PermuteRatlines for SccPermutationsRatlinePermuter {
for ratline in self.original_ratlines.iter() { for ratline in self.original_ratlines.iter() {
if scc.node_indices().contains( if scc.node_indices().contains(
&autorouter &autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(*ratline) .edge_endpoints(*ratline)
.unwrap() .unwrap()
.0, .0,
) && scc.node_indices().contains( ) && scc.node_indices().contains(
&autorouter &autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(*ratline) .edge_endpoints(*ratline)
.unwrap() .unwrap()

View File

@ -185,10 +185,13 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
.find_loose_band_uid(band_termseg.into()) .find_loose_band_uid(band_termseg.into())
.expect("a completely routed band should've Seg's as ends"); .expect("a completely routed band should've Seg's as ends");
autorouter.ratsnest.assign_band_termseg_to_ratline( autorouter
self.ratlines[self.curr_ratline_index], .ratsnests
band_termseg, .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(); let mut board_data_edit = BoardDataEdit::new();

View File

@ -40,7 +40,7 @@ impl SccIntersectionsAndLengthPresorter {
params: &PresortParams, params: &PresortParams,
) -> Self { ) -> Self {
// FIXME: Unnecessary copy. // 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)); filtered_ratsnest.retain_edges(|_g, i| ratlines.contains(&i));
let mut sccs: Vec<_> = tarjan_scc(&filtered_ratsnest) let mut sccs: Vec<_> = tarjan_scc(&filtered_ratsnest)

View File

@ -46,7 +46,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
pub fn band_termseg(&self) -> BandTermsegIndex { pub fn band_termseg(&self) -> BandTermsegIndex {
self.autorouter self.autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_weight(self.index) .edge_weight(self.index)
.unwrap() .unwrap()
@ -57,14 +58,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
pub fn endpoint_dots(&self) -> (FixedDotIndex, FixedDotIndex) { pub fn endpoint_dots(&self) -> (FixedDotIndex, FixedDotIndex) {
let (source, target) = self let (source, target) = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(self.index) .edge_endpoints(self.index)
.unwrap(); .unwrap();
let source_dot = match self let source_dot = match self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(source) .node_weight(source)
.unwrap() .unwrap()
@ -76,7 +79,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
let target_dot = match self let target_dot = match self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(target) .node_weight(target)
.unwrap() .unwrap()
@ -92,14 +96,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
pub fn terminating_dots(&self) -> (FixedDotIndex, FixedDotIndex) { pub fn terminating_dots(&self) -> (FixedDotIndex, FixedDotIndex) {
let (source, target) = self let (source, target) = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(self.index) .edge_endpoints(self.index)
.unwrap(); .unwrap();
let source_dot = self let source_dot = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(source) .node_weight(source)
.unwrap() .unwrap()
@ -109,7 +115,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
.unwrap_or(self.endpoint_dots().0); .unwrap_or(self.endpoint_dots().0);
let target_dot = self let target_dot = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(target) .node_weight(target)
.unwrap() .unwrap()
@ -123,15 +130,12 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
pub fn layer(&self) -> usize { pub fn layer(&self) -> usize {
self.autorouter self.autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_weight(self.index) .edge_weight(self.index)
.unwrap() .unwrap()
.layer .layer
/*self.endpoint_dots()
.0
.primitive_ref(self.autorouter.board().layout().drawing())
.layer()*/
} }
pub fn net(&self) -> usize { pub fn net(&self) -> usize {
@ -164,7 +168,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
let self_line_segment = self.line_segment(); let self_line_segment = self.line_segment();
self.autorouter self.autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_indices() .edge_indices()
.filter(move |other| { .filter(move |other| {
@ -195,14 +200,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
let (source, target) = self.endpoint_indices(); let (source, target) = self.endpoint_indices();
let source_pos = self let source_pos = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(source) .node_weight(source)
.unwrap() .unwrap()
.pos; .pos;
let target_pos = self let target_pos = self
.autorouter .autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.node_weight(target) .node_weight(target)
.unwrap() .unwrap()
@ -213,7 +220,8 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
pub fn endpoint_indices(&self) -> (NodeIndex<usize>, NodeIndex<usize>) { pub fn endpoint_indices(&self) -> (NodeIndex<usize>, NodeIndex<usize>) {
self.autorouter self.autorouter
.ratsnest .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(self.index) .edge_endpoints(self.index)
.unwrap() .unwrap()

View File

@ -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<impl AccessMesadata>) -> Result<Self, InsertionError> {
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]
}
}

View File

@ -78,7 +78,8 @@ impl<'a, M: AccessMesadata> SccRef<'a, M> {
self.scc.node_indices().contains( self.scc.node_indices().contains(
&self &self
.autorouter .autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(ratline) .edge_endpoints(ratline)
.unwrap() .unwrap()
@ -86,7 +87,8 @@ impl<'a, M: AccessMesadata> SccRef<'a, M> {
) && self.scc.node_indices().contains( ) && self.scc.node_indices().contains(
&self &self
.autorouter .autorouter
.ratsnest() .ratsnests()
.on_principal_layer(0)
.graph() .graph()
.edge_endpoints(ratline) .edge_endpoints(ratline)
.unwrap() .unwrap()