feat(autorouter/anterouter): Add option to set fanout clearance

This commit is contained in:
Mikolaj Wielgus 2025-10-07 22:37:50 +02:00
parent 506104a6a7
commit a3521e7286
21 changed files with 189 additions and 125 deletions

View File

@ -5,6 +5,7 @@
use clap::Parser; use clap::Parser;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use topola::autorouter::anterouter::AnterouterOptions;
use topola::autorouter::execution::Command; use topola::autorouter::execution::Command;
use topola::autorouter::history::History; use topola::autorouter::history::History;
use topola::autorouter::invoker::Invoker; use topola::autorouter::invoker::Invoker;
@ -41,7 +42,7 @@ fn main() -> Result<(), std::io::Error> {
AutorouterOptions { AutorouterOptions {
presort_by: PresortBy::RatlineIntersectionCountAndLength, presort_by: PresortBy::RatlineIntersectionCountAndLength,
permutate: true, permutate: true,
router_options: RouterOptions { router: RouterOptions {
wrap_around_bands: true, wrap_around_bands: true,
squeeze_through_under_bends: false, squeeze_through_under_bends: false,
routed_band_width: 100.0, routed_band_width: 100.0,

View File

@ -10,7 +10,9 @@ use crate::{
}; };
use egui::{Context, Ui}; use egui::{Context, Ui};
use topola::autorouter::{AutorouterOptions, PresortBy}; use topola::autorouter::{
multilayer_autoroute::MultilayerAutorouterOptions, AutorouterOptions, PresortBy,
};
pub struct FileActions { pub struct FileActions {
pub open_design: Trigger, pub open_design: Trigger,
@ -334,7 +336,7 @@ impl RouteActions {
tr: &Translator, tr: &Translator,
have_workspace: bool, have_workspace: bool,
workspace_activities_enabled: bool, workspace_activities_enabled: bool,
autorouter_options: &mut AutorouterOptions, multilayer_autorouter_options: &mut MultilayerAutorouterOptions,
) -> egui::InnerResponse<()> { ) -> egui::InnerResponse<()> {
ui.add_enabled_ui(have_workspace, |ui| { ui.add_enabled_ui(have_workspace, |ui| {
ui.add_enabled_ui(workspace_activities_enabled, |ui| { ui.add_enabled_ui(workspace_activities_enabled, |ui| {
@ -345,33 +347,43 @@ impl RouteActions {
ui.separator(); ui.separator();
ui.label(tr.text("tr-menu-route-routed-band-width")); ui.label(tr.text("tr-menu-route-routed-band-width"));
ui.add( ui.add(
egui::widgets::Slider::new( egui::widgets::Slider::new(
&mut autorouter_options.router_options.routed_band_width, &mut multilayer_autorouter_options.planar.router.routed_band_width,
1.0..=1000.0, 1.0..=1000.0,
) )
.suffix(""), .suffix(""),
); );
ui.label(tr.text("tr-menu-route-fanout-clearance"));
ui.add(
egui::widgets::Slider::new(
&mut multilayer_autorouter_options.anterouter.fanout_clearance,
0.0..=1000.0,
)
.suffix(""),
);
ui.separator(); ui.separator();
ui.menu_button(tr.text("tr-menu-options"), |ui| { ui.menu_button(tr.text("tr-menu-options"), |ui| {
egui::ComboBox::from_label(tr.text("tr-menu-route-options-presort-by")) egui::ComboBox::from_label(tr.text("tr-menu-route-options-presort-by"))
.selected_text(format!("{:?}", autorouter_options.presort_by)) .selected_text(format!("{:?}", multilayer_autorouter_options.planar.presort_by))
.show_ui(ui, |ui| { .show_ui(ui, |ui| {
ui.selectable_value(&mut autorouter_options.presort_by, PresortBy::RatlineIntersectionCountAndLength, tr.text("tr-menu-route-options-presort-by-ratline-intersection-count-and-length")); ui.selectable_value(&mut multilayer_autorouter_options.planar.presort_by, PresortBy::RatlineIntersectionCountAndLength, tr.text("tr-menu-route-options-presort-by-ratline-intersection-count-and-length"));
ui.selectable_value(&mut autorouter_options.presort_by, PresortBy::PairwiseDetours, tr.text("tr-menu-route-options-presort-by-pairwise-detours")); ui.selectable_value(&mut multilayer_autorouter_options.planar.presort_by, PresortBy::PairwiseDetours, tr.text("tr-menu-route-options-presort-by-pairwise-detours"));
}); });
ui.checkbox(&mut autorouter_options.permutate, tr.text("tr-menu-route-options-permutate")); ui.checkbox(&mut multilayer_autorouter_options.planar.permutate, tr.text("tr-menu-route-options-permutate"));
ui.checkbox( ui.checkbox(
&mut autorouter_options &mut multilayer_autorouter_options
.router_options .planar
.router
.squeeze_through_under_bends, .squeeze_through_under_bends,
tr.text("tr-menu-route-options-squeeze-through-under-bends"), tr.text("tr-menu-route-options-squeeze-through-under-bends"),
); );
ui.checkbox( ui.checkbox(
&mut autorouter_options.router_options.wrap_around_bands, &mut multilayer_autorouter_options.planar.router.wrap_around_bands,
tr.text("tr-menu-route-options-wrap-around-bands"), tr.text("tr-menu-route-options-wrap-around-bands"),
); );
}); });

View File

@ -6,7 +6,8 @@ use std::{collections::BTreeSet, ops::ControlFlow, path::Path, sync::mpsc::Sende
use topola::{ use topola::{
autorouter::{ autorouter::{
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions, anterouter::AnterouterOptions, execution::Command, invoker::InvokerError,
multilayer_autoroute::MultilayerAutorouterOptions, selection::Selection, AutorouterOptions,
PresortBy, PresortBy,
}, },
board::AccessMesadata, board::AccessMesadata,
@ -25,7 +26,7 @@ use crate::{
}; };
pub struct MenuBar { pub struct MenuBar {
pub autorouter_options: AutorouterOptions, pub multilayer_autorouter_options: MultilayerAutorouterOptions,
pub is_placing_via: bool, pub is_placing_via: bool,
pub show_ratsnest: bool, pub show_ratsnest: bool,
pub show_navmesh: bool, pub show_navmesh: bool,
@ -45,15 +46,20 @@ pub struct MenuBar {
impl MenuBar { impl MenuBar {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
autorouter_options: AutorouterOptions { multilayer_autorouter_options: MultilayerAutorouterOptions {
anterouter: AnterouterOptions {
fanout_clearance: 100.0,
},
planar: AutorouterOptions {
presort_by: PresortBy::RatlineIntersectionCountAndLength, presort_by: PresortBy::RatlineIntersectionCountAndLength,
permutate: true, permutate: true,
router_options: RouterOptions { router: RouterOptions {
routed_band_width: 100.0, routed_band_width: 100.0,
wrap_around_bands: true, wrap_around_bands: true,
squeeze_through_under_bends: true, squeeze_through_under_bends: true,
}, },
}, },
},
is_placing_via: false, is_placing_via: false,
show_ratsnest: true, show_ratsnest: true,
show_navmesh: false, show_navmesh: false,
@ -160,7 +166,7 @@ impl MenuBar {
tr, tr,
maybe_workspace.is_some(), maybe_workspace.is_some(),
workspace_activities_enabled, workspace_activities_enabled,
&mut self.autorouter_options, &mut self.multilayer_autorouter_options,
) )
}); });
@ -347,8 +353,9 @@ impl MenuBar {
allowed_edges: BTreeSet::new(), allowed_edges: BTreeSet::new(),
active_layer, active_layer,
routed_band_width: self routed_band_width: self
.autorouter_options .multilayer_autorouter_options
.router_options .planar
.router
.routed_band_width, .routed_band_width,
} }
}); });
@ -357,7 +364,7 @@ impl MenuBar {
schedule(error_dialog, workspace, |selection| { schedule(error_dialog, workspace, |selection| {
Command::MultilayerAutoroute( Command::MultilayerAutoroute(
selection.pin_selection, selection.pin_selection,
self.autorouter_options, self.multilayer_autorouter_options,
) )
}); });
} else if actions } else if actions
@ -366,7 +373,10 @@ impl MenuBar {
.consume_key_triggered(ctx, ui) .consume_key_triggered(ctx, ui)
{ {
schedule(error_dialog, workspace, |selection| { schedule(error_dialog, workspace, |selection| {
Command::Autoroute(selection.pin_selection, self.autorouter_options) Command::Autoroute(
selection.pin_selection,
self.multilayer_autorouter_options.planar,
)
}); });
} else if actions } else if actions
.inspect .inspect
@ -376,7 +386,7 @@ impl MenuBar {
schedule(error_dialog, workspace, |selection| { schedule(error_dialog, workspace, |selection| {
Command::CompareDetours( Command::CompareDetours(
selection.pin_selection, selection.pin_selection,
self.autorouter_options, self.multilayer_autorouter_options.planar,
) )
}); });
} else if actions } else if actions

View File

@ -119,7 +119,11 @@ impl Workspace {
to_layer: 0, to_layer: 0,
circle: Circle { circle: Circle {
pos: interactive_input.pointer_pos, pos: interactive_input.pointer_pos,
r: menu_bar.autorouter_options.router_options.routed_band_width r: menu_bar
.multilayer_autorouter_options
.planar
.router
.routed_band_width
/ 2.0, / 2.0,
}, },
maybe_net: Some(1234), maybe_net: Some(1234),

View File

@ -44,6 +44,7 @@ tr-menu-route-autoroute = Autoroute
tr-menu-route-planar-autoroute = Planar Autoroute tr-menu-route-planar-autoroute = Planar Autoroute
tr-menu-route-topo-autoroute = Topological planar Autoroute tr-menu-route-topo-autoroute = Topological planar Autoroute
tr-menu-route-routed-band-width = Routed Band Width tr-menu-route-routed-band-width = Routed Band Width
tr-menu-route-fanout-clearance = Fanout Clearance
tr-menu-help = Help tr-menu-help = Help
tr-menu-help-online-documentation = Online Documentation tr-menu-help-online-documentation = Online Documentation

View File

@ -4,9 +4,10 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use geo::{point, Point}; use geo::{point, Distance, Euclidean, Point};
use petgraph::graph::{EdgeIndex, NodeIndex}; use petgraph::graph::{EdgeIndex, NodeIndex};
use rstar::{Envelope, RTreeObject, AABB}; use rstar::{Envelope, RTreeObject, AABB};
use serde::{Deserialize, Serialize};
use specctra_core::mesadata::AccessMesadata; use specctra_core::mesadata::AccessMesadata;
use crate::{ use crate::{
@ -24,6 +25,11 @@ use crate::{
math::Circle, math::Circle,
}; };
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct AnterouterOptions {
pub fanout_clearance: f64,
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum TerminatingScheme { pub enum TerminatingScheme {
ExistingFixedDot(FixedDotIndex), ExistingFixedDot(FixedDotIndex),
@ -45,7 +51,11 @@ impl Anterouter {
Self { plan } Self { plan }
} }
pub fn anteroute(&mut self, autorouter: &mut Autorouter<impl AccessMesadata>) { pub fn anteroute(
&mut self,
autorouter: &mut Autorouter<impl AccessMesadata>,
options: &AnterouterOptions,
) {
// PERF: Unnecessary clone. // PERF: Unnecessary clone.
for (ratline, layer) in self.plan.layer_map.clone().iter() { for (ratline, layer) in self.plan.layer_map.clone().iter() {
let endpoint_indices = ratline.ref_(autorouter).endpoint_indices(); let endpoint_indices = ratline.ref_(autorouter).endpoint_indices();
@ -74,6 +84,7 @@ impl Anterouter {
*ratline, *ratline,
endpoint_dots.0, endpoint_dots.0,
*layer, *layer,
options,
), ),
} }
} }
@ -97,6 +108,7 @@ impl Anterouter {
*ratline, *ratline,
endpoint_dots.1, endpoint_dots.1,
*layer, *layer,
options,
), ),
} }
} }
@ -110,6 +122,7 @@ impl Anterouter {
ratline: EdgeIndex<usize>, ratline: EdgeIndex<usize>,
source_dot: FixedDotIndex, source_dot: FixedDotIndex,
target_layer: usize, target_layer: usize,
options: &AnterouterOptions,
) { ) {
let mut ratline_delta: Point = ratline.ref_(autorouter).line_segment().delta().into(); let mut ratline_delta: Point = ratline.ref_(autorouter).line_segment().delta().into();
@ -145,6 +158,7 @@ impl Anterouter {
small_bbox, small_bbox,
target_layer, target_layer,
CardinalDirection::nearest_to_vector(ratline_delta), CardinalDirection::nearest_to_vector(ratline_delta),
options,
) )
.is_ok() .is_ok()
{ {
@ -177,6 +191,7 @@ impl Anterouter {
large_bbox, large_bbox,
target_layer, target_layer,
CardinalDirection::nearest_to_vector(ratline_delta), CardinalDirection::nearest_to_vector(ratline_delta),
options,
) )
.is_ok() .is_ok()
{ {
@ -194,6 +209,7 @@ impl Anterouter {
bbox: AABB<[f64; 2]>, bbox: AABB<[f64; 2]>,
target_layer: usize, target_layer: usize,
preferred_cardinal_direction: CardinalDirection, preferred_cardinal_direction: CardinalDirection,
options: &AnterouterOptions,
) -> Result<(), ()> { ) -> Result<(), ()> {
if self if self
.anteroute_fanout_on_bbox_in_cardinal_direction( .anteroute_fanout_on_bbox_in_cardinal_direction(
@ -203,6 +219,7 @@ impl Anterouter {
bbox, bbox,
target_layer, target_layer,
preferred_cardinal_direction, preferred_cardinal_direction,
options,
) )
.is_ok() .is_ok()
{ {
@ -224,6 +241,7 @@ impl Anterouter {
bbox, bbox,
target_layer, target_layer,
counterclockwise_turning_cardinal_direction, counterclockwise_turning_cardinal_direction,
options,
) )
.is_ok() .is_ok()
{ {
@ -241,6 +259,7 @@ impl Anterouter {
bbox, bbox,
target_layer, target_layer,
clockwise_turning_cardinal_direction, clockwise_turning_cardinal_direction,
options,
) )
.is_ok() .is_ok()
{ {
@ -263,6 +282,7 @@ impl Anterouter {
bbox: AABB<[f64; 2]>, bbox: AABB<[f64; 2]>,
target_layer: usize, target_layer: usize,
cardinal_direction: CardinalDirection, cardinal_direction: CardinalDirection,
options: &AnterouterOptions,
) -> Result<(), ()> { ) -> Result<(), ()> {
let (_, dots) = self.place_fanout_via_on_bbox_in_cardinal_direction( let (_, dots) = self.place_fanout_via_on_bbox_in_cardinal_direction(
autorouter, autorouter,
@ -271,6 +291,7 @@ impl Anterouter {
bbox, bbox,
target_layer, target_layer,
cardinal_direction, cardinal_direction,
options,
)?; )?;
let layer = source_dot let layer = source_dot
@ -313,6 +334,7 @@ impl Anterouter {
bbox: AABB<[f64; 2]>, bbox: AABB<[f64; 2]>,
target_layer: usize, target_layer: usize,
cardinal_direction: CardinalDirection, cardinal_direction: CardinalDirection,
options: &AnterouterOptions,
) -> Result<(GenericIndex<ViaWeight>, Vec<FixedDotIndex>), ()> { ) -> Result<(GenericIndex<ViaWeight>, Vec<FixedDotIndex>), ()> {
let source_layer = autorouter let source_layer = autorouter
.board() .board()
@ -334,11 +356,21 @@ impl Anterouter {
.shape() .shape()
.center(); .center();
let bbox_to_anchor = Point::from(cardinal_direction) * 1.4; let cardinal_direction_vector = Point::from(cardinal_direction);
/*bbox_to_anchor *= 1.0
+ dbg!(
options.fanout_outer_length
/ Euclidean::distance(bbox_to_anchor, point! {x: 0.0, y: 0.0})
);*/
let bbox_anchor = point! { let bbox_anchor = point! {
x: center.x() + (bbox.upper()[0] - bbox.lower()[0]) / 2.0 * bbox_to_anchor.x(), x: (bbox.upper()[0] - bbox.lower()[0]) / 2.0 * cardinal_direction_vector.x(),
y: center.y() + (bbox.upper()[1] - bbox.lower()[1]) / 2.0 * bbox_to_anchor.y(), y: (bbox.upper()[1] - bbox.lower()[1]) / 2.0 * cardinal_direction_vector.y(),
}; };
let pos = center
+ bbox_anchor
* (1.0
+ options.fanout_clearance
/ Euclidean::distance(bbox_anchor, point! {x: 0.0, y: 0.0}));
//let via_bbox_to_anchor = [-pin_bbox_to_anchor[0], -pin_bbox_to_anchor[1]]; //let via_bbox_to_anchor = [-pin_bbox_to_anchor[0], -pin_bbox_to_anchor[1]];
@ -349,10 +381,7 @@ impl Anterouter {
ViaWeight { ViaWeight {
from_layer: std::cmp::min(source_layer, target_layer), from_layer: std::cmp::min(source_layer, target_layer),
to_layer: std::cmp::max(source_layer, target_layer), to_layer: std::cmp::max(source_layer, target_layer),
circle: Circle { circle: Circle { pos, r: 100.0 },
pos: bbox_anchor,
r: 100.0,
},
maybe_net: pin_maybe_net, maybe_net: pin_maybe_net,
}, },
autorouter autorouter

View File

@ -12,8 +12,9 @@ use thiserror::Error;
use crate::{ use crate::{
autorouter::{ autorouter::{
multilayer_autoroute::MultilayerAutorouteExecutionStepper, multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions},
permutator::PlanarAutorouteExecutionPermutator, planner::Planner, permutator::PlanarAutorouteExecutionPermutator,
planner::Planner,
}, },
board::{AccessMesadata, Board}, board::{AccessMesadata, Board},
drawing::band::BandTermsegIndex, drawing::band::BandTermsegIndex,
@ -45,7 +46,7 @@ pub enum PresortBy {
pub struct AutorouterOptions { pub struct AutorouterOptions {
pub presort_by: PresortBy, pub presort_by: PresortBy,
pub permutate: bool, pub permutate: bool,
pub router_options: RouterOptions, pub router: RouterOptions,
} }
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone)]
@ -111,7 +112,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn multilayer_autoroute( pub fn multilayer_autoroute(
&mut self, &mut self,
selection: &PinSelection, selection: &PinSelection,
options: AutorouterOptions, options: MultilayerAutorouterOptions,
) -> Result<MultilayerAutorouteExecutionStepper, AutorouterError> { ) -> Result<MultilayerAutorouteExecutionStepper, AutorouterError> {
let planner = Planner::new(self, &self.selected_ratlines(selection)); let planner = Planner::new(self, &self.selected_ratlines(selection));

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
autorouter::{ autorouter::{
multilayer_autoroute::MultilayerAutorouteExecutionStepper, multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions},
permutator::PlanarAutorouteExecutionPermutator, permutator::PlanarAutorouteExecutionPermutator,
}, },
board::{edit::BoardEdit, AccessMesadata}, board::{edit::BoardEdit, AccessMesadata},
@ -33,7 +33,7 @@ type Type = PinSelection;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Command { pub enum Command {
Autoroute(PinSelection, AutorouterOptions), // TODO: Rename to PlanarAutoroute. Autoroute(PinSelection, AutorouterOptions), // TODO: Rename to PlanarAutoroute.
MultilayerAutoroute(PinSelection, AutorouterOptions), MultilayerAutoroute(PinSelection, MultilayerAutorouterOptions),
TopoAutoroute { TopoAutoroute {
selection: PinSelection, selection: PinSelection,
#[serde(default, skip_serializing_if = "BTreeSet::is_empty")] #[serde(default, skip_serializing_if = "BTreeSet::is_empty")]

View File

@ -4,11 +4,12 @@
use std::ops::ControlFlow; use std::ops::ControlFlow;
use serde::{Deserialize, Serialize};
use specctra_core::mesadata::AccessMesadata; use specctra_core::mesadata::AccessMesadata;
use crate::{ use crate::{
autorouter::{ autorouter::{
anterouter::{Anterouter, AnterouterPlan}, anterouter::{Anterouter, AnterouterOptions, AnterouterPlan},
invoker::GetDebugOverlayData, invoker::GetDebugOverlayData,
permutator::PlanarAutorouteExecutionPermutator, permutator::PlanarAutorouteExecutionPermutator,
planar_autoroute::PlanarAutorouteContinueStatus, planar_autoroute::PlanarAutorouteContinueStatus,
@ -22,6 +23,12 @@ use crate::{
stepper::{Abort, EstimateProgress, Step}, stepper::{Abort, EstimateProgress, Step},
}; };
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct MultilayerAutorouterOptions {
pub anterouter: AnterouterOptions,
pub planar: AutorouterOptions,
}
pub struct MultilayerAutorouteExecutionStepper { pub struct MultilayerAutorouteExecutionStepper {
planar: PlanarAutorouteExecutionPermutator, planar: PlanarAutorouteExecutionPermutator,
} }
@ -31,13 +38,13 @@ impl MultilayerAutorouteExecutionStepper {
autorouter: &mut Autorouter<impl AccessMesadata>, autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>, ratlines: Vec<RatlineIndex>,
plan: AnterouterPlan, plan: AnterouterPlan,
options: AutorouterOptions, options: MultilayerAutorouterOptions,
) -> Result<Self, AutorouterError> { ) -> Result<Self, AutorouterError> {
let mut assigner = Anterouter::new(plan); let mut assigner = Anterouter::new(plan);
assigner.anteroute(autorouter); assigner.anteroute(autorouter, &options.anterouter);
Ok(Self { Ok(Self {
planar: PlanarAutorouteExecutionPermutator::new(autorouter, ratlines, options)?, planar: PlanarAutorouteExecutionPermutator::new(autorouter, ratlines, options.planar)?,
}) })
} }
} }

View File

@ -72,7 +72,7 @@ impl PlanarAutorouteExecutionStepper {
}; };
let (origin, destination) = ratlines[0].ref_(autorouter).terminating_dots(); let (origin, destination) = ratlines[0].ref_(autorouter).terminating_dots();
let mut router = Router::new(autorouter.board.layout_mut(), options.router_options); let mut router = Router::new(autorouter.board.layout_mut(), options.router);
Ok(Self { Ok(Self {
ratlines, ratlines,
@ -81,7 +81,7 @@ impl PlanarAutorouteExecutionStepper {
LayoutEdit::new(), LayoutEdit::new(),
origin, origin,
destination, destination,
options.router_options.routed_band_width, options.router.routed_band_width,
)?), )?),
layout_edits: vec![], layout_edits: vec![],
board_data_edits: vec![], board_data_edits: vec![],
@ -108,13 +108,13 @@ impl PlanarAutorouteExecutionStepper {
autorouter.board.apply_edit(&board_edit.reverse()); autorouter.board.apply_edit(&board_edit.reverse());
let (origin, destination) = self.ratlines[index].ref_(autorouter).terminating_dots(); let (origin, destination) = self.ratlines[index].ref_(autorouter).terminating_dots();
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options); let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
self.route = Some(router.route( self.route = Some(router.route(
LayoutEdit::new(), LayoutEdit::new(),
origin, origin,
destination, destination,
self.options.router_options.routed_band_width, self.options.router.routed_band_width,
)?); )?);
self.curr_ratline_index = index; self.curr_ratline_index = index;
@ -162,13 +162,13 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
.ref_(autorouter) .ref_(autorouter)
.terminating_dots(); .terminating_dots();
let ret = let ret = if let Some(band_termseg) =
if let Some(band_termseg) = autorouter.board.band_between_nodes(origin, destination) { autorouter.board.band_between_nodes(origin, destination)
{
PlanarAutorouteContinueStatus::Skipped(band_termseg[false]) PlanarAutorouteContinueStatus::Skipped(band_termseg[false])
} else { } else {
let band_termseg = { let band_termseg = {
let mut router = let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
Router::new(autorouter.board.layout_mut(), self.options.router_options);
let ControlFlow::Break(band_termseg) = route.step(&mut router)? else { let ControlFlow::Break(band_termseg) = route.step(&mut router)? else {
return Ok(ControlFlow::Continue( return Ok(ControlFlow::Continue(
@ -208,8 +208,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
if let Some(new_ratline) = self.ratlines.get(self.curr_ratline_index) { if let Some(new_ratline) = self.ratlines.get(self.curr_ratline_index) {
let (origin, destination) = new_ratline.ref_(autorouter).terminating_dots(); let (origin, destination) = new_ratline.ref_(autorouter).terminating_dots();
let mut router = let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
Router::new(autorouter.board.layout_mut(), self.options.router_options);
self.dissolve_route_stepper_and_push_layout_edit(); self.dissolve_route_stepper_and_push_layout_edit();
let recorder = LayoutEdit::new(); let recorder = LayoutEdit::new();
@ -218,7 +217,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
recorder, recorder,
origin, origin,
destination, destination,
self.options.router_options.routed_band_width, self.options.router.routed_band_width,
)?); )?);
} }

View File

@ -37,7 +37,7 @@ impl PointrouteExecutionStepper {
FixedDotWeight(GeneralDotWeight { FixedDotWeight(GeneralDotWeight {
circle: Circle { circle: Circle {
pos: point, pos: point,
r: options.router_options.routed_band_width / 2.0, r: options.router.routed_band_width / 2.0,
}, },
layer: 0, layer: 0,
maybe_net: None, maybe_net: None,
@ -45,14 +45,14 @@ impl PointrouteExecutionStepper {
None, None,
); );
let mut router = Router::new(autorouter.board.layout_mut(), options.router_options); let mut router = Router::new(autorouter.board.layout_mut(), options.router);
Ok(Self { Ok(Self {
route: router.route( route: router.route(
LayoutEdit::new(), // TODO? LayoutEdit::new(), // TODO?
origin, origin,
destination, destination,
options.router_options.routed_band_width, options.router.routed_band_width,
)?, )?,
options, options,
}) })
@ -66,7 +66,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, BandTermsegIndex> for PointrouteExec
&mut self, &mut self,
autorouter: &mut Autorouter<M>, autorouter: &mut Autorouter<M>,
) -> Result<ControlFlow<BandTermsegIndex>, AutorouterError> { ) -> Result<ControlFlow<BandTermsegIndex>, AutorouterError> {
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options); let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
Ok(self.route.step(&mut router)?) Ok(self.route.step(&mut router)?)
} }
} }

View File

@ -14,7 +14,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0
@ -37,7 +37,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0

View File

@ -199,7 +199,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true

View File

@ -71,7 +71,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -118,7 +118,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -197,7 +197,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -228,7 +228,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -259,7 +259,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -290,7 +290,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -321,7 +321,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true

View File

@ -50,7 +50,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0
@ -109,7 +109,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0
@ -168,7 +168,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0
@ -227,7 +227,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0

View File

@ -38,7 +38,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true

View File

@ -30,7 +30,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0

View File

@ -79,7 +79,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true

View File

@ -14,7 +14,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -37,7 +37,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -60,7 +60,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -83,7 +83,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -106,7 +106,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -129,7 +129,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -152,7 +152,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -175,7 +175,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true
@ -198,7 +198,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true

View File

@ -50,7 +50,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0
@ -73,7 +73,7 @@
], ],
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"router_options": { "router": {
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true, "squeeze_through_under_bends": true,
"routed_band_width": 100.0 "routed_band_width": 100.0

View File

@ -211,7 +211,7 @@
{ {
"presort_by": "RatlineIntersectionCountAndLength", "presort_by": "RatlineIntersectionCountAndLength",
"permutate": true, "permutate": true,
"router_options": { "router": {
"routed_band_width": 100.0, "routed_band_width": 100.0,
"wrap_around_bands": true, "wrap_around_bands": true,
"squeeze_through_under_bends": true "squeeze_through_under_bends": true