diff --git a/topola/src/board.rs b/topola/src/board.rs index 31fc5ea..de47c53 100644 --- a/topola/src/board.rs +++ b/topola/src/board.rs @@ -7,15 +7,10 @@ use derive_getters::{Dissolve, Getters}; use undoredo::{ApplyDelta, Delta, FlushDelta}; use crate::layout::{ - Joint, JointId, Layout, LayoutHalfDelta, NetId, Polygon, PolygonId, Segment, SegmentId, Via, - ViaId, + Joint, JointId, Layout, LayoutHalfDelta, NetId, PinId, Polygon, PolygonId, Segment, SegmentId, + Via, ViaId, }; -struct Layer { - name: String, - index: usize, -} - #[derive(Clone, Debug, Getters)] pub struct Board { layout: Layout, @@ -23,6 +18,8 @@ pub struct Board { layer_names: BiBTreeMap, #[getter(skip)] net_names: BiBTreeMap, + #[getter(skip)] + pin_names: BiBTreeMap, } impl Board { @@ -31,6 +28,7 @@ impl Board { layout: Layout::new(boundary, layer_count), layer_names: BiBTreeMap::new(), net_names: BiBTreeMap::new(), + pin_names: BiBTreeMap::new(), } } @@ -44,9 +42,21 @@ impl Board { layout: Layout::new(boundary, layer_count), layer_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 { self.layout.add_joint(joint) } diff --git a/topola/src/layout.rs b/topola/src/layout.rs index 56ffdaa..6219010 100644 --- a/topola/src/layout.rs +++ b/topola/src/layout.rs @@ -8,6 +8,42 @@ use derive_getters::{Dissolve, Getters}; use stable_vec::StableVec; 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, + segments: Vec, + vias: Vec, + polygons: Vec, +} + +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)] pub struct NetId(usize); @@ -48,6 +84,7 @@ pub struct Joint { pub layer: usize, pub radius: u64, pub net: NetId, + pub pin: Option, } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -73,6 +110,7 @@ pub struct Segment { pub layer: usize, pub half_width: u64, pub net: NetId, + pub pin: Option, } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -98,6 +136,7 @@ pub struct Via { pub layer: usize, pub radius: u64, pub net: NetId, + pub pin: Option, } #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -122,6 +161,7 @@ pub struct Polygon { pub vertices: Vec<[i64; 2]>, pub layer: usize, pub net: NetId, + pub pin: Option, } #[derive(Clone, Debug, Getters)] @@ -130,6 +170,7 @@ pub struct Layout { place_boundary: Vec<[i64; 2]>, layer_count: usize, + pins: StableVec, joints: Recorder>, segments: Recorder>, vias: Recorder>, @@ -143,6 +184,7 @@ impl Layout { place_boundary: boundary, layer_count, + pins: StableVec::new(), joints: Recorder::new(StableVec::new()), segments: 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 { - 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 { - 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 { - 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 { - 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] { @@ -173,6 +247,10 @@ impl Layout { self.joints.get(&endjoints[1].id()).unwrap().position, ] } + + pub fn pin(&self, pin: PinId) -> &Pin { + &self.pins[pin.id()] + } } #[derive(Clone, Debug, Dissolve)] diff --git a/topola/src/specctra.rs b/topola/src/specctra.rs index 0c57e1a..4db1345 100644 --- a/topola/src/specctra.rs +++ b/topola/src/specctra.rs @@ -13,7 +13,7 @@ use specctra::{ use crate::{ Segment, board::Board, - layout::{Joint, NetId, Polygon}, + layout::{Joint, NetId, PinId, Polygon}, math::Vector2, }; @@ -104,6 +104,7 @@ impl Board { for pin in &image.pins { 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 padstack = dsn.pcb.library.find_padstack_by_name(&pin.name).unwrap(); @@ -118,6 +119,7 @@ impl Board { (circle.diameter / 2.0) as u64, layer, net, + Some(pin_id), !place_side_is_front, ) } @@ -133,6 +135,7 @@ impl Board { rect.y2, layer, net, + Some(pin_id), !place_side_is_front, ) } @@ -146,6 +149,7 @@ impl Board { path.width, layer, net, + Some(pin_id), !place_side_is_front, ) } @@ -159,6 +163,7 @@ impl Board { polygon.width, layer, net, + Some(pin_id), !place_side_is_front, ) } @@ -187,6 +192,7 @@ impl Board { (circle.diameter / 2.0) as u64, layer, net, + None, false, ) } @@ -202,6 +208,7 @@ impl Board { rect.y2, layer, net, + None, false, ) } @@ -215,6 +222,7 @@ impl Board { path.width, layer, net, + None, false, ) } @@ -228,6 +236,7 @@ impl Board { polygon.width, layer, net, + None, false, ) } @@ -247,6 +256,7 @@ impl Board { wire.path.width, layer, net, + None, false, ); } @@ -257,16 +267,18 @@ impl Board { fn place_circle( board: &mut Board, place: PointWithRotation, - pin: PointWithRotation, + pin_pos: PointWithRotation, radius: u64, layer: usize, net: NetId, + pin: Option, flip: bool, ) { 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, net, + pin, radius, }); } @@ -274,49 +286,53 @@ impl Board { fn place_rect( board: &mut Board, place: PointWithRotation, - pin: PointWithRotation, + pin_pos: PointWithRotation, x1: f64, y1: f64, x2: f64, y2: f64, layer: usize, net: NetId, + pin: Option, flip: bool, ) { board.add_polygon(Polygon { vertices: vec![ - Self::pos(place, pin, x1, y1, flip), - Self::pos(place, pin, x2, y1, flip), - Self::pos(place, pin, x2, y2, flip), - Self::pos(place, pin, x1, y2, flip), + Self::pos(place, pin_pos, x1, y1, flip), + Self::pos(place, pin_pos, x2, y1, flip), + Self::pos(place, pin_pos, x2, y2, flip), + Self::pos(place, pin_pos, x1, y2, flip), ], layer, net, + pin, }); } fn place_path( board: &mut Board, place: PointWithRotation, - pin: PointWithRotation, + pin_pos: PointWithRotation, coords: &[Point], width: f64, layer: usize, net: NetId, + pin: Option, flip: bool, ) { // 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 { position: prev_pos, layer, radius: (width / 2.0) as u64, net, + pin, }); // Iterate through path coords starting from the second. 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 { continue; @@ -327,6 +343,7 @@ impl Board { layer, radius: (width / 2.0) as u64, net, + pin, }); // Add a seg between the current and previous coords. @@ -335,6 +352,7 @@ impl Board { layer, half_width: (width / 2.0) as u64, net, + pin, }); prev_pos = pos; @@ -345,21 +363,23 @@ impl Board { fn place_polygon( board: &mut Board, place: PointWithRotation, - pin: PointWithRotation, + pin_pos: PointWithRotation, coords: &[Point], width: f64, layer: usize, net: NetId, + pin: Option, flip: bool, ) { let vertices: Vec<[i64; 2]> = coords .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(); board.add_polygon(Polygon { vertices, layer, net, + pin, }); }