feat: use OrderedPair instead of custon BandName/BandUid (note: changes ordering of BandUid)

This commit is contained in:
Ellen Emilia Anna Zscheile 2025-02-07 13:59:01 +01:00
parent 910ab5b76a
commit c5a87d9bdf
8 changed files with 23 additions and 68 deletions

View File

@ -61,6 +61,10 @@ thiserror.workspace = true
path = "crates/specctra-core" path = "crates/specctra-core"
features = ["rstar"] features = ["rstar"]
[dependencies.topola-rules]
path = "crates/topola-rules"
features = ["serde"]
[dev-dependencies] [dev-dependencies]
serde_json.workspace = true serde_json.workspace = true

View File

@ -43,7 +43,7 @@ impl MeasureLengthExecutionStepper {
let mut length = 0.0; let mut length = 0.0;
for selector in self.selection.selectors() { 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(); length += band.ref_(autorouter.board.layout().drawing()).length();
} }

View File

@ -41,7 +41,7 @@ impl RemoveBandsExecutionStepper {
let mut edit = LayoutEdit::new(); let mut edit = LayoutEdit::new();
for selector in self.selection.selectors() { 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); autorouter.board.layout_mut().remove_band(&mut edit, band);
} }
Ok(Some(edit)) Ok(Some(edit))

View File

@ -13,6 +13,7 @@ use std::{cmp::Ordering, collections::BTreeMap};
use bimap::BiBTreeMap; use bimap::BiBTreeMap;
use derive_getters::Getters; use derive_getters::Getters;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use topola_rules::OrderedPair;
use crate::{ use crate::{
drawing::{ drawing::{
@ -33,21 +34,7 @@ use crate::{
}; };
/// Represents a band between two pins. /// Represents a band between two pins.
#[derive(Clone, Debug, Deserialize, Eq, PartialOrd, Ord, PartialEq, Serialize)] pub type BandName = OrderedPair<String>;
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)
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ResolvedSelector<'a> { pub enum ResolvedSelector<'a> {
@ -290,14 +277,14 @@ impl<M: AccessMesadata> Board<M> {
.unwrap() .unwrap()
.to_string(); .to_string();
self.band_bandname 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. /// Finds a band between two pin names.
pub fn band_between_pins(&self, pinname1: &str, pinname2: &str) -> Option<BandUid> { pub fn band_between_pins(&self, pinname1: &str, pinname2: &str) -> Option<BandUid> {
self.band_bandname self.band_bandname
// note: it doesn't matter in what order pinnames are given, the constructor sorts them // 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() .copied()
} }

View File

@ -5,6 +5,7 @@
use core::{cmp, hash}; use core::{cmp, hash};
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use topola_rules::OrderedPair;
use crate::{ use crate::{
geometry::shape::MeasureLength, geometry::shape::MeasureLength,
@ -19,54 +20,10 @@ use super::{
AccessRules, Drawing, AccessRules, Drawing,
}; };
#[derive(Clone, Copy, Debug)] pub type BandUid = OrderedPair<BandTermsegIndex>;
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<H: hash::Hasher>(&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<cmp::Ordering> {
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()),
}
}
}
#[enum_dispatch(GetPetgraphIndex)] #[enum_dispatch(GetPetgraphIndex)]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub enum BandTermsegIndex { pub enum BandTermsegIndex {
Straight(LoneLooseSegIndex), Straight(LoneLooseSegIndex),
Bended(SeqLooseSegIndex), Bended(SeqLooseSegIndex),

View File

@ -26,10 +26,10 @@ pub trait Collect {
impl<CW: Copy, R: AccessRules> Collect for Drawing<CW, R> { impl<CW: Copy, R: AccessRules> Collect for Drawing<CW, R> {
fn loose_band_uid(&self, start_loose: LooseIndex) -> BandUid { fn loose_band_uid(&self, start_loose: LooseIndex) -> BandUid {
BandUid::new( BandUid::from((
self.loose_band_first_seg(start_loose), self.loose_band_first_seg(start_loose),
self.loose_band_last_seg(start_loose), self.loose_band_last_seg(start_loose),
) ))
} }
fn bend_bow(&self, bend: LooseBendIndex) -> Vec<PrimitiveIndex> { fn bend_bow(&self, bend: LooseBendIndex) -> Vec<PrimitiveIndex> {

View File

@ -80,6 +80,13 @@ impl<W> Ord for GenericIndex<W> {
} }
} }
impl<W> core::hash::Hash for GenericIndex<W> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.node_index.hash(state);
}
}
impl<W> GetPetgraphIndex for GenericIndex<W> { impl<W> GetPetgraphIndex for GenericIndex<W> {
#[inline] #[inline]
fn petgraph_index(&self) -> NodeIndex<usize> { fn petgraph_index(&self) -> NodeIndex<usize> {

View File

@ -208,7 +208,7 @@ pub fn assert_band_length(
rel_err: f64, rel_err: f64,
) { ) {
let band = board.band_between_pins(source_pin, target_pin).unwrap(); 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!( assert!(
(band_length - expected_length).abs() < expected_length * rel_err, (band_length - expected_length).abs() < expected_length * rel_err,
"band_length = {}, expected_length = {}, epsilon = {}", "band_length = {}, expected_length = {}, epsilon = {}",