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

View File

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

View File

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

View File

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

View File

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