mirror of https://codeberg.org/topola/topola.git
autorouter: add option to disable presorting by pairwise detours
This commit is contained in:
parent
f7f2e8ea49
commit
a52515f6d3
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
ratlines.sort_unstable_by(|a, b| {
|
|
||||||
let mut compare_detours =
|
if options.presort_by_pairwise_detours {
|
||||||
self.autorouter.compare_detours_ratlines(*a, *b).unwrap();
|
ratlines.sort_unstable_by(|a, b| {
|
||||||
if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) {
|
let mut compare_detours = self
|
||||||
PartialOrd::partial_cmp(&al, &bl).unwrap()
|
.autorouter
|
||||||
} else {
|
.compare_detours_ratlines(*a, *b, *options)
|
||||||
Ordering::Equal
|
.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(
|
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);
|
||||||
|
|
|
||||||
|
|
@ -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,10 +249,12 @@ 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(),
|
||||||
|
),
|
||||||
|
)?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
|
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
|
||||||
|
|
@ -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(),
|
||||||
|
),
|
||||||
)?));
|
)?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue