mirror of https://codeberg.org/topola/topola.git
Add methods to obtain pin and component attractions
This commit is contained in:
parent
6cebbb2816
commit
4c6f5b4c43
|
|
@ -22,7 +22,7 @@ use undoredo::{Delta, Recorder};
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{
|
layout::{
|
||||||
LayerId, Layout, LayoutHalfDelta,
|
LayerId, Layout, LayoutHalfDelta,
|
||||||
compounds::{ComponentId, NetId, PinId},
|
compounds::{ComponentId, NetId, PinId, PinSpec},
|
||||||
},
|
},
|
||||||
vector::Vector2,
|
vector::Vector2,
|
||||||
};
|
};
|
||||||
|
|
@ -43,7 +43,11 @@ pub struct Board {
|
||||||
impl Board {
|
impl Board {
|
||||||
/*pub fn new(boundary: Vec<Vector2<i64>>, layer_count: usize) -> Self {
|
/*pub fn new(boundary: Vec<Vector2<i64>>, layer_count: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
layout: Layout::new(boundary.into_iter().map(Into::into).collect(), layer_count),
|
layout: Layout::new(
|
||||||
|
boundary.into_iter().map(Into::into).collect(),
|
||||||
|
layer_count,
|
||||||
|
0,
|
||||||
|
),
|
||||||
component_names: Recorder::new(BiBTreeMap::new()),
|
component_names: Recorder::new(BiBTreeMap::new()),
|
||||||
pin_names: Recorder::new(BiBTreeMap::new()),
|
pin_names: Recorder::new(BiBTreeMap::new()),
|
||||||
layer_descs: Recorder::new(BiBTreeMap::new()),
|
layer_descs: Recorder::new(BiBTreeMap::new()),
|
||||||
|
|
@ -60,6 +64,7 @@ impl Board {
|
||||||
layout: Layout::new(
|
layout: Layout::new(
|
||||||
boundary.into_iter().map(Into::into).collect(),
|
boundary.into_iter().map(Into::into).collect(),
|
||||||
layer_descs.len(),
|
layer_descs.len(),
|
||||||
|
net_names.len(),
|
||||||
),
|
),
|
||||||
component_names: Recorder::new(BiBTreeMap::new()),
|
component_names: Recorder::new(BiBTreeMap::new()),
|
||||||
pin_names: Recorder::new(BiBTreeMap::new()),
|
pin_names: Recorder::new(BiBTreeMap::new()),
|
||||||
|
|
@ -79,12 +84,12 @@ impl Board {
|
||||||
component_id
|
component_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_named_pin(&mut self, pin_name: String, net_id: Option<NetId>) -> PinId {
|
pub fn ensure_named_pin(&mut self, pin_name: String, pin_spec: PinSpec) -> PinId {
|
||||||
if let Some(pin) = self.pin_names.get_by_right(&pin_name) {
|
if let Some(pin) = self.pin_names.get_by_right(&pin_name) {
|
||||||
return *pin;
|
return *pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
let pin_id = self.layout.insert_pin(net_id);
|
let pin_id = self.layout.insert_pin(pin_spec);
|
||||||
self.pin_names.insert(pin_id, pin_name);
|
self.pin_names.insert(pin_id, pin_name);
|
||||||
|
|
||||||
pin_id
|
pin_id
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Topola contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
Layout, Vector2,
|
||||||
|
layout::compounds::{ComponentId, PinId},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl Layout {
|
||||||
|
pub fn component_attractions(
|
||||||
|
&self,
|
||||||
|
attractee: ComponentId,
|
||||||
|
) -> impl Iterator<Item = Vector2<i64>> + '_ {
|
||||||
|
self.component(attractee)
|
||||||
|
.pins
|
||||||
|
.iter()
|
||||||
|
.flat_map(move |&pin_id| self.pin_attractions(pin_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pin_attractions(&self, attractee: PinId) -> impl Iterator<Item = Vector2<i64>> + '_ {
|
||||||
|
self.pin(attractee)
|
||||||
|
.spec
|
||||||
|
.net
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(move |net_id| {
|
||||||
|
self.nets[net_id.index()]
|
||||||
|
.pins
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(move |&attractor| attractor != attractee)
|
||||||
|
.map(move |attractor| self.pin_pin_attraction(attractee, attractor))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pin_pin_attraction(&self, attractee: PinId, attractor: PinId) -> Vector2<i64> {
|
||||||
|
self.pin_centroid(attractor) - self.pin_centroid(attractee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ use derive_more::{Constructor, From};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
PinId,
|
||||||
layout::primitives::{JointId, PolygonId, SegmentId, ViaId},
|
layout::primitives::{JointId, PolygonId, SegmentId, ViaId},
|
||||||
primitives::PrimitiveId,
|
primitives::PrimitiveId,
|
||||||
};
|
};
|
||||||
|
|
@ -35,6 +36,7 @@ impl ComponentId {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
|
pub pins: Vec<PinId>,
|
||||||
pub joints: Vec<JointId>,
|
pub joints: Vec<JointId>,
|
||||||
pub segments: Vec<SegmentId>,
|
pub segments: Vec<SegmentId>,
|
||||||
pub vias: Vec<ViaId>,
|
pub vias: Vec<ViaId>,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,13 @@
|
||||||
use derive_more::{Constructor, From};
|
use derive_more::{Constructor, From};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::layout::primitives::{JointId, PolygonId, SegmentId, ViaId};
|
use crate::{
|
||||||
|
Layout, Vector2,
|
||||||
|
layout::{
|
||||||
|
compounds::{ComponentId, NetId},
|
||||||
|
primitives::{JointId, PolygonId, SegmentId, ViaId},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
|
|
@ -30,8 +36,15 @@ impl PinId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct PinSpec {
|
||||||
|
pub component: Option<ComponentId>,
|
||||||
|
pub net: Option<NetId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct Pin {
|
pub struct Pin {
|
||||||
|
pub spec: PinSpec,
|
||||||
pub joints: Vec<JointId>,
|
pub joints: Vec<JointId>,
|
||||||
pub segments: Vec<SegmentId>,
|
pub segments: Vec<SegmentId>,
|
||||||
pub vias: Vec<ViaId>,
|
pub vias: Vec<ViaId>,
|
||||||
|
|
@ -39,7 +52,45 @@ pub struct Pin {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pin {
|
impl Pin {
|
||||||
pub fn new() -> Self {
|
pub fn new(spec: PinSpec) -> Self {
|
||||||
Default::default()
|
Pin {
|
||||||
|
spec,
|
||||||
|
joints: Vec::new(),
|
||||||
|
segments: Vec::new(),
|
||||||
|
vias: Vec::new(),
|
||||||
|
polygons: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Layout {
|
||||||
|
pub fn pin_centroid(&self, pin_id: PinId) -> Vector2<i64> {
|
||||||
|
let pin = self.pin(pin_id);
|
||||||
|
let mut sum = Vector2::new(0, 0);
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
for &joint_id in &pin.joints {
|
||||||
|
sum = sum + self.joint(joint_id).center();
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
for &segment_id in &pin.segments {
|
||||||
|
sum = sum + self.segment(segment_id).center();
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
for &via_id in &pin.vias {
|
||||||
|
sum = sum + self.via(via_id).position;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
for &polygon_id in &pin.polygons {
|
||||||
|
sum = sum + self.polygon(polygon_id).center();
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return Vector2::new(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = count as i64;
|
||||||
|
Vector2::new(sum.x / count, sum.y / count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -392,7 +392,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primitive_net(&self, primitive: PrimitiveId) -> Option<NetId> {
|
pub fn primitive_net(&self, primitive: PrimitiveId) -> Option<NetId> {
|
||||||
match primitive {
|
match primitive {
|
||||||
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.net,
|
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.net,
|
||||||
PrimitiveId::Segment(segment_id) => self.segment(segment_id).net,
|
PrimitiveId::Segment(segment_id) => self.segment(segment_id).net,
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,9 @@
|
||||||
use rstar::primitives::GeomWithData;
|
use rstar::primitives::GeomWithData;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Pin, PinId,
|
|
||||||
layout::{
|
layout::{
|
||||||
Layout,
|
Layout,
|
||||||
compounds::{Component, ComponentId, NetId},
|
compounds::{Component, ComponentId, Pin, PinId, PinSpec},
|
||||||
},
|
},
|
||||||
primitives::{
|
primitives::{
|
||||||
Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId,
|
Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId,
|
||||||
|
|
@ -21,10 +20,16 @@ impl Layout {
|
||||||
ComponentId::new(self.components.push(Component::new()))
|
ComponentId::new(self.components.push(Component::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_pin(&mut self, net_id: Option<NetId>) -> PinId {
|
pub fn insert_pin(&mut self, spec: PinSpec) -> PinId {
|
||||||
let pin_id = PinId::new(self.pins.push(Pin::new()));
|
let pin_id = PinId::new(self.pins.push(Pin::new(spec)));
|
||||||
|
|
||||||
if let Some(net_id) = net_id {
|
if let Some(component_id) = spec.component {
|
||||||
|
self.components.modify(component_id.index(), |component| {
|
||||||
|
component.pins.push(pin_id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(net_id) = spec.net {
|
||||||
self.nets
|
self.nets
|
||||||
.modify(net_id.index(), |net| net.pins.push(pin_id));
|
.modify(net_id.index(), |net| net.pins.push(pin_id));
|
||||||
}
|
}
|
||||||
|
|
@ -33,11 +38,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_joint(&mut self, spec: JointSpec) -> JointId {
|
pub fn insert_joint(&mut self, spec: JointSpec) -> JointId {
|
||||||
let joint = Joint {
|
let joint = Joint::new(spec);
|
||||||
spec,
|
|
||||||
segments: Vec::new(),
|
|
||||||
vias: Vec::new(),
|
|
||||||
};
|
|
||||||
let bbox = joint.bbox();
|
let bbox = joint.bbox();
|
||||||
let component_id = joint.spec.component;
|
let component_id = joint.spec.component;
|
||||||
let pin_id = joint.spec.pin;
|
let pin_id = joint.spec.pin;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
mod attraction;
|
||||||
mod bbox;
|
mod bbox;
|
||||||
pub mod compounds;
|
pub mod compounds;
|
||||||
mod delete;
|
mod delete;
|
||||||
|
|
@ -90,14 +91,19 @@ pub struct Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub fn new(boundary: Vec<[i64; 2]>, layer_count: usize) -> Self {
|
pub fn new(boundary: Vec<[i64; 2]>, layer_count: usize, net_count: usize) -> Self {
|
||||||
|
let mut nets = StableVec::new();
|
||||||
|
for _ in 0..net_count {
|
||||||
|
nets.push(Net::default());
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
boundary: boundary.clone(),
|
boundary: boundary.clone(),
|
||||||
place_boundary: boundary,
|
place_boundary: boundary,
|
||||||
layer_count,
|
layer_count,
|
||||||
|
|
||||||
components: Recorder::new(StableVec::new()),
|
components: Recorder::new(StableVec::new()),
|
||||||
nets: Recorder::new(StableVec::new()),
|
nets: Recorder::new(nets),
|
||||||
pins: Recorder::new(StableVec::new()),
|
pins: Recorder::new(StableVec::new()),
|
||||||
|
|
||||||
joints: Recorder::new(StableVec::new()),
|
joints: Recorder::new(StableVec::new()),
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,14 @@ pub struct Joint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Joint {
|
impl Joint {
|
||||||
|
pub fn new(spec: JointSpec) -> Self {
|
||||||
|
Joint {
|
||||||
|
spec,
|
||||||
|
segments: Vec::new(),
|
||||||
|
vias: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn center(&self) -> Vector2<i64> {
|
pub fn center(&self) -> Vector2<i64> {
|
||||||
self.spec.position
|
self.spec.position
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ pub use polygon::*;
|
||||||
pub use segment::*;
|
pub use segment::*;
|
||||||
pub use via::*;
|
pub use via::*;
|
||||||
|
|
||||||
|
use crate::{Layout, PinId};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, From, Ord, PartialEq, PartialOrd, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, From, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
pub enum PrimitiveId {
|
pub enum PrimitiveId {
|
||||||
Joint(JointId),
|
Joint(JointId),
|
||||||
|
|
@ -22,3 +24,14 @@ pub enum PrimitiveId {
|
||||||
Via(ViaId),
|
Via(ViaId),
|
||||||
Polygon(PolygonId),
|
Polygon(PolygonId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Layout {
|
||||||
|
pub fn primitive_pin(&self, primitive: PrimitiveId) -> Option<PinId> {
|
||||||
|
match primitive {
|
||||||
|
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.pin,
|
||||||
|
PrimitiveId::Segment(segment_id) => self.segment(segment_id).spec.pin,
|
||||||
|
PrimitiveId::Via(via_id) => self.via(via_id).spec.pin,
|
||||||
|
PrimitiveId::Polygon(polygon_id) => self.polygon(polygon_id).pin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,10 @@ use specctra::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
board::{Board, LayerDesc, LayerSide, LayerType},
|
board::{Board, LayerDesc, LayerSide, LayerType},
|
||||||
layout::LayerId,
|
layout::{
|
||||||
layout::compounds::{ComponentId, NetId, PinId},
|
LayerId,
|
||||||
|
compounds::{ComponentId, NetId, PinId, PinSpec},
|
||||||
|
},
|
||||||
primitives::{JointSpec, Polygon, Segment, SegmentSpec},
|
primitives::{JointSpec, Polygon, Segment, SegmentSpec},
|
||||||
vector::Vector2,
|
vector::Vector2,
|
||||||
};
|
};
|
||||||
|
|
@ -161,7 +163,13 @@ impl Board {
|
||||||
let pin_name = format!("{}-{}", place.name, pin.id);
|
let pin_name = format!("{}-{}", place.name, pin.id);
|
||||||
let net_id = pin_nets.get(&pin_name).copied();
|
let net_id = pin_nets.get(&pin_name).copied();
|
||||||
|
|
||||||
let pin_id = board.ensure_named_pin(pin_name.clone(), net_id);
|
let pin_id = board.ensure_named_pin(
|
||||||
|
pin_name.clone(),
|
||||||
|
PinSpec {
|
||||||
|
component: Some(component_id),
|
||||||
|
net: net_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
|
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
|
||||||
|
|
||||||
for shape in padstack.shapes.iter() {
|
for shape in padstack.shapes.iter() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue