From af18d82d7c75803599c33a6bd330f539f33cc39c Mon Sep 17 00:00:00 2001 From: Alain Emilia Anna Zscheile Date: Fri, 3 Jan 2025 05:34:50 +0100 Subject: [PATCH] refactor(board): move recording methods to Recording<'_, Board> --- src/autorouter/autorouter.rs | 12 +- src/autorouter/pointroute.rs | 25 +-- src/board/mod.rs | 287 ++++++++++++++++++----------------- src/specctra/design.rs | 63 +++----- 4 files changed, 191 insertions(+), 196 deletions(-) diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 418e967..19468ec 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -78,7 +78,9 @@ impl Autorouter { .node_index() { RatvertexIndex::FixedDot(dot) => dot, - RatvertexIndex::Poly(poly) => self.board.poly_apex(&mut LayoutEdit::new(), poly), + RatvertexIndex::Poly(poly) => { + self.board.recording(&mut LayoutEdit::new()).poly_apex(poly) + } }; PointrouteExecutionStepper::new(self, origin_dot, point, options) @@ -198,7 +200,9 @@ impl Autorouter { .node_index() { RatvertexIndex::FixedDot(dot) => dot, - RatvertexIndex::Poly(poly) => self.board.poly_apex(&mut LayoutEdit::new(), poly), + RatvertexIndex::Poly(poly) => { + self.board.recording(&mut LayoutEdit::new()).poly_apex(poly) + } }; let target_dot = match self @@ -209,7 +213,9 @@ impl Autorouter { .node_index() { RatvertexIndex::FixedDot(dot) => dot, - RatvertexIndex::Poly(poly) => self.board.poly_apex(&mut LayoutEdit::new(), poly), + RatvertexIndex::Poly(poly) => { + self.board.recording(&mut LayoutEdit::new()).poly_apex(poly) + } }; (source_dot, target_dot) diff --git a/src/autorouter/pointroute.rs b/src/autorouter/pointroute.rs index 55b70be..0d210da 100644 --- a/src/autorouter/pointroute.rs +++ b/src/autorouter/pointroute.rs @@ -12,6 +12,7 @@ use crate::{ band::BandTermsegIndex, dot::{FixedDotIndex, FixedDotWeight}, }, + geometry::edit::Recordable, layout::LayoutEdit, math::Circle, router::{route::RouteStepper, Router}, @@ -33,18 +34,20 @@ impl PointrouteExecutionStepper { point: Point, options: AutorouterOptions, ) -> Result { - let destination = autorouter.board.add_fixed_dot_infringably( - &mut LayoutEdit::new(), - FixedDotWeight { - circle: Circle { - pos: point, - r: options.router_options.routed_band_width / 2.0, + let destination = autorouter + .board + .recording(&mut LayoutEdit::new()) + .add_fixed_dot_infringably( + FixedDotWeight { + circle: Circle { + pos: point, + r: options.router_options.routed_band_width / 2.0, + }, + layer: 0, + maybe_net: None, }, - layer: 0, - maybe_net: None, - }, - None, - ); + None, + ); let mut router = Router::new(autorouter.board.layout_mut(), options.router_options); diff --git a/src/board/mod.rs b/src/board/mod.rs index fa92c63..8208e7c 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -26,7 +26,7 @@ use crate::{ seg::{FixedSegIndex, FixedSegWeight, SegIndex, SegWeight}, }, geometry::{ - edit::{ApplyGeometryEdit, Recordable}, + edit::{ApplyGeometryEdit, Recordable, Recording}, shape::AccessShape, GenericNode, }, @@ -69,6 +69,18 @@ pub struct Board { band_bandname: BiHashMap, } +impl Recordable for Board { + type PW = PrimitiveWeight; + type DW = DotWeight; + type SW = SegWeight; + type BW = BendWeight; + type CW = CompoundWeight; + type PI = PrimitiveIndex; + type DI = DotIndex; + type SI = SegIndex; + type BI = BendIndex; +} + impl Board { /// Initializes the board with given [`Layout`] pub fn new(layout: Layout) -> Self { @@ -83,146 +95,6 @@ impl Board { pub fn layout_mut(&mut self) -> &mut Layout { &mut self.layout } -} - -impl Board { - /// Adds a new fixed dot with an optional pin name. - /// - /// Inserts the dot into the layout and, if a pin name is provided, maps it to the created dot's node. - pub fn add_fixed_dot_infringably( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - maybe_pin: Option, - ) -> FixedDotIndex { - let dot = self - .layout - .recording(recorder) - .add_fixed_dot_infringably(weight); - - if let Some(pin) = maybe_pin { - self.node_to_pinname - .insert(GenericNode::Primitive(dot.into()), pin); - } - - dot - } - - /// Adds a fixed segment between two dots with an optional pin name. - /// - /// Adds the segment to the layout and maps the pin name to the created segment if provided. - pub fn add_poly_fixed_dot_infringably( - &mut self, - recorder: &mut LayoutEdit, - weight: FixedDotWeight, - poly: GenericIndex, - ) -> FixedDotIndex { - let dot = self - .layout - .recording(recorder) - .add_poly_fixed_dot_infringably(weight, poly); - - if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { - self.node_to_pinname - .insert(GenericNode::Primitive(dot.into()), pin.to_string()); - } - - dot - } - - /// Adds a fixed segment associated with a polygon in the layout. - /// - /// Adds the segment to the layout and updates the internal mapping if necessary. - pub fn add_fixed_seg_infringably( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - maybe_pin: Option, - ) -> FixedSegIndex { - let seg = self - .layout - .recording(recorder) - .add_fixed_seg_infringably(from, to, weight); - - if let Some(pin) = maybe_pin { - self.node_to_pinname - .insert(GenericNode::Primitive(seg.into()), pin); - } - - seg - } - - /// Adds a fixed segment associated with a polygon in the layout. - /// - /// Adds the segment to the layout and updates the internal mapping if necessary. - pub fn add_poly_fixed_seg_infringably( - &mut self, - recorder: &mut LayoutEdit, - from: FixedDotIndex, - to: FixedDotIndex, - weight: FixedSegWeight, - poly: GenericIndex, - ) -> FixedSegIndex { - let seg = self - .layout - .recording(recorder) - .add_poly_fixed_seg_infringably(from, to, weight, poly); - - if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { - self.node_to_pinname - .insert(GenericNode::Primitive(seg.into()), pin.to_string()); - } - - seg - } - - /// Adds a new polygon to the layout with an optional pin name. - /// - /// Inserts the polygon into the layout and, if a pin name is provided, maps it to the created polygon's node. - pub fn add_poly( - &mut self, - recorder: &mut LayoutEdit, - weight: PolyWeight, - maybe_pin: Option, - ) -> GenericIndex { - let poly = self.layout.recording(recorder).add_poly(weight); - - if let Some(pin) = maybe_pin { - self.node_to_pinname - .insert(GenericNode::Compound(poly.into()), pin); - } - - poly - } - - /// Retrieves or creates the apex (center point) of a polygon in the layout. - /// - /// If the polygon already has an apex, returns it. Otherwise, creates and returns a new fixed dot as the apex. - pub fn poly_apex( - &mut self, - recorder: &mut LayoutEdit, - poly: GenericIndex, - ) -> FixedDotIndex { - let resolved_poly = self.layout.poly(poly); - if let Some(apex) = resolved_poly.maybe_apex() { - apex - } else { - self.add_poly_fixed_dot_infringably( - recorder, - FixedDotWeight { - circle: Circle { - pos: resolved_poly.shape().center(), - r: 100.0, - }, - layer: resolved_poly.layer(), - maybe_net: resolved_poly.maybe_net(), - }, - poly, - ) - } - } /// Returns the pin name associated with a given node. pub fn node_pinname(&self, node: &NodeIndex) -> Option<&String> { @@ -272,6 +144,139 @@ impl Board { } } +impl Recording<'_, Board> { + fn recording_layout(&mut self) -> Recording<'_, Layout> { + self.inner.layout.recording(self.recorder) + } + + /// Adds a new fixed dot with an optional pin name. + /// + /// Inserts the dot into the layout and, if a pin name is provided, maps it to the created dot's node. + pub fn add_fixed_dot_infringably( + &mut self, + weight: FixedDotWeight, + maybe_pin: Option, + ) -> FixedDotIndex { + let dot = self.recording_layout().add_fixed_dot_infringably(weight); + + if let Some(pin) = maybe_pin { + self.inner + .node_to_pinname + .insert(GenericNode::Primitive(dot.into()), pin); + } + + dot + } + + /// Adds a fixed segment between two dots with an optional pin name. + /// + /// Adds the segment to the layout and maps the pin name to the created segment if provided. + pub fn add_poly_fixed_dot_infringably( + &mut self, + weight: FixedDotWeight, + poly: GenericIndex, + ) -> FixedDotIndex { + let dot = self + .recording_layout() + .add_poly_fixed_dot_infringably(weight, poly); + + if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { + self.inner + .node_to_pinname + .insert(GenericNode::Primitive(dot.into()), pin.to_string()); + } + + dot + } + + /// Adds a fixed segment associated with a polygon in the layout. + /// + /// Adds the segment to the layout and updates the internal mapping if necessary. + pub fn add_fixed_seg_infringably( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + maybe_pin: Option, + ) -> FixedSegIndex { + let seg = self + .recording_layout() + .add_fixed_seg_infringably(from, to, weight); + + if let Some(pin) = maybe_pin { + self.inner + .node_to_pinname + .insert(GenericNode::Primitive(seg.into()), pin); + } + + seg + } + + /// Adds a fixed segment associated with a polygon in the layout. + /// + /// Adds the segment to the layout and updates the internal mapping if necessary. + pub fn add_poly_fixed_seg_infringably( + &mut self, + from: FixedDotIndex, + to: FixedDotIndex, + weight: FixedSegWeight, + poly: GenericIndex, + ) -> FixedSegIndex { + let seg = self + .recording_layout() + .add_poly_fixed_seg_infringably(from, to, weight, poly); + + if let Some(pin) = self.node_pinname(&GenericNode::Compound(poly.into())) { + self.inner + .node_to_pinname + .insert(GenericNode::Primitive(seg.into()), pin.to_string()); + } + + seg + } + + /// Adds a new polygon to the layout with an optional pin name. + /// + /// Inserts the polygon into the layout and, if a pin name is provided, maps it to the created polygon's node. + pub fn add_poly( + &mut self, + weight: PolyWeight, + maybe_pin: Option, + ) -> GenericIndex { + let poly = self.recording_layout().add_poly(weight); + + if let Some(pin) = maybe_pin { + self.inner + .node_to_pinname + .insert(GenericNode::Compound(poly.into()), pin); + } + + poly + } + + /// Retrieves or creates the apex (center point) of a polygon in the layout. + /// + /// If the polygon already has an apex, returns it. Otherwise, creates and returns a new fixed dot as the apex. + pub fn poly_apex(&mut self, poly: GenericIndex) -> FixedDotIndex { + let resolved_poly = self.inner.layout.poly(poly); + if let Some(apex) = resolved_poly.maybe_apex() { + apex + } else { + self.add_poly_fixed_dot_infringably( + FixedDotWeight { + circle: Circle { + pos: resolved_poly.shape().center(), + r: 100.0, + }, + layer: resolved_poly.layer(), + maybe_net: resolved_poly.maybe_net(), + }, + poly, + ) + } + } +} + impl ApplyGeometryEdit< PrimitiveWeight, diff --git a/src/specctra/design.rs b/src/specctra/design.rs index 14fd348..4f5cb90 100644 --- a/src/specctra/design.rs +++ b/src/specctra/design.rs @@ -18,7 +18,7 @@ use crate::{ seg::FixedSegWeight, Drawing, }, - geometry::{primitive::PrimitiveShape, GetWidth}, + geometry::{edit::Recordable, primitive::PrimitiveShape, GetWidth}, layout::{poly::SolidPolyWeight, Layout, LayoutEdit}, math::{Circle, PointWithRotation}, specctra::{ @@ -431,8 +431,7 @@ impl SpecctraDesign { r, }; - board.add_fixed_dot_infringably( - recorder, + board.recording(recorder).add_fixed_dot_infringably( FixedDotWeight { circle, layer, @@ -455,15 +454,12 @@ impl SpecctraDesign { maybe_net: Option, maybe_pin: Option, ) { - let poly = board.add_poly( - recorder, - SolidPolyWeight { layer, maybe_net }.into(), - maybe_pin, - ); + let mut recording_board = board.recording(recorder); + + let poly = recording_board.add_poly(SolidPolyWeight { layer, maybe_net }.into(), maybe_pin); // Corners. - let dot_1_1 = board.add_poly_fixed_dot_infringably( - recorder, + let dot_1_1 = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, x1, y1), @@ -474,8 +470,7 @@ impl SpecctraDesign { }, poly, ); - let dot_2_1 = board.add_poly_fixed_dot_infringably( - recorder, + let dot_2_1 = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, x2, y1), @@ -486,8 +481,7 @@ impl SpecctraDesign { }, poly, ); - let dot_2_2 = board.add_poly_fixed_dot_infringably( - recorder, + let dot_2_2 = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, x2, y2), @@ -498,8 +492,7 @@ impl SpecctraDesign { }, poly, ); - let dot_1_2 = board.add_poly_fixed_dot_infringably( - recorder, + let dot_1_2 = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, x1, y2), @@ -511,8 +504,7 @@ impl SpecctraDesign { poly, ); // Sides. - board.add_poly_fixed_seg_infringably( - recorder, + recording_board.add_poly_fixed_seg_infringably( dot_1_1, dot_2_1, FixedSegWeight { @@ -522,8 +514,7 @@ impl SpecctraDesign { }, poly, ); - board.add_poly_fixed_seg_infringably( - recorder, + recording_board.add_poly_fixed_seg_infringably( dot_2_1, dot_2_2, FixedSegWeight { @@ -533,8 +524,7 @@ impl SpecctraDesign { }, poly, ); - board.add_poly_fixed_seg_infringably( - recorder, + recording_board.add_poly_fixed_seg_infringably( dot_2_2, dot_1_2, FixedSegWeight { @@ -544,8 +534,7 @@ impl SpecctraDesign { }, poly, ); - board.add_poly_fixed_seg_infringably( - recorder, + recording_board.add_poly_fixed_seg_infringably( dot_1_2, dot_1_1, FixedSegWeight { @@ -568,10 +557,10 @@ impl SpecctraDesign { maybe_net: Option, maybe_pin: Option, ) { + let mut recording_board = board.recording(recorder); // 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); - let mut prev_index = board.add_fixed_dot_infringably( - recorder, + let mut prev_index = recording_board.add_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: prev_pos, @@ -591,8 +580,7 @@ impl SpecctraDesign { continue; } - let index = board.add_fixed_dot_infringably( - recorder, + let index = recording_board.add_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos, @@ -605,8 +593,7 @@ impl SpecctraDesign { ); // add a seg between the current and previous coords - let _ = board.add_fixed_seg_infringably( - recorder, + let _ = recording_board.add_fixed_seg_infringably( prev_index, index, FixedSegWeight { @@ -633,15 +620,11 @@ impl SpecctraDesign { maybe_net: Option, maybe_pin: Option, ) { - let poly = board.add_poly( - recorder, - SolidPolyWeight { layer, maybe_net }.into(), - maybe_pin, - ); + let mut recording_board = board.recording(recorder); + let poly = recording_board.add_poly(SolidPolyWeight { layer, maybe_net }.into(), maybe_pin); // add the first coordinate in the wire path as a dot and save its index - let mut prev_index = board.add_poly_fixed_dot_infringably( - recorder, + let mut prev_index = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, coords[0].x, coords[0].y), @@ -657,8 +640,7 @@ impl SpecctraDesign { // iterate through path coords starting from the second for coord in coords.iter().skip(1) { - let index = board.add_poly_fixed_dot_infringably( - recorder, + let index = recording_board.add_poly_fixed_dot_infringably( FixedDotWeight { circle: Circle { pos: Self::pos(place, pin, coord.x, coord.y), @@ -672,8 +654,7 @@ impl SpecctraDesign { ); // add a seg between the current and previous coords - let _ = board.add_poly_fixed_seg_infringably( - recorder, + let _ = recording_board.add_poly_fixed_seg_infringably( prev_index, index, FixedSegWeight {