mirror of https://codeberg.org/topola/topola.git
feat(autorouter/permuter): Implement permutation by ratline cut
Not yet used, and can get stuck in an infinite loop, but the cut seems to work.
This commit is contained in:
parent
fe7c258851
commit
1b485e81a6
|
|
@ -9,7 +9,7 @@
|
|||
feature = "serde",
|
||||
serde(bound(deserialize = "T: serde::Deserialize<'de> + Ord"))
|
||||
)]
|
||||
pub struct OrderedPair<T>(T, T);
|
||||
pub struct OrderedPair<T>(pub T, pub T);
|
||||
|
||||
impl<T> core::ops::Index<bool> for OrderedPair<T> {
|
||||
type Output = T;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use derive_getters::Getters;
|
||||
|
||||
use crate::{
|
||||
board::{
|
||||
edit::{BoardDataEdit, BoardEdit},
|
||||
|
|
@ -38,6 +40,7 @@ pub enum AutorouteContinueStatus {
|
|||
}
|
||||
|
||||
/// Manages the autorouting process across multiple ratlines.
|
||||
#[derive(Getters)]
|
||||
pub struct AutorouteExecutionStepper {
|
||||
/// The ratlines which we are routing.
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
|
|
|
|||
|
|
@ -130,13 +130,7 @@ impl<M: AccessMesadata> Autorouter<M> {
|
|||
ratlines: Vec<RatlineIndex>,
|
||||
) -> Result<(), AutorouterError> {
|
||||
for ratline in ratlines.iter() {
|
||||
let band = self
|
||||
.ratsnest
|
||||
.graph()
|
||||
.edge_weight(*ratline)
|
||||
.unwrap()
|
||||
.band_termseg
|
||||
.unwrap();
|
||||
let band = ratline.ref_(self).band_termseg();
|
||||
self.board
|
||||
.layout_mut()
|
||||
.remove_band(&mut LayoutEdit::new(), band)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use crate::{
|
|||
autorouter::{
|
||||
autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper},
|
||||
invoker::GetDebugOverlayData,
|
||||
permuter::{PermuteRatlines, RatlinesPermuter, SccPermutationsRatlinePermuter},
|
||||
permuter::{PermuteRatlines, RatlinesPermuter},
|
||||
presorter::{PresortRatlines, SccIntersectionsAndLengthPresorter},
|
||||
ratline::RatlineIndex,
|
||||
Autorouter, AutorouterError, AutorouterOptions,
|
||||
},
|
||||
|
|
@ -33,10 +34,12 @@ impl AutorouteExecutionPermutator {
|
|||
ratlines: Vec<RatlineIndex>,
|
||||
options: AutorouterOptions,
|
||||
) -> Result<Self, AutorouterError> {
|
||||
let mut permuter = RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new(
|
||||
autorouter, ratlines, &options,
|
||||
));
|
||||
let initially_sorted_ratlines = permuter.next_ratlines_permutation(autorouter).unwrap();
|
||||
let presorter = SccIntersectionsAndLengthPresorter::new(autorouter, &ratlines);
|
||||
let initially_sorted_ratlines = presorter.presort_ratlines(autorouter, &ratlines);
|
||||
/*let permuter = RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new(
|
||||
autorouter, ratlines, presorter, &options,
|
||||
));*/
|
||||
let permuter = RatlinesPermuter::new(autorouter, ratlines, presorter, &options);
|
||||
|
||||
Ok(Self {
|
||||
stepper: AutorouteExecutionStepper::new(
|
||||
|
|
@ -68,7 +71,8 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, AutorouteContinue
|
|||
}
|
||||
|
||||
loop {
|
||||
let Some(permutation) = self.permuter.next_ratlines_permutation(autorouter)
|
||||
let Some(permutation) =
|
||||
self.permuter.permute_ratlines(autorouter, &self.stepper)
|
||||
else {
|
||||
return Ok(ControlFlow::Break(None));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,26 +2,35 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::iter::Skip;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use itertools::{Itertools, Permutations};
|
||||
use petgraph::graph::NodeIndex;
|
||||
use specctra_core::mesadata::AccessMesadata;
|
||||
|
||||
use crate::autorouter::{
|
||||
presorter::SccIntersectionsAndLengthPresorter, ratline::RatlineIndex, Autorouter,
|
||||
AutorouterOptions,
|
||||
use crate::{
|
||||
autorouter::{
|
||||
autoroute::AutorouteExecutionStepper, presorter::SccIntersectionsAndLengthPresorter,
|
||||
ratline::RatlineIndex, Autorouter, AutorouterOptions,
|
||||
},
|
||||
drawing::graph::MakePrimitive,
|
||||
geometry::{GenericNode, GetLayer},
|
||||
graph::MakeRef,
|
||||
};
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait PermuteRatlines {
|
||||
fn next_ratlines_permutation(
|
||||
fn permute_ratlines(
|
||||
&mut self,
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
stepper: &AutorouteExecutionStepper,
|
||||
) -> Option<Vec<RatlineIndex>>;
|
||||
}
|
||||
|
||||
#[enum_dispatch(PermuteRatlines)]
|
||||
pub enum RatlinesPermuter {
|
||||
RatlineCuts(RatlineCutsRatlinePermuter),
|
||||
SccPermutations(SccPermutationsRatlinePermuter),
|
||||
}
|
||||
|
||||
|
|
@ -29,48 +38,53 @@ impl RatlinesPermuter {
|
|||
pub fn new(
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
presorter: SccIntersectionsAndLengthPresorter,
|
||||
options: &AutorouterOptions,
|
||||
) -> Self {
|
||||
RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new(
|
||||
autorouter, ratlines, options,
|
||||
autorouter, ratlines, presorter, options,
|
||||
))
|
||||
/*RatlinesPermuter::RatlineCuts(RatlineCutsRatlinePermuter::new(
|
||||
autorouter, ratlines, presorter, options,
|
||||
))*/
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SccPermutationsRatlinePermuter {
|
||||
sccs_permutations_iter: Permutations<std::vec::IntoIter<Vec<NodeIndex<usize>>>>,
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
sccs_permutations_iter: Skip<Permutations<std::vec::IntoIter<Vec<NodeIndex<usize>>>>>,
|
||||
original_ratlines: Vec<RatlineIndex>,
|
||||
}
|
||||
|
||||
impl SccPermutationsRatlinePermuter {
|
||||
pub fn new(
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
_autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
presorter: SccIntersectionsAndLengthPresorter,
|
||||
_options: &AutorouterOptions,
|
||||
) -> Self {
|
||||
// TODO: Instead of instantiating presorter again here, get it from
|
||||
// an argument.
|
||||
let presorter = SccIntersectionsAndLengthPresorter::new(autorouter, &ratlines);
|
||||
let sccs = presorter.dissolve();
|
||||
let sccs_len = sccs.len();
|
||||
|
||||
Self {
|
||||
sccs_permutations_iter: sccs.into_iter().permutations(sccs_len),
|
||||
ratlines,
|
||||
sccs_permutations_iter: sccs.into_iter().permutations(sccs_len).skip(1),
|
||||
original_ratlines: ratlines,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PermuteRatlines for SccPermutationsRatlinePermuter {
|
||||
fn next_ratlines_permutation(
|
||||
fn permute_ratlines(
|
||||
&mut self,
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
_stepper: &AutorouteExecutionStepper,
|
||||
) -> Option<Vec<RatlineIndex>> {
|
||||
let scc_permutation = self.sccs_permutations_iter.next()?;
|
||||
let mut ratlines = vec![];
|
||||
|
||||
for scc in scc_permutation {
|
||||
for ratline in self.ratlines.iter() {
|
||||
for ratline in self.original_ratlines.iter() {
|
||||
if scc.contains(
|
||||
&autorouter
|
||||
.ratsnest()
|
||||
|
|
@ -94,3 +108,68 @@ impl PermuteRatlines for SccPermutationsRatlinePermuter {
|
|||
Some(ratlines)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RatlineCutsRatlinePermuter {
|
||||
//sccs: Vec<Vec<NodeIndex<usize>>>,
|
||||
}
|
||||
|
||||
impl RatlineCutsRatlinePermuter {
|
||||
pub fn new(
|
||||
_autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
_ratlines: Vec<RatlineIndex>,
|
||||
_presorter: SccIntersectionsAndLengthPresorter,
|
||||
_options: &AutorouterOptions,
|
||||
) -> Self {
|
||||
/*Self {
|
||||
sccs: presorter.dissolve(),
|
||||
}*/
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl PermuteRatlines for RatlineCutsRatlinePermuter {
|
||||
fn permute_ratlines(
|
||||
&mut self,
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
stepper: &AutorouteExecutionStepper,
|
||||
) -> Option<Vec<RatlineIndex>> {
|
||||
let curr_ratline = stepper.ratlines()[*stepper.curr_ratline_index()];
|
||||
let endpoint_dots = curr_ratline.ref_(autorouter).endpoint_dots();
|
||||
let bands_cut_by_ratline: Vec<_> = autorouter
|
||||
.board()
|
||||
.layout()
|
||||
.bands_between_nodes(
|
||||
endpoint_dots
|
||||
.0
|
||||
.primitive(autorouter.board().layout().drawing())
|
||||
.layer(),
|
||||
GenericNode::Primitive(endpoint_dots.0.into()),
|
||||
GenericNode::Primitive(endpoint_dots.1.into()),
|
||||
)
|
||||
.collect();
|
||||
|
||||
// Find the first ratline corresponding to a band that is cut.
|
||||
let first_cut_ratline_index = stepper
|
||||
.ratlines()
|
||||
.iter()
|
||||
.position(|ratline| {
|
||||
for (band_uid, _) in &bands_cut_by_ratline {
|
||||
if ratline.ref_(autorouter).band_termseg() == band_uid.0
|
||||
|| ratline.ref_(autorouter).band_termseg() == band_uid.1
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// Swap the first ratline corresponding to a band that is cut with the
|
||||
// ratline that we have failed routing.
|
||||
let mut ratlines = stepper.ratlines().clone();
|
||||
ratlines.swap(*stepper.curr_ratline_index(), first_cut_ratline_index);
|
||||
|
||||
Some(ratlines)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ use crate::{
|
|||
#[enum_dispatch]
|
||||
pub trait PresortRatlines {
|
||||
fn presort_ratlines(
|
||||
&mut self,
|
||||
&self,
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
ratlines: &[RatlineIndex],
|
||||
) -> Vec<RatlineIndex>;
|
||||
}
|
||||
|
||||
|
|
@ -37,14 +37,13 @@ pub struct SccIntersectionsAndLengthPresorter {
|
|||
impl SccIntersectionsAndLengthPresorter {
|
||||
pub fn new(
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
ratlines: &Vec<RatlineIndex>,
|
||||
ratlines: &[RatlineIndex],
|
||||
) -> Self {
|
||||
// FIXME: Unnecessary copy.
|
||||
let mut filtered_ratsnest = autorouter.ratsnest().graph().clone();
|
||||
filtered_ratsnest.retain_edges(|_g, i| ratlines.contains(&i));
|
||||
|
||||
let mut sccs = tarjan_scc(&filtered_ratsnest);
|
||||
let sccs_len = sccs.len();
|
||||
|
||||
sccs.sort_unstable_by(|a, b| {
|
||||
// FIXME: These calculations should probably be stored somewhere
|
||||
|
|
@ -149,9 +148,9 @@ impl SccIntersectionsAndLengthPresorter {
|
|||
|
||||
impl PresortRatlines for SccIntersectionsAndLengthPresorter {
|
||||
fn presort_ratlines(
|
||||
&mut self,
|
||||
&self,
|
||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||
ratlines: Vec<RatlineIndex>,
|
||||
ratlines: &[RatlineIndex],
|
||||
) -> Vec<RatlineIndex> {
|
||||
let mut presorted_ratlines = vec![];
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
|||
Self { index, autorouter }
|
||||
}
|
||||
|
||||
pub fn band_termseg(&self) -> BandTermsegIndex {
|
||||
self.autorouter
|
||||
.ratsnest()
|
||||
.graph()
|
||||
.edge_weight(self.index)
|
||||
.unwrap()
|
||||
.band_termseg
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn endpoint_dots(&self) -> (FixedDotIndex, FixedDotIndex) {
|
||||
let (source, target) = self
|
||||
.autorouter
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ impl Ratsnest {
|
|||
let node_bound = layout.drawing().geometry().graph().node_bound();
|
||||
|
||||
for layer in 0..layout.drawing().layer_count() {
|
||||
let mut handle_rvw = |maybe_net: Option<usize>, vertex: RatvertexIndex, pos: Point| {
|
||||
let mut handle_ratvertex_weight =
|
||||
|maybe_net: Option<usize>, vertex: RatvertexIndex, pos: Point| {
|
||||
if let Some(net) = maybe_net {
|
||||
triangulations
|
||||
.entry((layer, net))
|
||||
|
|
@ -104,7 +105,7 @@ impl Ratsnest {
|
|||
// Dots that are parts of polys are ignored because ratlines
|
||||
// should only go to their centerpoints.
|
||||
if layout.drawing().compounds(dot).next().is_none() {
|
||||
handle_rvw(
|
||||
handle_ratvertex_weight(
|
||||
layout.drawing().primitive(dot).maybe_net(),
|
||||
RatvertexIndex::FixedDot(dot),
|
||||
node.primitive(layout.drawing()).shape().center(),
|
||||
|
|
@ -114,7 +115,7 @@ impl Ratsnest {
|
|||
}
|
||||
|
||||
for poly in layout.layer_poly_nodes(layer) {
|
||||
handle_rvw(
|
||||
handle_ratvertex_weight(
|
||||
layout.drawing().compound_weight(poly.into()).maybe_net(),
|
||||
RatvertexIndex::Poly(poly),
|
||||
poly.ref_(layout).shape().center(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue