autorouter: add option to disable presorting by pairwise detours

This commit is contained in:
Mikolaj Wielgus 2024-08-30 23:11:25 +02:00
parent f7f2e8ea49
commit a52515f6d3
5 changed files with 76 additions and 35 deletions

View File

@ -10,7 +10,7 @@ use crate::{
use super::{ use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
Autorouter, AutorouterError, Autorouter, AutorouterError, AutorouterOptions,
}; };
pub enum AutorouteStatus { pub enum AutorouteStatus {
@ -32,6 +32,7 @@ impl TryInto<()> for AutorouteStatus {
pub struct Autoroute { pub struct Autoroute {
ratlines_iter: Box<dyn Iterator<Item = EdgeIndex<usize>>>, ratlines_iter: Box<dyn Iterator<Item = EdgeIndex<usize>>>,
options: AutorouterOptions,
route: Option<Route>, route: Option<Route>,
curr_ratline: Option<EdgeIndex<usize>>, curr_ratline: Option<EdgeIndex<usize>>,
} }
@ -40,6 +41,7 @@ impl Autoroute {
pub fn new( pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>, autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static, ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
options: AutorouterOptions,
) -> Result<Self, AutorouterError> { ) -> Result<Self, AutorouterError> {
let mut ratlines_iter = Box::new(ratlines.into_iter()); let mut ratlines_iter = Box::new(ratlines.into_iter());
@ -52,8 +54,9 @@ impl Autoroute {
let this = Self { let this = Self {
ratlines_iter, ratlines_iter,
curr_ratline: Some(curr_ratline), options,
route: Some(router.route(source, target, 100.0)?), route: Some(router.route(source, target, 100.0)?),
curr_ratline: Some(curr_ratline),
}; };
Ok(this) Ok(this)

View File

@ -1,4 +1,5 @@
use petgraph::graph::EdgeIndex; use petgraph::graph::EdgeIndex;
use serde::{Deserialize, Serialize};
use spade::InsertionError; use spade::InsertionError;
use thiserror::Error; use thiserror::Error;
@ -24,6 +25,23 @@ use super::{
selection::{BandSelection, PinSelection}, selection::{BandSelection, PinSelection},
}; };
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct AutorouterOptions {
pub presort_by_pairwise_detours: bool,
//pub wrap_around_bands: bool,
//pub squeeze_under_bands: bool,
}
impl AutorouterOptions {
pub fn new() -> Self {
Self {
presort_by_pairwise_detours: false,
//wrap_around_bands: true,
//squeeze_under_bands: true,
}
}
}
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone)]
pub enum AutorouterError { pub enum AutorouterError {
#[error("nothing to route")] #[error("nothing to route")]
@ -51,15 +69,20 @@ impl<M: AccessMesadata> Autorouter<M> {
Ok(Self { board, ratsnest }) Ok(Self { board, ratsnest })
} }
pub fn autoroute(&mut self, selection: &PinSelection) -> Result<Autoroute, AutorouterError> { pub fn autoroute(
self.autoroute_ratlines(self.selected_ratlines(selection)) &mut self,
selection: &PinSelection,
options: AutorouterOptions,
) -> Result<Autoroute, AutorouterError> {
self.autoroute_ratlines(self.selected_ratlines(selection), options)
} }
pub(super) fn autoroute_ratlines( pub(super) fn autoroute_ratlines(
&mut self, &mut self,
ratlines: Vec<EdgeIndex<usize>>, ratlines: Vec<EdgeIndex<usize>>,
options: AutorouterOptions,
) -> Result<Autoroute, AutorouterError> { ) -> Result<Autoroute, AutorouterError> {
Autoroute::new(self, ratlines) Autoroute::new(self, ratlines, options)
} }
pub fn undo_autoroute(&mut self, selection: &PinSelection) -> Result<(), AutorouterError> { pub fn undo_autoroute(&mut self, selection: &PinSelection) -> Result<(), AutorouterError> {
@ -106,6 +129,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn compare_detours( pub fn compare_detours(
&mut self, &mut self,
selection: &PinSelection, selection: &PinSelection,
options: AutorouterOptions,
) -> Result<CompareDetours, AutorouterError> { ) -> Result<CompareDetours, AutorouterError> {
let ratlines = self.selected_ratlines(selection); let ratlines = self.selected_ratlines(selection);
let ratline1 = *ratlines let ratline1 = *ratlines
@ -114,15 +138,16 @@ impl<M: AccessMesadata> Autorouter<M> {
let ratline2 = *ratlines let ratline2 = *ratlines
.get(1) .get(1)
.ok_or(AutorouterError::NeedExactlyTwoRatlines)?; .ok_or(AutorouterError::NeedExactlyTwoRatlines)?;
self.compare_detours_ratlines(ratline1, ratline2) self.compare_detours_ratlines(ratline1, ratline2, options)
} }
pub(super) fn compare_detours_ratlines( pub(super) fn compare_detours_ratlines(
&mut self, &mut self,
ratline1: EdgeIndex<usize>, ratline1: EdgeIndex<usize>,
ratline2: EdgeIndex<usize>, ratline2: EdgeIndex<usize>,
options: AutorouterOptions,
) -> Result<CompareDetours, AutorouterError> { ) -> Result<CompareDetours, AutorouterError> {
CompareDetours::new(self, ratline1, ratline2) CompareDetours::new(self, ratline1, ratline2, options)
} }
pub fn measure_length( pub fn measure_length(

View File

@ -12,7 +12,7 @@ use crate::{
use super::{ use super::{
autoroute::{Autoroute, AutorouteStatus}, autoroute::{Autoroute, AutorouteStatus},
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles}, invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
Autorouter, AutorouterError, Autorouter, AutorouterError, AutorouterOptions,
}; };
pub enum CompareDetoursStatus { pub enum CompareDetoursStatus {
@ -47,10 +47,11 @@ impl CompareDetours {
autorouter: &mut Autorouter<impl AccessMesadata>, autorouter: &mut Autorouter<impl AccessMesadata>,
ratline1: EdgeIndex<usize>, ratline1: EdgeIndex<usize>,
ratline2: EdgeIndex<usize>, ratline2: EdgeIndex<usize>,
options: AutorouterOptions,
) -> Result<Self, AutorouterError> { ) -> Result<Self, AutorouterError> {
Ok(Self { Ok(Self {
autoroute: autorouter.autoroute_ratlines(vec![ratline1, ratline2])?, autoroute: autorouter.autoroute_ratlines(vec![ratline1, ratline2], options)?,
next_autoroute: Some(autorouter.autoroute_ratlines(vec![ratline2, ratline1])?), next_autoroute: Some(autorouter.autoroute_ratlines(vec![ratline2, ratline1], options)?),
ratline1, ratline1,
ratline2, ratline2,
total_length1: 0.0, total_length1: 0.0,

View File

@ -22,7 +22,7 @@ use super::{
place_via::PlaceVia, place_via::PlaceVia,
remove_bands::RemoveBands, remove_bands::RemoveBands,
selection::{BandSelection, PinSelection}, selection::{BandSelection, PinSelection},
Autorouter, AutorouterError, Autorouter, AutorouterError, AutorouterOptions,
}; };
#[enum_dispatch] #[enum_dispatch]
@ -71,10 +71,10 @@ impl TryInto<()> for InvokerStatus {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Command { pub enum Command {
Autoroute(PinSelection), Autoroute(PinSelection, AutorouterOptions),
PlaceVia(ViaWeight), PlaceVia(ViaWeight),
RemoveBands(BandSelection), RemoveBands(BandSelection),
CompareDetours(PinSelection), CompareDetours(PinSelection, AutorouterOptions),
MeasureLength(BandSelection), MeasureLength(BandSelection),
} }
@ -254,19 +254,25 @@ impl<M: AccessMesadata> Invoker<M> {
#[debug_requires(self.ongoing_command.is_none())] #[debug_requires(self.ongoing_command.is_none())]
fn dispatch_command(&mut self, command: &Command) -> Result<Execute, InvokerError> { fn dispatch_command(&mut self, command: &Command) -> Result<Execute, InvokerError> {
match command { match command {
Command::Autoroute(selection) => { Command::Autoroute(selection, options) => {
let mut ratlines = self.autorouter.selected_ratlines(selection); let mut ratlines = self.autorouter.selected_ratlines(selection);
if options.presort_by_pairwise_detours {
ratlines.sort_unstable_by(|a, b| { ratlines.sort_unstable_by(|a, b| {
let mut compare_detours = let mut compare_detours = self
self.autorouter.compare_detours_ratlines(*a, *b).unwrap(); .autorouter
.compare_detours_ratlines(*a, *b, *options)
.unwrap();
if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) { if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) {
PartialOrd::partial_cmp(&al, &bl).unwrap() PartialOrd::partial_cmp(&al, &bl).unwrap()
} else { } else {
Ordering::Equal Ordering::Equal
} }
}); });
}
Ok::<Execute, InvokerError>(Execute::Autoroute( Ok::<Execute, InvokerError>(Execute::Autoroute(
self.autorouter.autoroute_ratlines(ratlines)?, self.autorouter.autoroute_ratlines(ratlines, *options)?,
)) ))
} }
Command::PlaceVia(weight) => { Command::PlaceVia(weight) => {
@ -275,8 +281,8 @@ impl<M: AccessMesadata> Invoker<M> {
Command::RemoveBands(selection) => Ok::<Execute, InvokerError>(Execute::RemoveBands( Command::RemoveBands(selection) => Ok::<Execute, InvokerError>(Execute::RemoveBands(
self.autorouter.remove_bands(selection)?, self.autorouter.remove_bands(selection)?,
)), )),
Command::CompareDetours(selection) => Ok::<Execute, InvokerError>( Command::CompareDetours(selection, options) => Ok::<Execute, InvokerError>(
Execute::CompareDetours(self.autorouter.compare_detours(selection)?), Execute::CompareDetours(self.autorouter.compare_detours(selection, *options)?),
), ),
Command::MeasureLength(selection) => Ok::<Execute, InvokerError>( Command::MeasureLength(selection) => Ok::<Execute, InvokerError>(
Execute::MeasureLength(self.autorouter.measure_length(selection)?), Execute::MeasureLength(self.autorouter.measure_length(selection)?),
@ -289,8 +295,8 @@ impl<M: AccessMesadata> Invoker<M> {
let command = self.history.last_done()?; let command = self.history.last_done()?;
match command { match command {
Command::Autoroute(ref selection) => { Command::Autoroute(ref selection, ..) => {
self.autorouter.undo_autoroute(selection); self.autorouter.undo_autoroute(selection)?;
} }
Command::PlaceVia(weight) => { Command::PlaceVia(weight) => {
self.autorouter.undo_place_via(*weight); self.autorouter.undo_place_via(*weight);

View File

@ -5,8 +5,9 @@ use std::{
}; };
use topola::{ use topola::{
autorouter::invoker::{ autorouter::{
Command, Execute, ExecuteWithStatus, Invoker, InvokerError, InvokerStatus, invoker::{Command, Execute, ExecuteWithStatus, Invoker, InvokerError, InvokerStatus},
AutorouterOptions,
}, },
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata}, specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
}; };
@ -248,9 +249,11 @@ impl Top {
) { ) {
let selection = overlay.selection().clone(); let selection = overlay.selection().clone();
overlay.clear_selection(); overlay.clear_selection();
maybe_execute maybe_execute.insert(ExecuteWithStatus::new(invoker.execute_stepper(
.insert(ExecuteWithStatus::new(invoker.execute_stepper( Command::Autoroute(
Command::Autoroute(selection.pin_selection), selection.pin_selection,
AutorouterOptions::new(),
),
)?)); )?));
} }
} }
@ -304,7 +307,10 @@ impl Top {
let selection = overlay.selection().clone(); let selection = overlay.selection().clone();
overlay.clear_selection(); overlay.clear_selection();
maybe_execute.insert(ExecuteWithStatus::new(invoker.execute_stepper( maybe_execute.insert(ExecuteWithStatus::new(invoker.execute_stepper(
Command::CompareDetours(selection.pin_selection), Command::CompareDetours(
selection.pin_selection,
AutorouterOptions::new(),
),
)?)); )?));
} }
} }