Optionally assign primitives to pins

This commit is contained in:
Mikolaj Wielgus 2026-03-13 13:36:14 +01:00
parent 3f362d62c3
commit d77be1b0b3
3 changed files with 132 additions and 24 deletions

View File

@ -7,15 +7,10 @@ use derive_getters::{Dissolve, Getters};
use undoredo::{ApplyDelta, Delta, FlushDelta}; use undoredo::{ApplyDelta, Delta, FlushDelta};
use crate::layout::{ use crate::layout::{
Joint, JointId, Layout, LayoutHalfDelta, NetId, Polygon, PolygonId, Segment, SegmentId, Via, Joint, JointId, Layout, LayoutHalfDelta, NetId, PinId, Polygon, PolygonId, Segment, SegmentId,
ViaId, Via, ViaId,
}; };
struct Layer {
name: String,
index: usize,
}
#[derive(Clone, Debug, Getters)] #[derive(Clone, Debug, Getters)]
pub struct Board { pub struct Board {
layout: Layout, layout: Layout,
@ -23,6 +18,8 @@ pub struct Board {
layer_names: BiBTreeMap<usize, String>, layer_names: BiBTreeMap<usize, String>,
#[getter(skip)] #[getter(skip)]
net_names: BiBTreeMap<NetId, String>, net_names: BiBTreeMap<NetId, String>,
#[getter(skip)]
pin_names: BiBTreeMap<PinId, String>,
} }
impl Board { impl Board {
@ -31,6 +28,7 @@ impl Board {
layout: Layout::new(boundary, layer_count), layout: Layout::new(boundary, layer_count),
layer_names: BiBTreeMap::new(), layer_names: BiBTreeMap::new(),
net_names: BiBTreeMap::new(), net_names: BiBTreeMap::new(),
pin_names: BiBTreeMap::new(),
} }
} }
@ -44,9 +42,21 @@ impl Board {
layout: Layout::new(boundary, layer_count), layout: Layout::new(boundary, layer_count),
layer_names, layer_names,
net_names, net_names,
pin_names: BiBTreeMap::new(),
} }
} }
pub fn ensure_pin(&mut self, pin_name: String) -> PinId {
if let Some(pin) = self.pin_names.get_by_right(&pin_name) {
return *pin;
};
let pin_id = self.layout.add_pin();
self.pin_names.insert(pin_id, pin_name);
pin_id
}
pub fn add_joint(&mut self, joint: Joint) -> JointId { pub fn add_joint(&mut self, joint: Joint) -> JointId {
self.layout.add_joint(joint) self.layout.add_joint(joint)
} }

View File

@ -8,6 +8,42 @@ use derive_getters::{Dissolve, Getters};
use stable_vec::StableVec; use stable_vec::StableVec;
use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder}; use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PinId(usize);
impl PinId {
/// Wrap a pin index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
}
/// Returns the underlying index.
#[inline]
pub fn id(self) -> usize {
self.0
}
}
#[derive(Clone, Debug)]
pub struct Pin {
joints: Vec<JointId>,
segments: Vec<SegmentId>,
vias: Vec<ViaId>,
polygons: Vec<PolygonId>,
}
impl Pin {
pub fn new() -> Self {
Self {
joints: Vec::new(),
segments: Vec::new(),
vias: Vec::new(),
polygons: Vec::new(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct NetId(usize); pub struct NetId(usize);
@ -48,6 +84,7 @@ pub struct Joint {
pub layer: usize, pub layer: usize,
pub radius: u64, pub radius: u64,
pub net: NetId, pub net: NetId,
pub pin: Option<PinId>,
} }
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@ -73,6 +110,7 @@ pub struct Segment {
pub layer: usize, pub layer: usize,
pub half_width: u64, pub half_width: u64,
pub net: NetId, pub net: NetId,
pub pin: Option<PinId>,
} }
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@ -98,6 +136,7 @@ pub struct Via {
pub layer: usize, pub layer: usize,
pub radius: u64, pub radius: u64,
pub net: NetId, pub net: NetId,
pub pin: Option<PinId>,
} }
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@ -122,6 +161,7 @@ pub struct Polygon {
pub vertices: Vec<[i64; 2]>, pub vertices: Vec<[i64; 2]>,
pub layer: usize, pub layer: usize,
pub net: NetId, pub net: NetId,
pub pin: Option<PinId>,
} }
#[derive(Clone, Debug, Getters)] #[derive(Clone, Debug, Getters)]
@ -130,6 +170,7 @@ pub struct Layout {
place_boundary: Vec<[i64; 2]>, place_boundary: Vec<[i64; 2]>,
layer_count: usize, layer_count: usize,
pins: StableVec<Pin>,
joints: Recorder<StableVec<Joint>>, joints: Recorder<StableVec<Joint>>,
segments: Recorder<StableVec<Segment>>, segments: Recorder<StableVec<Segment>>,
vias: Recorder<StableVec<Via>>, vias: Recorder<StableVec<Via>>,
@ -143,6 +184,7 @@ impl Layout {
place_boundary: boundary, place_boundary: boundary,
layer_count, layer_count,
pins: StableVec::new(),
joints: Recorder::new(StableVec::new()), joints: Recorder::new(StableVec::new()),
segments: Recorder::new(StableVec::new()), segments: Recorder::new(StableVec::new()),
vias: Recorder::new(StableVec::new()), vias: Recorder::new(StableVec::new()),
@ -150,20 +192,52 @@ impl Layout {
} }
} }
pub fn add_pin(&mut self) -> PinId {
PinId::new(self.pins.push(Pin::new()))
}
pub fn add_joint(&mut self, joint: Joint) -> JointId { pub fn add_joint(&mut self, joint: Joint) -> JointId {
JointId::new(self.joints.push(joint)) let pin_id = joint.pin;
let joint_id = JointId::new(self.joints.push(joint));
if let Some(pin_id) = pin_id {
self.pins[pin_id.id()].joints.push(joint_id);
}
joint_id
} }
pub fn add_segment(&mut self, segment: Segment) -> SegmentId { pub fn add_segment(&mut self, segment: Segment) -> SegmentId {
SegmentId::new(self.segments.push(segment)) let pin_id = segment.pin;
let segment_id = SegmentId::new(self.segments.push(segment));
if let Some(pin_id) = pin_id {
self.pins[pin_id.id()].segments.push(segment_id);
}
segment_id
} }
pub fn add_via(&mut self, via: Via) -> ViaId { pub fn add_via(&mut self, via: Via) -> ViaId {
ViaId::new(self.vias.push(via)) let pin_id = via.pin;
let via_id = ViaId::new(self.vias.push(via));
if let Some(pin_id) = pin_id {
self.pins[pin_id.id()].vias.push(via_id);
}
via_id
} }
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId { pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
PolygonId::new(self.polygons.push(polygon)) let pin_id = polygon.pin;
let polygon_id = PolygonId::new(self.polygons.push(polygon));
if let Some(pin_id) = pin_id {
self.pins[pin_id.id()].polygons.push(polygon_id);
}
polygon_id
} }
pub fn segment_endpoints(&self, segment: SegmentId) -> [[i64; 2]; 2] { pub fn segment_endpoints(&self, segment: SegmentId) -> [[i64; 2]; 2] {
@ -173,6 +247,10 @@ impl Layout {
self.joints.get(&endjoints[1].id()).unwrap().position, self.joints.get(&endjoints[1].id()).unwrap().position,
] ]
} }
pub fn pin(&self, pin: PinId) -> &Pin {
&self.pins[pin.id()]
}
} }
#[derive(Clone, Debug, Dissolve)] #[derive(Clone, Debug, Dissolve)]

View File

@ -13,7 +13,7 @@ use specctra::{
use crate::{ use crate::{
Segment, Segment,
board::Board, board::Board,
layout::{Joint, NetId, Polygon}, layout::{Joint, NetId, PinId, Polygon},
math::Vector2, math::Vector2,
}; };
@ -104,6 +104,7 @@ impl Board {
for pin in &image.pins { for pin in &image.pins {
let pin_name = format!("{}-{}", place.name, pin.id); let pin_name = format!("{}-{}", place.name, pin.id);
let pin_id = board.ensure_pin(pin_name.clone());
let net = pin_nets.get(&pin_name).copied().unwrap(); let net = pin_nets.get(&pin_name).copied().unwrap();
let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap(); let padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap();
@ -118,6 +119,7 @@ impl Board {
(circle.diameter / 2.0) as u64, (circle.diameter / 2.0) as u64,
layer, layer,
net, net,
Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
} }
@ -133,6 +135,7 @@ impl Board {
rect.y2, rect.y2,
layer, layer,
net, net,
Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
} }
@ -146,6 +149,7 @@ impl Board {
path.width, path.width,
layer, layer,
net, net,
Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
} }
@ -159,6 +163,7 @@ impl Board {
polygon.width, polygon.width,
layer, layer,
net, net,
Some(pin_id),
!place_side_is_front, !place_side_is_front,
) )
} }
@ -187,6 +192,7 @@ impl Board {
(circle.diameter / 2.0) as u64, (circle.diameter / 2.0) as u64,
layer, layer,
net, net,
None,
false, false,
) )
} }
@ -202,6 +208,7 @@ impl Board {
rect.y2, rect.y2,
layer, layer,
net, net,
None,
false, false,
) )
} }
@ -215,6 +222,7 @@ impl Board {
path.width, path.width,
layer, layer,
net, net,
None,
false, false,
) )
} }
@ -228,6 +236,7 @@ impl Board {
polygon.width, polygon.width,
layer, layer,
net, net,
None,
false, false,
) )
} }
@ -247,6 +256,7 @@ impl Board {
wire.path.width, wire.path.width,
layer, layer,
net, net,
None,
false, false,
); );
} }
@ -257,16 +267,18 @@ impl Board {
fn place_circle( fn place_circle(
board: &mut Board, board: &mut Board,
place: PointWithRotation, place: PointWithRotation,
pin: PointWithRotation, pin_pos: PointWithRotation,
radius: u64, radius: u64,
layer: usize, layer: usize,
net: NetId, net: NetId,
pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
board.add_joint(Joint { board.add_joint(Joint {
position: Self::pos(place, pin, 0.0, 0.0, flip), position: Self::pos(place, pin_pos, 0.0, 0.0, flip),
layer, layer,
net, net,
pin,
radius, radius,
}); });
} }
@ -274,49 +286,53 @@ impl Board {
fn place_rect( fn place_rect(
board: &mut Board, board: &mut Board,
place: PointWithRotation, place: PointWithRotation,
pin: PointWithRotation, pin_pos: PointWithRotation,
x1: f64, x1: f64,
y1: f64, y1: f64,
x2: f64, x2: f64,
y2: f64, y2: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
board.add_polygon(Polygon { board.add_polygon(Polygon {
vertices: vec![ vertices: vec![
Self::pos(place, pin, x1, y1, flip), Self::pos(place, pin_pos, x1, y1, flip),
Self::pos(place, pin, x2, y1, flip), Self::pos(place, pin_pos, x2, y1, flip),
Self::pos(place, pin, x2, y2, flip), Self::pos(place, pin_pos, x2, y2, flip),
Self::pos(place, pin, x1, y2, flip), Self::pos(place, pin_pos, x1, y2, flip),
], ],
layer, layer,
net, net,
pin,
}); });
} }
fn place_path( fn place_path(
board: &mut Board, board: &mut Board,
place: PointWithRotation, place: PointWithRotation,
pin: PointWithRotation, pin_pos: PointWithRotation,
coords: &[Point], coords: &[Point],
width: f64, width: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
// Add the first coordinate in the wire path as a dot and save its index. // Add the first coordinate in the wire path as a dot and save its index.
let mut prev_pos = Self::pos(place, pin, coords[0].x, coords[0].y, flip); let mut prev_pos = Self::pos(place, pin_pos, coords[0].x, coords[0].y, flip);
let mut prev_joint = board.add_joint(Joint { let mut prev_joint = board.add_joint(Joint {
position: prev_pos, position: prev_pos,
layer, layer,
radius: (width / 2.0) as u64, radius: (width / 2.0) as u64,
net, net,
pin,
}); });
// Iterate through path coords starting from the second. // Iterate through path coords starting from the second.
for coord in coords.iter().skip(1) { for coord in coords.iter().skip(1) {
let pos = Self::pos(place, pin, coord.x, coord.y, flip); let pos = Self::pos(place, pin_pos, coord.x, coord.y, flip);
if pos == prev_pos { if pos == prev_pos {
continue; continue;
@ -327,6 +343,7 @@ impl Board {
layer, layer,
radius: (width / 2.0) as u64, radius: (width / 2.0) as u64,
net, net,
pin,
}); });
// Add a seg between the current and previous coords. // Add a seg between the current and previous coords.
@ -335,6 +352,7 @@ impl Board {
layer, layer,
half_width: (width / 2.0) as u64, half_width: (width / 2.0) as u64,
net, net,
pin,
}); });
prev_pos = pos; prev_pos = pos;
@ -345,21 +363,23 @@ impl Board {
fn place_polygon( fn place_polygon(
board: &mut Board, board: &mut Board,
place: PointWithRotation, place: PointWithRotation,
pin: PointWithRotation, pin_pos: PointWithRotation,
coords: &[Point], coords: &[Point],
width: f64, width: f64,
layer: usize, layer: usize,
net: NetId, net: NetId,
pin: Option<PinId>,
flip: bool, flip: bool,
) { ) {
let vertices: Vec<[i64; 2]> = coords let vertices: Vec<[i64; 2]> = coords
.iter() .iter()
.map(|coord| Self::pos(place, pin, coord.x, coord.y, flip)) .map(|coord| Self::pos(place, pin_pos, coord.x, coord.y, flip))
.collect(); .collect();
board.add_polygon(Polygon { board.add_polygon(Polygon {
vertices, vertices,
layer, layer,
net, net,
pin,
}); });
} }