diff --git a/Cargo.toml b/Cargo.toml index 04e873c..4878121 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,10 @@ thiserror.workspace = true path = "crates/specctra-core" features = ["rstar"] +[dependencies.topola-rules] +path = "crates/topola-rules" +features = ["serde"] + [dev-dependencies] serde_json.workspace = true diff --git a/src/autorouter/measure_length.rs b/src/autorouter/measure_length.rs index cd9b009..5e60fa9 100644 --- a/src/autorouter/measure_length.rs +++ b/src/autorouter/measure_length.rs @@ -43,7 +43,7 @@ impl MeasureLengthExecutionStepper { let mut length = 0.0; for selector in self.selection.selectors() { - let band = autorouter.board.bandname_band(&selector.band).unwrap().0; + let band = autorouter.board.bandname_band(&selector.band).unwrap()[false]; length += band.ref_(autorouter.board.layout().drawing()).length(); } diff --git a/src/autorouter/remove_bands.rs b/src/autorouter/remove_bands.rs index 758d7aa..7d201ec 100644 --- a/src/autorouter/remove_bands.rs +++ b/src/autorouter/remove_bands.rs @@ -41,7 +41,7 @@ impl RemoveBandsExecutionStepper { let mut edit = LayoutEdit::new(); for selector in self.selection.selectors() { - let band = autorouter.board.bandname_band(&selector.band).unwrap().0; + let band = autorouter.board.bandname_band(&selector.band).unwrap()[false]; autorouter.board.layout_mut().remove_band(&mut edit, band); } Ok(Some(edit)) diff --git a/src/board/mod.rs b/src/board/mod.rs index 0fab29f..90bd45c 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -13,6 +13,7 @@ use std::{cmp::Ordering, collections::BTreeMap}; use bimap::BiBTreeMap; use derive_getters::Getters; use serde::{Deserialize, Serialize}; +use topola_rules::OrderedPair; use crate::{ drawing::{ @@ -33,21 +34,7 @@ use crate::{ }; /// Represents a band between two pins. -#[derive(Clone, Debug, Deserialize, Eq, PartialOrd, Ord, PartialEq, Serialize)] -pub struct BandName(String, String); - -impl BandName { - /// Creates a new [`BandName`] and manages their order. - /// - /// This function ensures that the two pin names are sorted in lexicographical order, so that the smaller name always comes first. - pub fn new(pinname1: String, pinname2: String) -> Self { - if pinname1.cmp(&pinname2) == Ordering::Greater { - BandName(pinname2, pinname1) - } else { - BandName(pinname1, pinname2) - } - } -} +pub type BandName = OrderedPair; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum ResolvedSelector<'a> { @@ -290,14 +277,14 @@ impl Board { .unwrap() .to_string(); self.band_bandname - .insert(band, BandName::new(source_pinname, target_pinname)); + .insert(band, BandName::from((source_pinname, target_pinname))); } /// Finds a band between two pin names. pub fn band_between_pins(&self, pinname1: &str, pinname2: &str) -> Option { self.band_bandname // note: it doesn't matter in what order pinnames are given, the constructor sorts them - .get_by_right(&BandName::new(pinname1.to_string(), pinname2.to_string())) + .get_by_right(&BandName::from((pinname1.to_string(), pinname2.to_string()))) .copied() } diff --git a/src/drawing/band.rs b/src/drawing/band.rs index 2d8ae2b..300b24c 100644 --- a/src/drawing/band.rs +++ b/src/drawing/band.rs @@ -5,6 +5,7 @@ use core::{cmp, hash}; use enum_dispatch::enum_dispatch; use petgraph::stable_graph::NodeIndex; +use topola_rules::OrderedPair; use crate::{ geometry::shape::MeasureLength, @@ -19,54 +20,10 @@ use super::{ AccessRules, Drawing, }; -#[derive(Clone, Copy, Debug)] -pub struct BandUid(pub BandTermsegIndex, pub BandTermsegIndex); - -impl BandUid { - pub fn new(first_seg1: BandTermsegIndex, first_seg2: BandTermsegIndex) -> Self { - if first_seg1.petgraph_index() <= first_seg2.petgraph_index() { - BandUid(first_seg1, first_seg2) - } else { - BandUid(first_seg2, first_seg1) - } - } -} - -impl PartialEq for BandUid { - fn eq(&self, other: &Self) -> bool { - self.0.petgraph_index() == other.0.petgraph_index() - && self.1.petgraph_index() == other.1.petgraph_index() - } -} - -impl Eq for BandUid {} - -impl hash::Hash for BandUid { - fn hash(&self, state: &mut H) { - self.0.petgraph_index().hash(state); - self.1.petgraph_index().hash(state); - } -} - -impl cmp::PartialOrd for BandUid { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl cmp::Ord for BandUid { - fn cmp(&self, other: &Self) -> cmp::Ordering { - use cmp::Ordering as O; - match self.0.petgraph_index().cmp(&other.0.petgraph_index()) { - O::Less => O::Less, - O::Greater => O::Greater, - O::Equal => self.1.petgraph_index().cmp(&other.1.petgraph_index()), - } - } -} +pub type BandUid = OrderedPair; #[enum_dispatch(GetPetgraphIndex)] -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] pub enum BandTermsegIndex { Straight(LoneLooseSegIndex), Bended(SeqLooseSegIndex), diff --git a/src/drawing/collect.rs b/src/drawing/collect.rs index a3a2661..49c1e80 100644 --- a/src/drawing/collect.rs +++ b/src/drawing/collect.rs @@ -26,10 +26,10 @@ pub trait Collect { impl Collect for Drawing { fn loose_band_uid(&self, start_loose: LooseIndex) -> BandUid { - BandUid::new( + BandUid::from(( self.loose_band_first_seg(start_loose), self.loose_band_last_seg(start_loose), - ) + )) } fn bend_bow(&self, bend: LooseBendIndex) -> Vec { diff --git a/src/graph.rs b/src/graph.rs index fdb1ad4..a0d6ed2 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -80,6 +80,13 @@ impl Ord for GenericIndex { } } +impl core::hash::Hash for GenericIndex { + #[inline] + fn hash(&self, state: &mut H) { + self.node_index.hash(state); + } +} + impl GetPetgraphIndex for GenericIndex { #[inline] fn petgraph_index(&self) -> NodeIndex { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 04781b0..53d8c0d 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -208,7 +208,7 @@ pub fn assert_band_length( rel_err: f64, ) { let band = board.band_between_pins(source_pin, target_pin).unwrap(); - let band_length = band.0.ref_(board.layout().drawing()).length(); + let band_length = band[false].ref_(board.layout().drawing()).length(); assert!( (band_length - expected_length).abs() < expected_length * rel_err, "band_length = {}, expected_length = {}, epsilon = {}",