From b568f2d7906ae6517247c5ff43dd250be6b99628 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 24 Jul 2024 14:59:28 +0200 Subject: [PATCH] autorouter: split selection into pin selection and band selection --- src/autorouter/autorouter.rs | 24 ++-- src/autorouter/invoker.rs | 17 +-- src/autorouter/selection.rs | 207 +++++++++++++++++++---------------- src/bin/topola-egui/top.rs | 3 +- src/board/board.rs | 7 +- 5 files changed, 142 insertions(+), 116 deletions(-) diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 9e4e5a5..1aa44f4 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -3,12 +3,6 @@ use spade::InsertionError; use thiserror::Error; use crate::{ - autorouter::{ - autoroute::Autoroute, - place_via::PlaceVia, - ratsnest::{Ratsnest, RatvertexIndex}, - selection::Selection, - }, board::{mesadata::AccessMesadata, Board}, drawing::{dot::FixedDotIndex, Infringement}, layout::via::ViaWeight, @@ -16,6 +10,13 @@ use crate::{ triangulation::GetTrianvertexNodeIndex, }; +use super::{ + autoroute::Autoroute, + place_via::PlaceVia, + ratsnest::{Ratsnest, RatvertexIndex}, + selection::{BandSelection, PinSelection}, +}; + #[derive(Error, Debug, Clone)] pub enum AutorouterError { #[error("nothing to route")] @@ -44,7 +45,7 @@ impl Autorouter { Ok(Self { board, ratsnest }) } - pub fn autoroute(&mut self, selection: &Selection) -> Result<(), AutorouterError> { + pub fn autoroute(&mut self, selection: &PinSelection) -> Result<(), AutorouterError> { let mut autoroute = self.autoroute_walk(selection)?; loop { @@ -59,11 +60,14 @@ impl Autorouter { } } - pub fn autoroute_walk(&mut self, selection: &Selection) -> Result { + pub fn autoroute_walk( + &mut self, + selection: &PinSelection, + ) -> Result { Autoroute::new(self, self.selected_ratlines(selection)) } - pub fn undo_autoroute(&mut self, selection: &Selection) { + pub fn undo_autoroute(&mut self, selection: &PinSelection) { for ratline in self.selected_ratlines(selection).iter() { let band = self .ratsnest @@ -120,7 +124,7 @@ impl Autorouter { (source_dot, target_dot) } - fn selected_ratlines(&self, selection: &Selection) -> Vec> { + fn selected_ratlines(&self, selection: &PinSelection) -> Vec> { self.ratsnest .graph() .edge_indices() diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 6e177a9..69b07fe 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -4,13 +4,6 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::{ - autorouter::{ - autoroute::Autoroute, - history::{History, HistoryError}, - place_via::PlaceVia, - selection::Selection, - Autorouter, AutorouterError, AutorouterStatus, - }, board::mesadata::AccessMesadata, drawing::graph::PrimitiveIndex, geometry::primitive::PrimitiveShape, @@ -18,6 +11,14 @@ use crate::{ router::{navmesh::Navmesh, trace::Trace}, }; +use super::{ + autoroute::Autoroute, + history::{History, HistoryError}, + place_via::PlaceVia, + selection::{BandSelection, PinSelection}, + Autorouter, AutorouterError, AutorouterStatus, +}; + #[enum_dispatch] pub trait GetMaybeNavmesh { fn maybe_navmesh(&self) -> Option<&Navmesh>; @@ -54,7 +55,7 @@ pub enum InvokerStatus { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Command { - Autoroute(Selection), + Autoroute(PinSelection), PlaceVia(ViaWeight), } diff --git a/src/autorouter/selection.rs b/src/autorouter/selection.rs index ea200da..345e145 100644 --- a/src/autorouter/selection.rs +++ b/src/autorouter/selection.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use serde::{Deserialize, Serialize}; use crate::{ - board::{mesadata::AccessMesadata, Board}, + board::{mesadata::AccessMesadata, BandName, Board}, drawing::{ band::BandUid, graph::{GetLayer, MakePrimitive, PrimitiveIndex}, @@ -14,117 +14,28 @@ use crate::{ }; #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] -pub struct Selector { +pub struct PinSelector { pin: String, layer: String, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Selection { - selectors: HashSet, - #[serde(skip)] - selected_bands: HashSet, +pub struct PinSelection { + selectors: HashSet, } -impl Selection { +impl PinSelection { pub fn new() -> Self { Self { selectors: HashSet::new(), - selected_bands: HashSet::new(), } } - pub fn new_select_all(board: &Board) -> Self { - let mut this = Self::new(); - - for node in board.layout().drawing().primitive_nodes() { - if let Some(selector) = this.node_selector(board, GenericNode::Primitive(node)) { - if !this.contains_node(board, GenericNode::Primitive(node)) { - this.select(board, selector); - } - } - } - - this - } - - pub fn new_select_layer(board: &Board, layer: usize) -> Self { - let mut this = Self::new(); - - for node in board.layout().drawing().layer_primitive_nodes(layer) { - if let Some(selector) = this.node_selector(board, GenericNode::Primitive(node)) { - if !this.contains_node(board, GenericNode::Primitive(node)) { - this.select(board, selector); - } - } - } - - this - } - - pub fn toggle_at_node(&mut self, board: &Board, node: NodeIndex) { - if let Some(selector) = self.node_selector(board, node) { - if self.contains_node(board, node) { - self.deselect(board, &selector); - } else { - self.select(board, selector); - } - } else if let Some(band) = self.node_band(board, node) { - if self.contains_node(board, node) { - self.deselect_band(board, band); - } else { - self.select_band(board, band); - } - } - } - - fn select(&mut self, _board: &Board, selector: Selector) { - self.selectors.insert(selector); - } - - fn deselect(&mut self, _board: &Board, selector: &Selector) { - self.selectors.remove(selector); - } - - fn select_band(&mut self, board: &Board, band: BandUid) { - self.selected_bands.insert(band); - } - - fn deselect_band(&mut self, board: &Board, band: BandUid) { - self.selected_bands.remove(&band); - } - - pub fn contains_node(&self, board: &Board, node: NodeIndex) -> bool { - if let Some(selector) = self.node_selector(board, node) { - self.selectors.contains(&selector) - } else if let Some(band) = self.node_band(board, node) { - self.selected_bands.contains(&band) - } else { - false - } - } - - fn node_band(&self, board: &Board, node: NodeIndex) -> Option { - let NodeIndex::Primitive(primitive) = node else { - return None; - }; - - let loose = match primitive { - PrimitiveIndex::LooseDot(dot) => dot.into(), - PrimitiveIndex::LoneLooseSeg(seg) => seg.into(), - PrimitiveIndex::SeqLooseSeg(seg) => seg.into(), - PrimitiveIndex::LooseBend(bend) => bend.into(), - _ => return None, - }; - - Some(board.layout().drawing().collect().loose_band_uid(loose)) - } - fn node_selector( &self, board: &Board, node: NodeIndex, - ) -> Option { + ) -> Option { let layer = match node { NodeIndex::Primitive(primitive) => { primitive.primitive(board.layout().drawing()).layer() @@ -146,7 +57,7 @@ impl Selection { board.node_pinname(node), board.layout().rules().layer_layername(layer), ) { - Some(Selector { + Some(PinSelector { pin: pinname.to_string(), layer: layername.to_string(), }) @@ -154,4 +65,108 @@ impl Selection { None } } + + fn select(&mut self, selector: PinSelector) { + self.selectors.insert(selector); + } + + fn deselect(&mut self, selector: &PinSelector) { + self.selectors.remove(selector); + } + + pub fn contains_node(&self, board: &Board, node: NodeIndex) -> bool { + self.node_selector(board, node) + .map_or(false, |selector| self.selectors.contains(&selector)) + } +} + +#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct BandSelector { + band: BandName, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BandSelection { + selectors: HashSet, +} + +impl BandSelection { + pub fn new() -> Self { + Self { + selectors: HashSet::new(), + } + } + + fn node_selector( + &self, + board: &Board, + node: NodeIndex, + ) -> Option { + let NodeIndex::Primitive(primitive) = node else { + return None; + }; + + let loose = match primitive { + PrimitiveIndex::LooseDot(dot) => dot.into(), + PrimitiveIndex::LoneLooseSeg(seg) => seg.into(), + PrimitiveIndex::SeqLooseSeg(seg) => seg.into(), + PrimitiveIndex::LooseBend(bend) => bend.into(), + _ => return None, + }; + + Some(BandSelector { + band: board + .band_bandname(board.layout().drawing().collect().loose_band_uid(loose))? + .clone(), + }) + } + + fn select(&mut self, selector: BandSelector) { + self.selectors.insert(selector); + } + + fn deselect(&mut self, selector: &BandSelector) { + self.selectors.remove(&selector); + } + + pub fn contains_node(&self, board: &Board, node: NodeIndex) -> bool { + self.node_selector(board, node) + .map_or(false, |selector| self.selectors.contains(&selector)) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Selection { + pub pin_selection: PinSelection, + pub band_selection: BandSelection, +} + +impl Selection { + pub fn new() -> Self { + Self { + pin_selection: PinSelection::new(), + band_selection: BandSelection::new(), + } + } + + pub fn toggle_at_node(&mut self, board: &Board, node: NodeIndex) { + if let Some(selector) = self.pin_selection.node_selector(board, node) { + if self.pin_selection.contains_node(board, node) { + self.pin_selection.deselect(&selector); + } else { + self.pin_selection.select(selector); + } + } else if let Some(selector) = self.band_selection.node_selector(board, node) { + if self.band_selection.contains_node(board, node) { + self.band_selection.deselect(&selector); + } else { + self.band_selection.select(selector); + } + } + } + + pub fn contains_node(&self, board: &Board, node: NodeIndex) -> bool { + self.pin_selection.contains_node(board, node) + || self.band_selection.contains_node(board, node) + } } diff --git a/src/bin/topola-egui/top.rs b/src/bin/topola-egui/top.rs index 027126d..f5dc512 100644 --- a/src/bin/topola-egui/top.rs +++ b/src/bin/topola-egui/top.rs @@ -207,7 +207,8 @@ impl Top { let selection = overlay.selection().clone(); overlay.clear_selection(); maybe_execute.insert(ExecuteWithStatus::new( - invoker.execute_walk(Command::Autoroute(selection))?, + invoker + .execute_walk(Command::Autoroute(selection.pin_selection))?, )); } } diff --git a/src/board/board.rs b/src/board/board.rs index d433945..eacebec 100644 --- a/src/board/board.rs +++ b/src/board/board.rs @@ -1,6 +1,7 @@ use std::{cmp::Ordering, collections::HashMap}; use bimap::BiHashMap; +use serde::{Deserialize, Serialize}; use crate::{ board::mesadata::AccessMesadata, @@ -19,7 +20,7 @@ use crate::{ math::Circle, }; -#[derive(Debug, Hash, Clone, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct BandName(String, String); impl BandName { @@ -151,6 +152,10 @@ impl Board { self.node_to_pinname.get(&node) } + pub fn band_bandname(&self, band: BandUid) -> Option<&BandName> { + self.band_bandname.get_by_left(&band) + } + pub fn try_set_band_between_nodes( &mut self, source: FixedDotIndex,