topola/src/autorouter/permuter.rs

176 lines
5.4 KiB
Rust

// SPDX-FileCopyrightText: 2025 Topola contributors
//
// 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::{
autoroute::AutorouteExecutionStepper, presorter::SccIntersectionsAndLengthPresorter,
ratline::RatlineIndex, Autorouter, AutorouterOptions,
},
drawing::graph::MakePrimitiveRef,
geometry::{GenericNode, GetLayer},
graph::MakeRef,
};
#[enum_dispatch]
pub trait PermuteRatlines {
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),
}
impl RatlinesPermuter {
pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
presorter: SccIntersectionsAndLengthPresorter,
options: &AutorouterOptions,
) -> Self {
RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new(
autorouter, ratlines, presorter, options,
))
/*RatlinesPermuter::RatlineCuts(RatlineCutsRatlinePermuter::new(
autorouter, ratlines, presorter, options,
))*/
}
}
pub struct SccPermutationsRatlinePermuter {
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>,
ratlines: Vec<RatlineIndex>,
presorter: SccIntersectionsAndLengthPresorter,
_options: &AutorouterOptions,
) -> Self {
// TODO: Instead of instantiating presorter again here, get it from
// an argument.
let sccs = presorter.dissolve();
let sccs_len = sccs.len();
Self {
sccs_permutations_iter: sccs.into_iter().permutations(sccs_len).skip(1),
original_ratlines: ratlines,
}
}
}
impl PermuteRatlines for SccPermutationsRatlinePermuter {
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.original_ratlines.iter() {
if scc.contains(
&autorouter
.ratsnest()
.graph()
.edge_endpoints(*ratline)
.unwrap()
.0,
) && scc.contains(
&autorouter
.ratsnest()
.graph()
.edge_endpoints(*ratline)
.unwrap()
.1,
) {
ratlines.push(*ratline);
}
}
}
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_ref(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)
}
}