fix(autorouter/autoroute): Only route each pin-pin connection at most once

Fixes #219.
This commit is contained in:
Ellen Emilia Anna Zscheile 2025-05-22 17:06:53 +02:00
parent 8647df026d
commit 56cc737b82
4 changed files with 65 additions and 30 deletions

View File

@ -31,6 +31,8 @@ pub enum AutorouteContinueStatus {
Running, Running,
/// A specific segment has been successfully routed. /// A specific segment has been successfully routed.
Routed(BandTermsegIndex), Routed(BandTermsegIndex),
/// A specific segment was already routed and has been skipped.
Skipped(BandTermsegIndex),
} }
/// Manages the autorouting process across multiple ratlines. /// Manages the autorouting process across multiple ratlines.
@ -106,30 +108,36 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
let (source, target) = autorouter.ratline_endpoints(curr_ratline); let (source, target) = autorouter.ratline_endpoints(curr_ratline);
let band_termseg = { let ret = if let Some(band_termseg) = autorouter.board.band_between_nodes(source, target) {
let mut router = AutorouteContinueStatus::Skipped(band_termseg[false])
Router::new(autorouter.board.layout_mut(), self.options.router_options); } else {
let band_termseg = {
let mut router =
Router::new(autorouter.board.layout_mut(), self.options.router_options);
let ControlFlow::Break(band_termseg) = route.step(&mut router)? else { let ControlFlow::Break(band_termseg) = route.step(&mut router)? else {
return Ok(ControlFlow::Continue(AutorouteContinueStatus::Running)); return Ok(ControlFlow::Continue(AutorouteContinueStatus::Running));
};
band_termseg
}; };
band_termseg
let band = autorouter
.board
.layout()
.drawing()
.loose_band_uid(band_termseg.into());
autorouter
.ratsnest
.assign_band_termseg_to_ratline(self.curr_ratline.unwrap(), band_termseg);
autorouter
.board
.try_set_band_between_nodes(source, target, band);
AutorouteContinueStatus::Routed(band_termseg)
}; };
let band = autorouter
.board
.layout()
.drawing()
.loose_band_uid(band_termseg.into());
autorouter
.ratsnest
.assign_band_termseg_to_ratline(self.curr_ratline.unwrap(), band_termseg);
autorouter
.board
.try_set_band_between_nodes(source, target, band);
if let Some(new_ratline) = self.ratlines_iter.next() { if let Some(new_ratline) = self.ratlines_iter.next() {
let (source, target) = autorouter.ratline_endpoints(new_ratline); let (source, target) = autorouter.ratline_endpoints(new_ratline);
let mut router = let mut router =
@ -154,9 +162,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
self.curr_ratline = None; self.curr_ratline = None;
} }
Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed( Ok(ControlFlow::Continue(ret))
band_termseg,
)))
} }
} }

View File

@ -69,9 +69,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, (f64, f64)> for CompareDetoursExecut
} }
match self.autoroute.step(autorouter)? { match self.autoroute.step(autorouter)? {
ControlFlow::Continue(AutorouteContinueStatus::Running) => { ControlFlow::Continue(
Ok(ControlFlow::Continue(())) AutorouteContinueStatus::Running | AutorouteContinueStatus::Skipped(_),
} ) => Ok(ControlFlow::Continue(())),
ControlFlow::Continue(AutorouteContinueStatus::Routed(band_termseg)) => { ControlFlow::Continue(AutorouteContinueStatus::Routed(band_termseg)) => {
let length = band_termseg let length = band_termseg
.ref_(autorouter.board.layout().drawing()) .ref_(autorouter.board.layout().drawing())

View File

@ -189,7 +189,7 @@ impl<M: AccessMesadata> Board<M> {
source: FixedDotIndex, source: FixedDotIndex,
target: FixedDotIndex, target: FixedDotIndex,
band: BandUid, band: BandUid,
) { ) -> bool {
let source_pinname = self let source_pinname = self
.node_pinname(&GenericNode::Primitive(source.into())) .node_pinname(&GenericNode::Primitive(source.into()))
.unwrap() .unwrap()
@ -198,8 +198,27 @@ impl<M: AccessMesadata> Board<M> {
.node_pinname(&GenericNode::Primitive(target.into())) .node_pinname(&GenericNode::Primitive(target.into()))
.unwrap() .unwrap()
.to_string(); .to_string();
self.band_bandname let bandname = BandName::from((source_pinname, target_pinname));
.insert(band, BandName::from((source_pinname, target_pinname))); if self.band_bandname.get_by_right(&bandname).is_some() {
false
} else {
self.band_bandname.insert(band, bandname);
true
}
}
pub fn band_between_nodes(
&self,
source: FixedDotIndex,
target: FixedDotIndex,
) -> Option<BandUid> {
let source_pinname = self
.node_pinname(&GenericNode::Primitive(source.into()))
.unwrap();
let target_pinname = self
.node_pinname(&GenericNode::Primitive(target.into()))
.unwrap();
self.band_between_pins(source_pinname, target_pinname)
} }
/// Finds a band between two pin names. /// Finds a band between two pin names.

View File

@ -6,7 +6,7 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{ use crate::{
geometry::shape::MeasureLength, geometry::{shape::MeasureLength, GetLayer},
graph::{GetPetgraphIndex, MakeRef}, graph::{GetPetgraphIndex, MakeRef},
}; };
@ -67,6 +67,16 @@ impl<'a, CW: 'a, Cel: 'a, R: 'a> BandRef<'a, CW, Cel, R> {
} }
} }
impl<CW: Clone, Cel: Copy, R: AccessRules> GetLayer for BandRef<'_, CW, Cel, R> {
fn layer(&self) -> usize {
match self.first_seg {
BandTermsegIndex::Straight(seg) => seg.primitive(self.drawing),
BandTermsegIndex::Bended(seg) => seg.primitive(self.drawing),
}
.layer()
}
}
impl<CW: Clone, Cel: Copy, R: AccessRules> MeasureLength for BandRef<'_, CW, Cel, R> { impl<CW: Clone, Cel: Copy, R: AccessRules> MeasureLength for BandRef<'_, CW, Cel, R> {
fn length(&self) -> f64 { fn length(&self) -> f64 {
match self.first_seg { match self.first_seg {