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"
features = ["rstar"]
[dependencies.topola-rules]
path = "crates/topola-rules"
features = ["serde"]
[dev-dependencies]
serde_json.workspace = true

View File

@ -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();
}

View File

@ -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))

View File

@ -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<String>;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ResolvedSelector<'a> {
@ -290,14 +277,14 @@ impl<M: AccessMesadata> Board<M> {
.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<BandUid> {
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()
}

View File

@ -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<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()),
}
}
}
pub type BandUid = OrderedPair<BandTermsegIndex>;
#[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),

View File

@ -26,10 +26,10 @@ pub trait Collect {
impl<CW: Copy, R: AccessRules> Collect for Drawing<CW, R> {
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<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> {
#[inline]
fn petgraph_index(&self) -> NodeIndex<usize> {

View File

@ -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 = {}",