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

View File

@ -10,7 +10,9 @@ use crate::{
};
use egui::{Context, Ui};
use topola::autorouter::{AutorouterOptions, PresortBy};
use topola::autorouter::{
multilayer_autoroute::MultilayerAutorouterOptions, AutorouterOptions, PresortBy,
};
pub struct FileActions {
pub open_design: Trigger,
@ -334,7 +336,7 @@ impl RouteActions {
tr: &Translator,
have_workspace: bool,
workspace_activities_enabled: bool,
autorouter_options: &mut AutorouterOptions,
multilayer_autorouter_options: &mut MultilayerAutorouterOptions,
) -> egui::InnerResponse<()> {
ui.add_enabled_ui(have_workspace, |ui| {
ui.add_enabled_ui(workspace_activities_enabled, |ui| {
@ -345,33 +347,43 @@ impl RouteActions {
ui.separator();
ui.label(tr.text("tr-menu-route-routed-band-width"));
ui.add(
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,
)
.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.menu_button(tr.text("tr-menu-options"), |ui| {
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| {
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 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::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::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(
&mut autorouter_options
.router_options
&mut multilayer_autorouter_options
.planar
.router
.squeeze_through_under_bends,
tr.text("tr-menu-route-options-squeeze-through-under-bends"),
);
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"),
);
});

View File

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

View File

@ -119,7 +119,11 @@ impl Workspace {
to_layer: 0,
circle: Circle {
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,
},
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-topo-autoroute = Topological planar Autoroute
tr-menu-route-routed-band-width = Routed Band Width
tr-menu-route-fanout-clearance = Fanout Clearance
tr-menu-help = Help
tr-menu-help-online-documentation = Online Documentation

View File

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

View File

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

View File

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

View File

@ -4,11 +4,12 @@
use std::ops::ControlFlow;
use serde::{Deserialize, Serialize};
use specctra_core::mesadata::AccessMesadata;
use crate::{
autorouter::{
anterouter::{Anterouter, AnterouterPlan},
anterouter::{Anterouter, AnterouterOptions, AnterouterPlan},
invoker::GetDebugOverlayData,
permutator::PlanarAutorouteExecutionPermutator,
planar_autoroute::PlanarAutorouteContinueStatus,
@ -22,6 +23,12 @@ use crate::{
stepper::{Abort, EstimateProgress, Step},
};
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct MultilayerAutorouterOptions {
pub anterouter: AnterouterOptions,
pub planar: AutorouterOptions,
}
pub struct MultilayerAutorouteExecutionStepper {
planar: PlanarAutorouteExecutionPermutator,
}
@ -31,13 +38,13 @@ impl MultilayerAutorouteExecutionStepper {
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
plan: AnterouterPlan,
options: AutorouterOptions,
options: MultilayerAutorouterOptions,
) -> Result<Self, AutorouterError> {
let mut assigner = Anterouter::new(plan);
assigner.anteroute(autorouter);
assigner.anteroute(autorouter, &options.anterouter);
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 mut router = Router::new(autorouter.board.layout_mut(), options.router_options);
let mut router = Router::new(autorouter.board.layout_mut(), options.router);
Ok(Self {
ratlines,
@ -81,7 +81,7 @@ impl PlanarAutorouteExecutionStepper {
LayoutEdit::new(),
origin,
destination,
options.router_options.routed_band_width,
options.router.routed_band_width,
)?),
layout_edits: vec![],
board_data_edits: vec![],
@ -108,13 +108,13 @@ impl PlanarAutorouteExecutionStepper {
autorouter.board.apply_edit(&board_edit.reverse());
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(
LayoutEdit::new(),
origin,
destination,
self.options.router_options.routed_band_width,
self.options.router.routed_band_width,
)?);
self.curr_ratline_index = index;
@ -162,54 +162,53 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
.ref_(autorouter)
.terminating_dots();
let ret =
if let Some(band_termseg) = autorouter.board.band_between_nodes(origin, destination) {
PlanarAutorouteContinueStatus::Skipped(band_termseg[false])
} else {
let band_termseg = {
let mut router =
Router::new(autorouter.board.layout_mut(), self.options.router_options);
let ret = if let Some(band_termseg) =
autorouter.board.band_between_nodes(origin, destination)
{
PlanarAutorouteContinueStatus::Skipped(band_termseg[false])
} else {
let band_termseg = {
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router);
let ControlFlow::Break(band_termseg) = route.step(&mut router)? else {
return Ok(ControlFlow::Continue(
PlanarAutorouteContinueStatus::Running,
));
};
band_termseg
let ControlFlow::Break(band_termseg) = route.step(&mut router)? else {
return Ok(ControlFlow::Continue(
PlanarAutorouteContinueStatus::Running,
));
};
let band = autorouter
.board
.layout()
.drawing()
.find_loose_band_uid(band_termseg.into())
.expect("a completely routed band should've Seg's as ends");
autorouter.ratsnest.assign_band_termseg_to_ratline(
self.ratlines[self.curr_ratline_index],
band_termseg,
);
let mut board_data_edit = BoardDataEdit::new();
autorouter.board.try_set_band_between_nodes(
&mut board_data_edit,
origin,
destination,
band,
);
self.board_data_edits.push(board_data_edit);
PlanarAutorouteContinueStatus::Routed(band_termseg)
band_termseg
};
let band = autorouter
.board
.layout()
.drawing()
.find_loose_band_uid(band_termseg.into())
.expect("a completely routed band should've Seg's as ends");
autorouter.ratsnest.assign_band_termseg_to_ratline(
self.ratlines[self.curr_ratline_index],
band_termseg,
);
let mut board_data_edit = BoardDataEdit::new();
autorouter.board.try_set_band_between_nodes(
&mut board_data_edit,
origin,
destination,
band,
);
self.board_data_edits.push(board_data_edit);
PlanarAutorouteContinueStatus::Routed(band_termseg)
};
self.curr_ratline_index += 1;
if let Some(new_ratline) = self.ratlines.get(self.curr_ratline_index) {
let (origin, destination) = new_ratline.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.dissolve_route_stepper_and_push_layout_edit();
let recorder = LayoutEdit::new();
@ -218,7 +217,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteCo
recorder,
origin,
destination,
self.options.router_options.routed_band_width,
self.options.router.routed_band_width,
)?);
}

View File

@ -37,7 +37,7 @@ impl PointrouteExecutionStepper {
FixedDotWeight(GeneralDotWeight {
circle: Circle {
pos: point,
r: options.router_options.routed_band_width / 2.0,
r: options.router.routed_band_width / 2.0,
},
layer: 0,
maybe_net: None,
@ -45,14 +45,14 @@ impl PointrouteExecutionStepper {
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 {
route: router.route(
LayoutEdit::new(), // TODO?
origin,
destination,
options.router_options.routed_band_width,
options.router.routed_band_width,
)?,
options,
})
@ -66,7 +66,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, BandTermsegIndex> for PointrouteExec
&mut self,
autorouter: &mut Autorouter<M>,
) -> 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)?)
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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