mirror of https://codeberg.org/topola/topola.git
feat(autorouter/anterouter): Add option to set fanout clearance
This commit is contained in:
parent
506104a6a7
commit
a3521e7286
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")]
|
||||||
|
|
|
||||||
|
|
@ -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)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue