refactor(autorouter/autorouter): Store terminating dots in configuration instead of ratsnest

This commit is contained in:
Mikolaj Wielgus 2025-10-24 03:48:35 +02:00
parent 87f63fd96f
commit d896fe7322
11 changed files with 115 additions and 132 deletions

View File

@ -4,6 +4,7 @@
use std::collections::BTreeMap;
use derive_getters::Getters;
use geo::{point, Distance, Euclidean, Point};
use petgraph::graph::NodeIndex;
use rstar::{Envelope, RTreeObject, AABB};
@ -46,6 +47,7 @@ pub struct AnterouterPlan {
pub ratline_terminating_schemes: BTreeMap<(RatlineUid, FixedDotIndex), TerminatingScheme>,
}
#[derive(Getters)]
pub struct Anterouter {
plan: AnterouterPlan,
}
@ -60,7 +62,9 @@ impl Anterouter {
autorouter: &mut Autorouter<impl AccessMesadata>,
recorder: &mut BoardEdit,
options: &AnterouterOptions,
) {
) -> BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex> {
let mut terminating_dot_map = BTreeMap::new();
// PERF: Unnecessary clone.
for (ratline, layer) in self.plan.layer_map.clone().iter() {
let endpoint_indices = ratline.ref_(autorouter).endpoint_indices();
@ -77,14 +81,10 @@ impl Anterouter {
.get(&(*ratline, endpoint_dots.0))
{
match terminating_scheme {
TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter
.ratsnests
.on_principal_layer_mut(ratline.principal_layer)
.assign_terminating_dot_to_ratvertex(
endpoint_indices.0,
*layer,
*terminating_dot,
),
TerminatingScheme::ExistingFixedDot(terminating_dot) => {
terminating_dot_map
.insert((*ratline, endpoint_dots.0, *layer), *terminating_dot);
}
TerminatingScheme::Fanout => self.anteroute_fanout(
autorouter,
recorder,
@ -93,6 +93,7 @@ impl Anterouter {
endpoint_dots.0,
*layer,
options,
&mut terminating_dot_map,
),
}
}
@ -103,14 +104,10 @@ impl Anterouter {
.get(&(*ratline, endpoint_dots.1))
{
match terminating_scheme {
TerminatingScheme::ExistingFixedDot(terminating_dot) => autorouter
.ratsnests
.on_principal_layer_mut(ratline.principal_layer)
.assign_terminating_dot_to_ratvertex(
endpoint_indices.1,
*layer,
*terminating_dot,
),
TerminatingScheme::ExistingFixedDot(terminating_dot) => {
terminating_dot_map
.insert((*ratline, endpoint_dots.1, *layer), *terminating_dot);
}
TerminatingScheme::Fanout => self.anteroute_fanout(
autorouter,
recorder,
@ -119,10 +116,13 @@ impl Anterouter {
endpoint_dots.1,
*layer,
options,
&mut terminating_dot_map,
),
}
}
}
terminating_dot_map
}
fn anteroute_fanout(
@ -134,6 +134,7 @@ impl Anterouter {
source_dot: FixedDotIndex,
target_layer: usize,
options: &AnterouterOptions,
terminating_dot_map: &mut BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
) {
let mut ratline_delta: Point = ratline.ref_(autorouter).line_segment().delta().into();
@ -172,6 +173,7 @@ impl Anterouter {
target_layer,
CardinalDirection::nearest_from_vector(ratline_delta),
options,
terminating_dot_map,
)
.is_ok()
{
@ -207,6 +209,7 @@ impl Anterouter {
target_layer,
CardinalDirection::nearest_from_vector(ratline_delta),
options,
terminating_dot_map,
)
.is_ok()
{
@ -224,6 +227,7 @@ impl Anterouter {
target_layer,
OrdinalDirection::nearest_from_vector(ratline_delta),
options,
terminating_dot_map,
)
.is_ok()
{
@ -241,6 +245,7 @@ impl Anterouter {
target_layer,
OrdinalDirection::nearest_from_vector(ratline_delta),
options,
terminating_dot_map,
)
.is_ok()
{
@ -261,6 +266,7 @@ impl Anterouter {
target_layer: usize,
preferred_compass_direction: impl CompassDirection,
options: &AnterouterOptions,
terminating_dot_map: &mut BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
) -> Result<(), ()> {
if self
.anteroute_fanout_on_bbox_in_direction(
@ -273,6 +279,7 @@ impl Anterouter {
target_layer,
preferred_compass_direction,
options,
terminating_dot_map,
)
.is_ok()
{
@ -297,6 +304,7 @@ impl Anterouter {
target_layer,
counterclockwise_turning_cardinal_direction,
options,
terminating_dot_map,
)
.is_ok()
{
@ -317,6 +325,7 @@ impl Anterouter {
target_layer,
clockwise_turning_cardinal_direction,
options,
terminating_dot_map,
)
.is_ok()
{
@ -342,6 +351,7 @@ impl Anterouter {
target_layer: usize,
direction: impl Into<Point>,
options: &AnterouterOptions,
terminating_dot_map: &mut BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
) -> Result<(), ()> {
let (via, dots) = self.place_fanout_via_on_bbox_in_direction(
autorouter,
@ -353,6 +363,7 @@ impl Anterouter {
target_layer,
direction,
options,
terminating_dot_map,
)?;
let layer = source_dot
@ -401,6 +412,7 @@ impl Anterouter {
target_layer: usize,
direction: impl Into<Point>,
options: &AnterouterOptions,
terminating_dot_map: &mut BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
) -> Result<(GenericIndex<ViaWeight>, Vec<FixedDotIndex>), ()> {
let source_layer = autorouter
.board()
@ -460,10 +472,7 @@ impl Anterouter {
.layer()
})
.unwrap();
autorouter
.ratsnests
.on_principal_layer_mut(ratline.principal_layer)
.assign_terminating_dot_to_ratvertex(ratvertex, target_layer, *terminating_dot);
terminating_dot_map.insert((ratline, source_dot, target_layer), *terminating_dot);
Ok((via, dots))
} else {
Err(())

View File

@ -7,7 +7,7 @@ use geo::Point;
use petgraph::graph::NodeIndex;
use serde::{Deserialize, Serialize};
use spade::InsertionError;
use std::collections::BTreeSet;
use std::collections::{BTreeMap, BTreeSet};
use thiserror::Error;
use crate::{
@ -137,6 +137,7 @@ impl<M: AccessMesadata> Autorouter<M> {
self,
PlanarAutoroutePreconfigurerInput {
ratlines: self.selected_planar_ratlines(selection, options.principal_layer),
terminating_dot_map: BTreeMap::new(),
},
options,
)
@ -196,7 +197,7 @@ impl<M: AccessMesadata> Autorouter<M> {
active_layer,
allowed_edges,
ratlines.into_iter().filter_map(|ratline| {
let (origin, destination) = ratline.ref_(self).terminating_dots();
let (origin, destination) = ratline.ref_(self).endpoint_dots();
if navmesh
.as_ref()

View File

@ -48,12 +48,16 @@ impl MultilayerAutorouteExecutionStepper {
) -> Result<Self, AutorouterError> {
let mut anterouter = Anterouter::new(configuration.plan);
let mut anteroute_edit = BoardEdit::new();
anterouter.anteroute(autorouter, &mut anteroute_edit, &options.anterouter);
let terminating_dot_map =
anterouter.anteroute(autorouter, &mut anteroute_edit, &options.anterouter);
Ok(Self {
planar: PlanarAutorouteReconfigurator::new(
autorouter,
configuration.planar,
PlanarAutoroutePreconfigurerInput {
terminating_dot_map,
..configuration.planar
},
options.planar,
)?,
anteroute_edit,

View File

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
use std::ops::ControlFlow;
use std::{collections::BTreeMap, ops::ControlFlow};
use specctra_core::mesadata::AccessMesadata;
@ -49,6 +49,7 @@ impl MultilayerAutorouteReconfigurator {
plan: planner.plan().clone(),
planar: PlanarAutoroutePreconfigurerInput {
ratlines: input.ratlines.clone(),
terminating_dot_map: BTreeMap::new(),
},
};
let reconfigurer = MultilayerReconfigurer::new(autorouter, input.ratlines, &options);

View File

@ -5,7 +5,7 @@
//! Manages autorouting of ratlines in a layout, tracking status and processed
//! routing steps.
use std::ops::ControlFlow;
use std::{collections::BTreeMap, ops::ControlFlow};
use derive_getters::Getters;
@ -14,7 +14,7 @@ use crate::{
edit::{BoardDataEdit, BoardEdit},
AccessMesadata,
},
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex},
geometry::{edit::Edit, primitive::PrimitiveShape},
graph::MakeRef,
layout::LayoutEdit,
@ -32,6 +32,30 @@ use super::{
#[derive(Clone, Debug)]
pub struct PlanarAutorouteConfiguration {
pub ratlines: Vec<RatlineUid>,
pub terminating_dot_map: BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
}
impl PlanarAutorouteConfiguration {
pub fn ratline_terminating_dots(
&self,
autorouter: &Autorouter<impl AccessMesadata>,
ratline_index: usize,
) -> (FixedDotIndex, FixedDotIndex) {
let ratline = self.ratlines[ratline_index];
let endpoint_dots = ratline.ref_(autorouter).endpoint_dots();
let layer = ratline.ref_(autorouter).layer();
(
*self
.terminating_dot_map
.get(&(ratline, endpoint_dots.0, layer))
.unwrap_or(&endpoint_dots.0),
*self
.terminating_dot_map
.get(&(ratline, endpoint_dots.1, layer))
.unwrap_or(&endpoint_dots.1),
)
}
}
#[derive(Clone, Debug)]
@ -83,9 +107,7 @@ impl PlanarAutorouteExecutionStepper {
return Err(AutorouterError::NothingToRoute);
};
let (origin, destination) = configuration.ratlines[0]
.ref_(autorouter)
.terminating_dots();
let (origin, destination) = configuration.ratline_terminating_dots(autorouter, 0);
let mut router = Router::new(autorouter.board.layout_mut(), options.router);
Ok(Self {
@ -121,9 +143,9 @@ impl PlanarAutorouteExecutionStepper {
autorouter.board.apply_edit(&board_edit.reverse());
let (origin, destination) = self.configuration.ratlines[index]
.ref_(autorouter)
.terminating_dots();
let (origin, destination) = self
.configuration
.ratline_terminating_dots(autorouter, index);
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
self.route = Some(router.route(
@ -169,9 +191,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
))));
}
let (origin, destination) = self.configuration().ratlines[self.curr_ratline_index]
.ref_(autorouter)
.terminating_dots();
let (origin, destination) = self
.configuration
.ratline_terminating_dots(autorouter, self.curr_ratline_index);
let Some(ref mut route) = self.route else {
// May happen if stepper was aborted.
@ -226,7 +248,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
self.curr_ratline_index += 1;
if let Some(new_ratline) = self.configuration.ratlines.get(self.curr_ratline_index) {
let (origin, destination) = new_ratline.ref_(autorouter).terminating_dots();
let (origin, destination) = self
.configuration
.ratline_terminating_dots(autorouter, self.curr_ratline_index);
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
self.dissolve_route_stepper_and_push_layout_edit();

View File

@ -2,21 +2,25 @@
//
// SPDX-License-Identifier: MIT
use std::collections::BTreeSet;
use std::collections::{BTreeMap, BTreeSet};
use derive_getters::{Dissolve, Getters};
use enum_dispatch::enum_dispatch;
use petgraph::algo::tarjan_scc;
use specctra_core::mesadata::AccessMesadata;
use crate::autorouter::{
planar_autoroute::PlanarAutorouteConfiguration, ratline::RatlineUid, scc::Scc, Autorouter,
PlanarAutorouteOptions,
use crate::{
autorouter::{
planar_autoroute::PlanarAutorouteConfiguration, ratline::RatlineUid, scc::Scc, Autorouter,
PlanarAutorouteOptions,
},
drawing::dot::FixedDotIndex,
};
#[derive(Clone, Debug)]
pub struct PlanarAutoroutePreconfigurerInput {
pub ratlines: BTreeSet<RatlineUid>,
pub terminating_dot_map: BTreeMap<(RatlineUid, FixedDotIndex, usize), FixedDotIndex>,
}
pub struct PresortParams {
@ -102,6 +106,7 @@ impl PreconfigurePlanarAutoroute for SccIntersectionsAndLengthRatlinePlanarAutor
PlanarAutorouteConfiguration {
ratlines: presorted_ratlines,
terminating_dot_map: input.terminating_dot_map,
}
}
}

View File

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
use std::ops::ControlFlow;
use std::{collections::BTreeMap, ops::ControlFlow};
use specctra_core::mesadata::AccessMesadata;
@ -95,12 +95,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarReconfigura
return Ok(ControlFlow::Break(None));
};
match self.stepper.reconfigure(
autorouter,
PlanarAutorouteConfiguration {
ratlines: configuration,
},
) {
match self.stepper.reconfigure(autorouter, configuration) {
Ok(result) => {
return Ok(ControlFlow::Continue(ReconfiguratorStatus::Reconfigured(
result,

View File

@ -8,17 +8,12 @@ use enum_dispatch::enum_dispatch;
use itertools::{Itertools, Permutations};
use specctra_core::mesadata::AccessMesadata;
use crate::{
autorouter::{
planar_autoroute::{PlanarAutorouteConfiguration, PlanarAutorouteExecutionStepper},
planar_preconfigurer::SccIntersectionsAndLengthRatlinePlanarAutoroutePreconfigurer,
ratline::RatlineUid,
scc::Scc,
Autorouter, PlanarAutorouteOptions,
},
drawing::graph::MakePrimitiveRef,
geometry::{GenericNode, GetLayer},
graph::MakeRef,
use crate::autorouter::{
planar_autoroute::{PlanarAutorouteConfiguration, PlanarAutorouteExecutionStepper},
planar_preconfigurer::SccIntersectionsAndLengthRatlinePlanarAutoroutePreconfigurer,
ratline::RatlineUid,
scc::Scc,
Autorouter, PlanarAutorouteOptions,
};
#[enum_dispatch]
@ -27,12 +22,12 @@ pub trait MakeNextPlanarAutorouteConfiguration {
&mut self,
autorouter: &mut Autorouter<impl AccessMesadata>,
stepper: &PlanarAutorouteExecutionStepper,
) -> Option<Vec<RatlineUid>>;
) -> Option<PlanarAutorouteConfiguration>;
}
#[enum_dispatch(MakeNextPlanarAutorouteConfiguration)]
pub enum PlanarAutorouteReconfigurer {
RatlineCuts(RatlineCutsPlanarAutorouteReconfigurer),
//RatlineCuts(RatlineCutsPlanarAutorouteReconfigurer),
SccPermutations(SccPermutationsPlanarAutorouteReconfigurer),
}
@ -59,7 +54,7 @@ impl PlanarAutorouteReconfigurer {
pub struct SccPermutationsPlanarAutorouteReconfigurer {
sccs_permutations_iter: Skip<Permutations<std::vec::IntoIter<Scc>>>,
initial_configuration: PlanarAutorouteConfiguration,
preconfiguration: PlanarAutorouteConfiguration,
}
impl SccPermutationsPlanarAutorouteReconfigurer {
@ -76,7 +71,7 @@ impl SccPermutationsPlanarAutorouteReconfigurer {
Self {
sccs_permutations_iter: sccs.into_iter().permutations(sccs_len).skip(1),
initial_configuration: preconfiguration,
preconfiguration,
}
}
}
@ -86,12 +81,12 @@ impl MakeNextPlanarAutorouteConfiguration for SccPermutationsPlanarAutorouteReco
&mut self,
autorouter: &mut Autorouter<impl AccessMesadata>,
_stepper: &PlanarAutorouteExecutionStepper,
) -> Option<Vec<RatlineUid>> {
) -> Option<PlanarAutorouteConfiguration> {
let scc_permutation = self.sccs_permutations_iter.next()?;
let mut ratlines = vec![];
for scc in scc_permutation {
for ratline in self.initial_configuration.ratlines.iter() {
for ratline in self.preconfiguration.ratlines.iter() {
if scc.node_indices().contains(
&autorouter
.ratsnests()
@ -114,7 +109,10 @@ impl MakeNextPlanarAutorouteConfiguration for SccPermutationsPlanarAutorouteReco
}
}
Some(ratlines)
Some(PlanarAutorouteConfiguration {
ratlines,
..self.preconfiguration.clone()
})
}
}
@ -122,7 +120,7 @@ pub struct RatlineCutsPlanarAutorouteReconfigurer {
//sccs: Vec<Vec<NodeIndex<usize>>>,
}
impl RatlineCutsPlanarAutorouteReconfigurer {
/*impl RatlineCutsPlanarAutorouteReconfigurer {
pub fn new(
_autorouter: &mut Autorouter<impl AccessMesadata>,
_ratlines: Vec<RatlineUid>,
@ -134,16 +132,19 @@ impl RatlineCutsPlanarAutorouteReconfigurer {
}*/
Self {}
}
}
}*/
impl MakeNextPlanarAutorouteConfiguration for RatlineCutsPlanarAutorouteReconfigurer {
/*impl MakeNextPlanarAutorouteConfiguration for RatlineCutsPlanarAutorouteReconfigurer {
fn next_configuration(
&mut self,
autorouter: &mut Autorouter<impl AccessMesadata>,
stepper: &PlanarAutorouteExecutionStepper,
) -> Option<Vec<RatlineUid>> {
let curr_ratline = stepper.configuration().ratlines[*stepper.curr_ratline_index()];
let terminating_dots = curr_ratline.ref_(autorouter).terminating_dots();
let terminating_dots = stepper
.configuration()
.terminating_dots
.get(&(curr_ratline,));
let bands_cut_by_ratline: Vec<_> = autorouter
.board()
.layout()
@ -182,4 +183,4 @@ impl MakeNextPlanarAutorouteConfiguration for RatlineCutsPlanarAutorouteReconfig
Some(ratlines)
}
}
}*/

View File

@ -99,41 +99,6 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
(source_dot, target_dot)
}
pub fn terminating_dots(&self) -> (FixedDotIndex, FixedDotIndex) {
let (source, target) = self
.autorouter
.ratsnests()
.on_principal_layer(self.uid.principal_layer)
.graph()
.edge_endpoints(self.uid.index)
.unwrap();
let source_dot = self
.autorouter
.ratsnests()
.on_principal_layer(self.uid.principal_layer)
.graph()
.node_weight(source)
.unwrap()
.layer_terminating_dots
.get(&self.layer())
.copied()
.unwrap_or(self.endpoint_dots().0);
let target_dot = self
.autorouter
.ratsnests()
.on_principal_layer(self.uid.principal_layer)
.graph()
.node_weight(target)
.unwrap()
.layer_terminating_dots
.get(&self.layer())
.copied()
.unwrap_or(self.endpoint_dots().1);
(source_dot, target_dot)
}
pub fn layer(&self) -> usize {
self.autorouter
.ratsnests()

View File

@ -9,11 +9,7 @@ use std::{
use enum_dispatch::enum_dispatch;
use geo::Point;
use petgraph::{
data::Element,
graph::{EdgeIndex, NodeIndex},
prelude::StableUnGraph,
};
use petgraph::{data::Element, graph::EdgeIndex, prelude::StableUnGraph};
use spade::{handles::FixedVertexHandle, HasPosition, InsertionError, Point2};
use specctra_core::mesadata::AccessMesadata;
@ -54,7 +50,6 @@ impl From<RatvertexNodeIndex> for crate::layout::NodeIndex {
pub struct RatvertexWeight {
vertex: RatvertexNodeIndex,
pub pos: Point,
pub layer_terminating_dots: BTreeMap<usize, FixedDotIndex>,
}
impl GetTrianvertexNodeIndex<RatvertexNodeIndex> for RatvertexWeight {
@ -191,11 +186,7 @@ impl Ratsnest {
return Ok(());
}
triangulation.add_vertex(RatvertexWeight {
vertex,
pos,
layer_terminating_dots: BTreeMap::new(),
})?;
triangulation.add_vertex(RatvertexWeight { vertex, pos })?;
Ok(())
};
@ -230,19 +221,6 @@ impl Ratsnest {
Ok(())
}
pub fn assign_terminating_dot_to_ratvertex(
&mut self,
node_index: NodeIndex<usize>,
layer: usize,
terminating_dot: FixedDotIndex,
) {
self.graph
.node_weight_mut(node_index)
.unwrap()
.layer_terminating_dots
.insert(layer, terminating_dot);
}
pub fn assign_layer_to_ratline(&mut self, ratline_index: EdgeIndex<usize>, layer: usize) {
self.graph.edge_weight_mut(ratline_index).unwrap().layer = layer;
}

View File

@ -17,7 +17,7 @@ use topola::{
graph::{GetMaybeNet, MakePrimitiveRef, PrimitiveIndex},
primitive::MakePrimitiveShape,
},
geometry::{shape::MeasureLength, GenericNode, GetLayer},
geometry::{shape::MeasureLength, GenericNode},
graph::{GetIndex, MakeRef},
router::{navmesh::Navmesh, RouterOptions},
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},