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::{
|
||||
layout::{
|
||||
LayerId, Layout, LayoutHalfDelta,
|
||||
compounds::{ComponentId, NetId, PinId},
|
||||
compounds::{ComponentId, NetId, PinId, PinSpec},
|
||||
},
|
||||
vector::Vector2,
|
||||
};
|
||||
|
|
@ -43,7 +43,11 @@ pub struct Board {
|
|||
impl Board {
|
||||
/*pub fn new(boundary: Vec<Vector2<i64>>, layer_count: usize) -> 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()),
|
||||
pin_names: Recorder::new(BiBTreeMap::new()),
|
||||
layer_descs: Recorder::new(BiBTreeMap::new()),
|
||||
|
|
@ -60,6 +64,7 @@ impl Board {
|
|||
layout: Layout::new(
|
||||
boundary.into_iter().map(Into::into).collect(),
|
||||
layer_descs.len(),
|
||||
net_names.len(),
|
||||
),
|
||||
component_names: Recorder::new(BiBTreeMap::new()),
|
||||
pin_names: Recorder::new(BiBTreeMap::new()),
|
||||
|
|
@ -79,12 +84,12 @@ impl Board {
|
|||
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) {
|
||||
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);
|
||||
|
||||
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 crate::{
|
||||
PinId,
|
||||
layout::primitives::{JointId, PolygonId, SegmentId, ViaId},
|
||||
primitives::PrimitiveId,
|
||||
};
|
||||
|
|
@ -35,6 +36,7 @@ impl ComponentId {
|
|||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Component {
|
||||
pub pins: Vec<PinId>,
|
||||
pub joints: Vec<JointId>,
|
||||
pub segments: Vec<SegmentId>,
|
||||
pub vias: Vec<ViaId>,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,13 @@
|
|||
use derive_more::{Constructor, From};
|
||||
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(
|
||||
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 spec: PinSpec,
|
||||
pub joints: Vec<JointId>,
|
||||
pub segments: Vec<SegmentId>,
|
||||
pub vias: Vec<ViaId>,
|
||||
|
|
@ -39,7 +52,45 @@ pub struct Pin {
|
|||
}
|
||||
|
||||
impl Pin {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
pub fn new(spec: PinSpec) -> Self {
|
||||
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 {
|
||||
PrimitiveId::Joint(joint_id) => self.joint(joint_id).spec.net,
|
||||
PrimitiveId::Segment(segment_id) => self.segment(segment_id).net,
|
||||
|
|
|
|||
|
|
@ -5,10 +5,9 @@
|
|||
use rstar::primitives::GeomWithData;
|
||||
|
||||
use crate::{
|
||||
Pin, PinId,
|
||||
layout::{
|
||||
Layout,
|
||||
compounds::{Component, ComponentId, NetId},
|
||||
compounds::{Component, ComponentId, Pin, PinId, PinSpec},
|
||||
},
|
||||
primitives::{
|
||||
Joint, JointId, JointSpec, Polygon, PolygonId, Segment, SegmentId, SegmentSpec, Via, ViaId,
|
||||
|
|
@ -21,10 +20,16 @@ impl Layout {
|
|||
ComponentId::new(self.components.push(Component::new()))
|
||||
}
|
||||
|
||||
pub fn insert_pin(&mut self, net_id: Option<NetId>) -> PinId {
|
||||
let pin_id = PinId::new(self.pins.push(Pin::new()));
|
||||
pub fn insert_pin(&mut self, spec: PinSpec) -> PinId {
|
||||
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
|
||||
.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 {
|
||||
let joint = Joint {
|
||||
spec,
|
||||
segments: Vec::new(),
|
||||
vias: Vec::new(),
|
||||
};
|
||||
let joint = Joint::new(spec);
|
||||
let bbox = joint.bbox();
|
||||
let component_id = joint.spec.component;
|
||||
let pin_id = joint.spec.pin;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
mod attraction;
|
||||
mod bbox;
|
||||
pub mod compounds;
|
||||
mod delete;
|
||||
|
|
@ -90,14 +91,19 @@ pub struct 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 {
|
||||
boundary: boundary.clone(),
|
||||
place_boundary: boundary,
|
||||
layer_count,
|
||||
|
||||
components: Recorder::new(StableVec::new()),
|
||||
nets: Recorder::new(StableVec::new()),
|
||||
nets: Recorder::new(nets),
|
||||
pins: Recorder::new(StableVec::new()),
|
||||
|
||||
joints: Recorder::new(StableVec::new()),
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@ pub struct Joint {
|
|||
}
|
||||
|
||||
impl Joint {
|
||||
pub fn new(spec: JointSpec) -> Self {
|
||||
Joint {
|
||||
spec,
|
||||
segments: Vec::new(),
|
||||
vias: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn center(&self) -> Vector2<i64> {
|
||||
self.spec.position
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ pub use polygon::*;
|
|||
pub use segment::*;
|
||||
pub use via::*;
|
||||
|
||||
use crate::{Layout, PinId};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, From, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum PrimitiveId {
|
||||
Joint(JointId),
|
||||
|
|
@ -22,3 +24,14 @@ pub enum PrimitiveId {
|
|||
Via(ViaId),
|
||||
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::{
|
||||
board::{Board, LayerDesc, LayerSide, LayerType},
|
||||
layout::LayerId,
|
||||
layout::compounds::{ComponentId, NetId, PinId},
|
||||
layout::{
|
||||
LayerId,
|
||||
compounds::{ComponentId, NetId, PinId, PinSpec},
|
||||
},
|
||||
primitives::{JointSpec, Polygon, Segment, SegmentSpec},
|
||||
vector::Vector2,
|
||||
};
|
||||
|
|
@ -161,7 +163,13 @@ impl Board {
|
|||
let pin_name = format!("{}-{}", place.name, pin.id);
|
||||
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();
|
||||
|
||||
for shape in padstack.shapes.iter() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue