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,
/// A specific segment has been successfully routed.
Routed(BandTermsegIndex),
/// A specific segment was already routed and has been skipped.
Skipped(BandTermsegIndex),
}
/// Manages the autorouting process across multiple ratlines.
@ -106,6 +108,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
let ret = if let Some(band_termseg) = autorouter.board.band_between_nodes(source, target) {
AutorouteContinueStatus::Skipped(band_termseg[false])
} else {
let band_termseg = {
let mut router =
Router::new(autorouter.board.layout_mut(), self.options.router_options);
@ -130,6 +135,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
.board
.try_set_band_between_nodes(source, target, band);
AutorouteContinueStatus::Routed(band_termseg)
};
if let Some(new_ratline) = self.ratlines_iter.next() {
let (source, target) = autorouter.ratline_endpoints(new_ratline);
let mut router =
@ -154,9 +162,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<LayoutEdit>, AutorouteContinu
self.curr_ratline = None;
}
Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed(
band_termseg,
)))
Ok(ControlFlow::Continue(ret))
}
}

View File

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

View File

@ -189,7 +189,7 @@ impl<M: AccessMesadata> Board<M> {
source: FixedDotIndex,
target: FixedDotIndex,
band: BandUid,
) {
) -> bool {
let source_pinname = self
.node_pinname(&GenericNode::Primitive(source.into()))
.unwrap()
@ -198,8 +198,27 @@ impl<M: AccessMesadata> Board<M> {
.node_pinname(&GenericNode::Primitive(target.into()))
.unwrap()
.to_string();
self.band_bandname
.insert(band, BandName::from((source_pinname, target_pinname)));
let bandname = 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.

View File

@ -6,7 +6,7 @@ use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex;
use crate::{
geometry::shape::MeasureLength,
geometry::{shape::MeasureLength, GetLayer},
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> {
fn length(&self) -> f64 {
match self.first_seg {