diff --git a/committed.toml b/committed.toml index 2c561b4..fd92a66 100644 --- a/committed.toml +++ b/committed.toml @@ -25,6 +25,7 @@ allowed_scopes = [ "autorouter/history", "autorouter/invoker", "autorouter/measure_length", + "autorouter/permutator", "autorouter/place_via", "autorouter/pointroute", "autorouter/ratsnest", diff --git a/src/autorouter/autoroute.rs b/src/autorouter/autoroute.rs index 8ce6118..a36dd0b 100644 --- a/src/autorouter/autoroute.rs +++ b/src/autorouter/autoroute.rs @@ -5,8 +5,7 @@ //! Manages autorouting of ratlines in a layout, tracking status and processed //! routing steps. -use itertools::{Itertools, Permutations}; -use std::{iter::Skip, ops::ControlFlow}; +use std::ops::ControlFlow; use crate::{ board::{ @@ -20,7 +19,7 @@ use crate::{ router::{ navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper, RouteStepper, Router, }, - stepper::{Abort, EstimateProgress, Permute, Step}, + stepper::{Abort, EstimateProgress, Permutate, Step}, }; use super::{ @@ -224,11 +223,11 @@ impl Abort> for AutorouteExecutionStepper { } } -impl Permute> for AutorouteExecutionStepper { +impl Permutate> for AutorouteExecutionStepper { type Index = RatlineIndex; type Output = Result<(), AutorouterError>; - fn permute( + fn permutate( &mut self, autorouter: &mut Autorouter, permutation: Vec, @@ -277,99 +276,3 @@ impl GetDebugOverlayData for AutorouteExecutionStepper { self.route.as_ref().map_or(&[], |route| route.obstacles()) } } - -pub struct AutorouteExecutionPermutator { - stepper: AutorouteExecutionStepper, - permutations_iter: Skip>>, - options: AutorouterOptions, -} - -impl AutorouteExecutionPermutator { - pub fn new( - autorouter: &mut Autorouter, - ratlines: Vec, - options: AutorouterOptions, - ) -> Result { - let ratlines_len = ratlines.len(); - - Ok(Self { - stepper: AutorouteExecutionStepper::new(autorouter, ratlines.clone(), options)?, - // Note: I assume here that the first permutation is the same as the original order. - permutations_iter: ratlines.into_iter().permutations(ratlines_len).skip(1), - options, - }) - } -} - -impl Step, Option, AutorouteContinueStatus> - for AutorouteExecutionPermutator -{ - type Error = AutorouterError; - - fn step( - &mut self, - autorouter: &mut Autorouter, - ) -> Result, AutorouteContinueStatus>, AutorouterError> { - match self.stepper.step(autorouter) { - Ok(ok) => Ok(ok), - Err(err) => { - if !self.options.permutate { - return Err(err); - } - - loop { - let Some(permutation) = self.permutations_iter.next() else { - return Ok(ControlFlow::Break(None)); - }; - - match self.stepper.permute(autorouter, permutation) { - Ok(()) => break, - Err(AutorouterError::NothingToUndoForPermutation) => continue, - Err(err) => return Err(err), - } - } - - self.stepper.step(autorouter) - } - } - } -} - -impl Abort> for AutorouteExecutionPermutator { - fn abort(&mut self, autorouter: &mut Autorouter) { - self.permutations_iter.all(|_| true); - self.stepper.abort(autorouter); - } -} - -impl EstimateProgress for AutorouteExecutionPermutator { - type Value = f64; - - fn estimate_progress_value(&self) -> f64 { - // TODO. - self.stepper.estimate_progress_value() - } - - fn estimate_progress_maximum(&self) -> f64 { - // TODO. - self.stepper.estimate_progress_maximum() - } -} - -impl GetDebugOverlayData for AutorouteExecutionPermutator { - fn maybe_thetastar(&self) -> Option<&ThetastarStepper> { - self.stepper.maybe_thetastar() - } - - fn maybe_navcord(&self) -> Option<&Navcord> { - self.stepper.maybe_navcord() - } - - fn ghosts(&self) -> &[PrimitiveShape] { - self.stepper.ghosts() - } - - fn obstacles(&self) -> &[PrimitiveIndex] { - self.stepper.obstacles() - } -} diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index fb420d1..4fa966f 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -11,6 +11,7 @@ use std::{cmp::Ordering, collections::BTreeSet}; use thiserror::Error; use crate::{ + autorouter::permutator::AutorouteExecutionPermutator, board::{AccessMesadata, Board}, drawing::{band::BandTermsegIndex, Infringement}, geometry::shape::MeasureLength, @@ -22,7 +23,7 @@ use crate::{ }; use super::{ - autoroute::{AutorouteExecutionPermutator, AutorouteExecutionStepper}, + autoroute::AutorouteExecutionStepper, compare_detours::CompareDetoursExecutionStepper, measure_length::MeasureLengthExecutionStepper, place_via::PlaceViaExecutionStepper, diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index 212171a..abc718a 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -8,6 +8,7 @@ use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; use crate::{ + autorouter::permutator::AutorouteExecutionPermutator, board::{edit::BoardEdit, AccessMesadata}, layout::via::ViaWeight, router::ng, @@ -15,7 +16,6 @@ use crate::{ }; use super::{ - autoroute::AutorouteExecutionPermutator, compare_detours::CompareDetoursExecutionStepper, invoker::{GetDebugOverlayData, Invoker, InvokerError}, measure_length::MeasureLengthExecutionStepper, diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 9eb7474..7e64084 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -28,11 +28,11 @@ use crate::{ }; use super::{ - autoroute::AutorouteExecutionPermutator, compare_detours::CompareDetoursExecutionStepper, execution::{Command, ExecutionStepper}, history::{History, HistoryError}, measure_length::MeasureLengthExecutionStepper, + permutator::AutorouteExecutionPermutator, place_via::PlaceViaExecutionStepper, remove_bands::RemoveBandsExecutionStepper, Autorouter, AutorouterError, diff --git a/src/autorouter/mod.rs b/src/autorouter/mod.rs index 67bcbbf..8609eb4 100644 --- a/src/autorouter/mod.rs +++ b/src/autorouter/mod.rs @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: MIT -//! Manages autorouting process, under work for now - pub mod autoroute; mod autorouter; pub mod compare_detours; @@ -11,6 +9,7 @@ pub mod execution; pub mod history; pub mod invoker; pub mod measure_length; +pub mod permutator; pub mod place_via; pub mod pointroute; pub mod ratline; diff --git a/src/autorouter/permutator.rs b/src/autorouter/permutator.rs new file mode 100644 index 0000000..caa7b98 --- /dev/null +++ b/src/autorouter/permutator.rs @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: 2025 Topola contributors +// +// SPDX-License-Identifier: MIT + +use std::{iter::Skip, ops::ControlFlow}; + +use itertools::{Itertools, Permutations}; +use specctra_core::mesadata::AccessMesadata; + +use crate::{ + autorouter::{ + autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper}, + invoker::GetDebugOverlayData, + ratline::RatlineIndex, + Autorouter, AutorouterError, AutorouterOptions, + }, + board::edit::BoardEdit, + drawing::graph::PrimitiveIndex, + geometry::primitive::PrimitiveShape, + router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper}, + stepper::{Abort, EstimateProgress, Permutate, Step}, +}; + +pub struct AutorouteExecutionPermutator { + stepper: AutorouteExecutionStepper, + permutations_iter: Skip>>, + options: AutorouterOptions, +} + +impl AutorouteExecutionPermutator { + pub fn new( + autorouter: &mut Autorouter, + ratlines: Vec, + options: AutorouterOptions, + ) -> Result { + let ratlines_len = ratlines.len(); + + Ok(Self { + stepper: AutorouteExecutionStepper::new(autorouter, ratlines.clone(), options)?, + // Note: I assume here that the first permutation is the same as the original order. + permutations_iter: ratlines.into_iter().permutations(ratlines_len).skip(1), + options, + }) + } +} + +impl Step, Option, AutorouteContinueStatus> + for AutorouteExecutionPermutator +{ + type Error = AutorouterError; + + fn step( + &mut self, + autorouter: &mut Autorouter, + ) -> Result, AutorouteContinueStatus>, AutorouterError> { + match self.stepper.step(autorouter) { + Ok(ok) => Ok(ok), + Err(err) => { + if !self.options.permutate { + return Err(err); + } + + loop { + let Some(permutation) = self.permutations_iter.next() else { + return Ok(ControlFlow::Break(None)); + }; + + match self.stepper.permutate(autorouter, permutation) { + Ok(()) => break, + Err(AutorouterError::NothingToUndoForPermutation) => continue, + Err(err) => return Err(err), + } + } + + self.stepper.step(autorouter) + } + } + } +} + +impl Abort> for AutorouteExecutionPermutator { + fn abort(&mut self, autorouter: &mut Autorouter) { + self.permutations_iter.all(|_| true); + self.stepper.abort(autorouter); + } +} + +impl EstimateProgress for AutorouteExecutionPermutator { + type Value = f64; + + fn estimate_progress_value(&self) -> f64 { + // TODO. + self.stepper.estimate_progress_value() + } + + fn estimate_progress_maximum(&self) -> f64 { + // TODO. + self.stepper.estimate_progress_maximum() + } +} + +impl GetDebugOverlayData for AutorouteExecutionPermutator { + fn maybe_thetastar(&self) -> Option<&ThetastarStepper> { + self.stepper.maybe_thetastar() + } + + fn maybe_navcord(&self) -> Option<&Navcord> { + self.stepper.maybe_navcord() + } + + fn ghosts(&self) -> &[PrimitiveShape] { + self.stepper.ghosts() + } + + fn obstacles(&self) -> &[PrimitiveIndex] { + self.stepper.obstacles() + } +} diff --git a/src/stepper.rs b/src/stepper.rs index 86e6c3f..f3e4abf 100644 --- a/src/stepper.rs +++ b/src/stepper.rs @@ -54,11 +54,11 @@ pub trait Abort { } /// Some steppers may be permuted from their initial order. -pub trait Permute { +pub trait Permutate { type Index; type Output; - fn permute(&mut self, context: &mut Ctx, ordering: Vec) -> Self::Output; + fn permutate(&mut self, context: &mut Ctx, ordering: Vec) -> Self::Output; } /// Steppers that can receive discrete events and act on them implement this