From d7129354a14f4a29a9ad78409bb609f756b15594 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sun, 13 Jul 2025 22:49:30 +0200 Subject: [PATCH] feat(autorouter/autoroute): Record band assigns so undo actually works Aborting the autoroute stepper was unimplemented and it would make the autorouting job finish instead. This is fixed now. --- crates/topola-cli/src/main.rs | 4 +- crates/topola-egui/src/workspace.rs | 5 +- src/autorouter/autoroute.rs | 58 +++++++++-------- src/autorouter/execution.rs | 15 +++-- src/autorouter/history.rs | 6 +- src/autorouter/invoker.rs | 6 +- src/autorouter/place_via.rs | 16 +++-- src/autorouter/pointroute.rs | 6 +- src/autorouter/remove_bands.rs | 10 ++- src/board/edit.rs | 62 ++++++++++++++++++ src/board/mod.rs | 99 +++++++++++++++++------------ src/router/ng/eval.rs | 7 +- src/router/ng/mod.rs | 20 ++++-- src/router/ng/poly.rs | 9 +-- src/router/ng/router.rs | 23 +++---- src/specctra/design.rs | 14 ++-- 16 files changed, 237 insertions(+), 123 deletions(-) create mode 100644 src/board/edit.rs diff --git a/crates/topola-cli/src/main.rs b/crates/topola-cli/src/main.rs index 1168674..6afd676 100644 --- a/crates/topola-cli/src/main.rs +++ b/crates/topola-cli/src/main.rs @@ -12,7 +12,7 @@ use topola::autorouter::selection::PinSelection; use topola::autorouter::Autorouter; use topola::autorouter::AutorouterOptions; use topola::autorouter::PresortBy; -use topola::layout::LayoutEdit; +use topola::board::edit::BoardEdit; use topola::router::RouterOptions; use topola::specctra::design::SpecctraDesign; @@ -27,7 +27,7 @@ fn main() -> Result<(), std::io::Error> { let design = SpecctraDesign::load(design_bufread).expect("File failed to parse as Specctra DSN"); - let board = design.make_board(&mut LayoutEdit::new()); + let board = design.make_board(&mut BoardEdit::new()); let history = if let Some(commands_filename) = args.commands { let command_file = File::open(commands_filename)?; diff --git a/crates/topola-egui/src/workspace.rs b/crates/topola-egui/src/workspace.rs index 44dc06f..46eb66f 100644 --- a/crates/topola-egui/src/workspace.rs +++ b/crates/topola-egui/src/workspace.rs @@ -9,11 +9,12 @@ use std::{ use topola::{ autorouter::{execution::Command, history::History}, + board::edit::BoardEdit, interactor::{ activity::{InteractiveEvent, InteractiveEventKind, InteractiveInput}, Interactor, }, - layout::{via::ViaWeight, LayoutEdit}, + layout::via::ViaWeight, math::Circle, specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata}, }; @@ -40,7 +41,7 @@ pub struct Workspace { impl Workspace { pub fn new(design: SpecctraDesign, tr: &Translator) -> Result { - let board = design.make_board(&mut LayoutEdit::new()); + let board = design.make_board(&mut BoardEdit::new()); let appearance_panel = AppearancePanel::new(&board); let overlay = Overlay::new(&board).map_err(|err| { format!( diff --git a/src/autorouter/autoroute.rs b/src/autorouter/autoroute.rs index 94a2af0..15d745d 100644 --- a/src/autorouter/autoroute.rs +++ b/src/autorouter/autoroute.rs @@ -8,9 +8,12 @@ use std::ops::ControlFlow; use crate::{ - board::AccessMesadata, + board::{ + edit::{BoardDataEdit, BoardEdit}, + AccessMesadata, + }, drawing::{band::BandTermsegIndex, graph::PrimitiveIndex, Collect}, - geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape}, + geometry::primitive::PrimitiveShape, graph::MakeRef, layout::LayoutEdit, router::{ @@ -42,6 +45,9 @@ pub struct AutorouteExecutionStepper { curr_ratline_index: usize, /// Stores the current route being processed, if any. route: Option, + /// Records the changes to the board data (changes to layout data are + /// recorded in navcord in route stepper). + data_edit: BoardDataEdit, /// The options for the autorouting process, defining how routing should be carried out. options: AutorouterOptions, } @@ -73,12 +79,22 @@ impl AutorouteExecutionStepper { destination, options.router_options.routed_band_width, )?), + data_edit: BoardDataEdit::new(), options, }) } + + fn dissolve_route_stepper_into_layout_edit(&mut self) -> LayoutEdit { + if let Some(taken_route) = self.route.take() { + let (_thetastar, navcord, ..) = taken_route.dissolve(); + navcord.recorder + } else { + LayoutEdit::new() + } + } } -impl Step, Option, AutorouteContinueStatus> +impl Step, Option, AutorouteContinueStatus> for AutorouteExecutionStepper { type Error = AutorouterError; @@ -86,20 +102,17 @@ impl Step, Option, AutorouteContinu fn step( &mut self, autorouter: &mut Autorouter, - ) -> Result, AutorouteContinueStatus>, AutorouterError> { + ) -> Result, AutorouteContinueStatus>, AutorouterError> { if self.curr_ratline_index >= self.ratlines.len() { - let recorder = if let Some(taken_route) = self.route.take() { - let (_thetastar, navcord, ..) = taken_route.dissolve(); - navcord.recorder - } else { - LayoutEdit::new() - }; - - return Ok(ControlFlow::Break(Some(recorder))); + let recorder = self.dissolve_route_stepper_into_layout_edit(); + return Ok(ControlFlow::Break(Some(BoardEdit::new_from_edits( + self.data_edit.clone(), + recorder, + )))); } let Some(ref mut route) = self.route else { - // Shouldn't happen. + // May happen if stepper was aborted. return Ok(ControlFlow::Break(None)); }; @@ -134,7 +147,7 @@ impl Step, Option, AutorouteContinu autorouter .board - .try_set_band_between_nodes(source, target, band); + .try_set_band_between_nodes(&mut self.data_edit, source, target, band); AutorouteContinueStatus::Routed(band_termseg) }; @@ -145,13 +158,7 @@ impl Step, Option, AutorouteContinu let (source, target) = new_ratline.ref_(autorouter).endpoint_dots(); let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options); - - let recorder = if let Some(taken_route) = self.route.take() { - let (_thetastar, navcord, ..) = taken_route.dissolve(); - navcord.recorder - } else { - LayoutEdit::new() - }; + let recorder = self.dissolve_route_stepper_into_layout_edit(); self.route = Some(router.route( recorder, @@ -167,10 +174,11 @@ impl Step, Option, AutorouteContinu impl Abort> for AutorouteExecutionStepper { fn abort(&mut self, autorouter: &mut Autorouter) { - if let Some(ref route) = self.route { - autorouter.board.apply(&route.navcord().recorder.reverse()); - self.curr_ratline_index = self.ratlines.len(); - } + let layout_edit = self.dissolve_route_stepper_into_layout_edit(); + let board_edit = BoardEdit::new_from_edits(self.data_edit.clone(), layout_edit); + + autorouter.board.apply_edit(&board_edit.reverse()); + self.curr_ratline_index = self.ratlines.len(); } } diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index fa4a3dd..77da306 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -8,8 +8,8 @@ use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; use crate::{ - board::AccessMesadata, - layout::{via::ViaWeight, LayoutEdit}, + board::{edit::BoardEdit, AccessMesadata}, + layout::via::ViaWeight, router::ng, stepper::{Abort, EstimateProgress, Step}, }; @@ -57,7 +57,7 @@ impl ExecutionStepper { fn step_catch_err( &mut self, autorouter: &mut Autorouter, - ) -> Result, String)>, InvokerError> { + ) -> Result, String)>, InvokerError> { Ok(match self { ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? { ControlFlow::Continue(..) => ControlFlow::Continue(()), @@ -74,9 +74,12 @@ impl ExecutionStepper { ControlFlow::Break(true) => { for (ep, band) in &autoroute.last_bands { let (source, target) = ep.end_points.into(); - autorouter - .board - .try_set_band_between_nodes(source, target, *band); + autorouter.board.try_set_band_between_nodes( + &mut autoroute.last_recorder.data_edit, + source, + target, + *band, + ); } let topo_navmesh = autoroute.maybe_topo_navmesh().unwrap().to_owned(); diff --git a/src/autorouter/history.rs b/src/autorouter/history.rs index cdcccef..745543c 100644 --- a/src/autorouter/history.rs +++ b/src/autorouter/history.rs @@ -10,7 +10,7 @@ use derive_getters::{Dissolve, Getters}; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{autorouter::execution::Command, layout::LayoutEdit}; +use crate::{autorouter::execution::Command, board::edit::BoardEdit}; #[derive(Error, Debug, Clone)] pub enum HistoryError { @@ -25,7 +25,7 @@ pub enum HistoryError { pub struct HistoryEntry { command: Command, #[serde(skip)] - edit: Option, + edit: Option, } #[derive(Debug, Default, Clone, Getters, Dissolve, Serialize, Deserialize)] @@ -39,7 +39,7 @@ impl History { Self::default() } - pub fn do_(&mut self, command: Command, edit: Option) { + pub fn do_(&mut self, command: Command, edit: Option) { self.done.push(HistoryEntry { command, edit }); } diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index 3a7b4f9..0b5c66d 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -15,7 +15,7 @@ use thiserror::Error; use crate::{ board::AccessMesadata, drawing::graph::PrimitiveIndex, - geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape, shape::MeasureLength}, + geometry::{primitive::PrimitiveShape, shape::MeasureLength}, graph::{GenericIndex, MakeRef}, layout::poly::PolyWeight, router::{ @@ -256,7 +256,7 @@ impl Invoker { let last_done = self.history.last_done()?; if let Some(edit) = last_done.edit() { - self.autorouter.board.apply(&edit.reverse()); + self.autorouter.board.apply_edit(&edit.reverse()); } Ok(self.history.undo()?) @@ -268,7 +268,7 @@ impl Invoker { let last_undone = self.history.last_undone()?; if let Some(edit) = last_undone.edit() { - self.autorouter.board.apply(edit); + self.autorouter.board.apply_edit(edit); } Ok(self.history.redo()?) diff --git a/src/autorouter/place_via.rs b/src/autorouter/place_via.rs index 69c18c0..cecb120 100644 --- a/src/autorouter/place_via.rs +++ b/src/autorouter/place_via.rs @@ -7,7 +7,10 @@ //! checks if the via has already been placed. use crate::{ - board::AccessMesadata, + board::{ + edit::{BoardDataEdit, BoardEdit}, + AccessMesadata, + }, layout::{via::ViaWeight, LayoutEdit}, stepper::EstimateProgress, }; @@ -31,16 +34,19 @@ impl PlaceViaExecutionStepper { pub fn doit( &mut self, autorouter: &mut Autorouter, - ) -> Result, AutorouterError> { + ) -> Result, AutorouterError> { if !self.done { self.done = true; - let mut edit = LayoutEdit::new(); + let mut layout_edit = LayoutEdit::new(); autorouter .board .layout_mut() - .add_via(&mut edit, self.weight)?; - Ok(Some(edit)) + .add_via(&mut layout_edit, self.weight)?; + Ok(Some(BoardEdit::new_from_edits( + BoardDataEdit::new(), + layout_edit, + ))) } else { Ok(None) } diff --git a/src/autorouter/pointroute.rs b/src/autorouter/pointroute.rs index 7a37d63..bb8bdc3 100644 --- a/src/autorouter/pointroute.rs +++ b/src/autorouter/pointroute.rs @@ -7,7 +7,7 @@ use std::ops::ControlFlow; use geo::Point; use crate::{ - board::AccessMesadata, + board::{edit::BoardEdit, AccessMesadata}, drawing::{ band::BandTermsegIndex, dot::{FixedDotIndex, FixedDotWeight, GeneralDotWeight}, @@ -33,7 +33,7 @@ impl PointrouteExecutionStepper { options: AutorouterOptions, ) -> Result { let destination = autorouter.board.add_fixed_dot_infringably( - &mut LayoutEdit::new(), + &mut BoardEdit::new(), // TODO? FixedDotWeight(GeneralDotWeight { circle: Circle { pos: point, @@ -49,7 +49,7 @@ impl PointrouteExecutionStepper { Ok(Self { route: router.route( - LayoutEdit::new(), + LayoutEdit::new(), // TODO? origin, destination, options.router_options.routed_band_width, diff --git a/src/autorouter/remove_bands.rs b/src/autorouter/remove_bands.rs index f67e2de..d9ecfd9 100644 --- a/src/autorouter/remove_bands.rs +++ b/src/autorouter/remove_bands.rs @@ -4,7 +4,10 @@ //! Provides functionality to remove bands from the layout. -use crate::{board::AccessMesadata, layout::LayoutEdit, stepper::EstimateProgress}; +use crate::{ + board::{edit::BoardEdit, AccessMesadata}, + stepper::EstimateProgress, +}; use super::{invoker::GetDebugOverlayData, selection::BandSelection, Autorouter, AutorouterError}; @@ -25,11 +28,12 @@ impl RemoveBandsExecutionStepper { pub fn doit( &mut self, autorouter: &mut Autorouter, - ) -> Result, AutorouterError> { + ) -> Result, AutorouterError> { if !self.done { self.done = true; - let mut edit = LayoutEdit::new(); + let mut edit = BoardEdit::new(); + for selector in self.selection.selectors() { let band = *autorouter.board.bandname_band(&selector.band).unwrap(); autorouter diff --git a/src/board/edit.rs b/src/board/edit.rs new file mode 100644 index 0000000..505bfca --- /dev/null +++ b/src/board/edit.rs @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2025 Topola contributors +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use std::collections::BTreeMap; + +use crate::{drawing::band::BandUid, layout::LayoutEdit}; + +use super::BandName; + +#[derive(Debug, Clone)] +pub struct BoardDataEdit { + pub(super) bands: BTreeMap, Option)>, +} + +impl BoardDataEdit { + pub fn new() -> Self { + Self { + bands: BTreeMap::new(), + } + } +} + +#[derive(Debug, Clone)] +pub struct BoardEdit { + pub data_edit: BoardDataEdit, + pub layout_edit: LayoutEdit, +} + +impl BoardEdit { + pub fn new() -> Self { + Self { + data_edit: BoardDataEdit::new(), + layout_edit: LayoutEdit::new(), + } + } + + pub fn new_from_edits(data_edit: BoardDataEdit, layout_edit: LayoutEdit) -> Self { + Self { + data_edit, + layout_edit, + } + } + + pub fn reverse_inplace(&mut self) { + self.data_edit + .bands + .values_mut() + .for_each(Self::swap_tuple_inplace); + self.layout_edit.reverse_inplace(); + } + + fn swap_tuple_inplace(x: &mut (D, D)) { + core::mem::swap(&mut x.0, &mut x.1); + } + + pub fn reverse(&self) -> Self { + let mut rev = self.clone(); + rev.reverse_inplace(); + rev + } +} diff --git a/src/board/mod.rs b/src/board/mod.rs index 7a51a30..666cc02 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -2,10 +2,12 @@ // // SPDX-License-Identifier: MIT -//! Provides the functionality to create and manage relationships -//! between nodes, pins, and bands, as well as handle metadata and geometric data -//! for layout construction. +//! Manages relationship between pins and bands and the primitives and compounds +//! that consitutite them on the layout. And some more. +pub mod edit; + +use edit::{BoardDataEdit, BoardEdit}; pub use specctra_core::mesadata::AccessMesadata; use bimap::BiBTreeMap; @@ -16,15 +18,14 @@ use std::collections::BTreeMap; use crate::{ drawing::{ band::BandUid, - bend::{BendIndex, BendWeight}, - dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight}, + dot::{FixedDotIndex, FixedDotWeight}, graph::PrimitiveIndex, - seg::{FixedSegIndex, FixedSegWeight, SegIndex, SegWeight}, + seg::{FixedSegIndex, FixedSegWeight}, Collect, DrawingException, }, geometry::{edit::ApplyGeometryEdit, GenericNode, GetLayer}, graph::{GenericIndex, MakeRef}, - layout::{poly::PolyWeight, CompoundEntryLabel, CompoundWeight, Layout, LayoutEdit, NodeIndex}, + layout::{poly::PolyWeight, CompoundWeight, Layout, NodeIndex}, router::ng::EtchedPath, }; @@ -109,11 +110,13 @@ impl Board { /// 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, + recorder: &mut BoardEdit, weight: FixedDotWeight, maybe_pin: Option, ) -> FixedDotIndex { - let dot = self.layout.add_fixed_dot_infringably(recorder, weight); + let dot = self + .layout + .add_fixed_dot_infringably(&mut recorder.layout_edit, weight); if let Some(pin) = maybe_pin { self.node_to_pinname @@ -128,15 +131,15 @@ impl Board { /// Adds the segment to the layout and updates the internal mapping if necessary. pub fn add_fixed_seg_infringably( &mut self, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, from: FixedDotIndex, to: FixedDotIndex, weight: FixedSegWeight, maybe_pin: Option, ) -> FixedSegIndex { - let seg = self - .layout - .add_fixed_seg_infringably(recorder, from, to, weight); + let seg = + self.layout + .add_fixed_seg_infringably(&mut recorder.layout_edit, from, to, weight); if let Some(pin) = maybe_pin { self.node_to_pinname @@ -151,12 +154,14 @@ impl Board { /// 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_with_nodes( &mut self, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, weight: PolyWeight, maybe_pin: Option, nodes: &[PrimitiveIndex], ) -> GenericIndex { - let (poly, apex) = self.layout.add_poly_with_nodes(recorder, weight, nodes); + let (poly, apex) = + self.layout + .add_poly_with_nodes(&mut recorder.layout_edit, weight, nodes); if let Some(pin) = maybe_pin { for i in nodes { @@ -203,6 +208,7 @@ impl Board { /// Creates band between the two nodes pub fn try_set_band_between_nodes( &mut self, + recorder: &mut BoardDataEdit, source: FixedDotIndex, target: FixedDotIndex, band: BandUid, @@ -216,6 +222,7 @@ impl Board { .unwrap() .to_string(); let bandname = BandName::from((source_pinname, target_pinname)); + if self.band_bandname.get_by_right(&bandname).is_some() { false } else { @@ -223,7 +230,9 @@ impl Board { end_points: (source, target).into(), }; self.bands_by_id.insert(ep, band); - self.band_bandname.insert(band, bandname); + self.band_bandname.insert(band, bandname.clone()); + + recorder.bands.insert(bandname, (None, Some(band))); true } } @@ -242,10 +251,10 @@ impl Board { self.band_between_pins(source_pinname, target_pinname) } - /// Removes the band between the two nodes + /// Removes the band between the two nodes. pub fn remove_band_between_nodes( &mut self, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, source: FixedDotIndex, target: FixedDotIndex, ) -> Result<(), DrawingException> { @@ -260,25 +269,35 @@ impl Board { .node_pinname(&GenericNode::Primitive(target.into())) .unwrap() .to_string(); - self.band_bandname - .remove_by_right(&BandName::from((source_pinname, target_pinname))); + + let bandname = BandName::from((source_pinname, target_pinname)); + let maybe_band = self.band_bandname.get_by_right(&bandname).cloned(); + self.band_bandname.remove_by_right(&bandname); + if let Some((_, uid)) = self.bands_by_id.remove_by_left(&ep) { let (from, _) = uid.into(); - self.layout.remove_band(recorder, from)?; + self.layout.remove_band(&mut recorder.layout_edit, from)?; } + + recorder + .data_edit + .bands + .insert(bandname, (maybe_band, None)); + Ok(()) } - /// Removes the band between two nodes given by [`BandUid`] + /// Removes the band between two nodes given by [`BandUid`]. pub fn remove_band_by_id( &mut self, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, uid: BandUid, ) -> Result<(), DrawingException> { if let Some(ep) = self.bands_by_id.get_by_right(&uid) { let (source, target) = ep.end_points.into(); self.remove_band_between_nodes(recorder, source, target)?; } + Ok(()) } @@ -293,26 +312,24 @@ impl Board { .copied() } + pub fn apply_edit(&mut self, edit: &BoardEdit) { + for (bandname, (maybe_old_band_uid, ..)) in &edit.data_edit.bands { + if maybe_old_band_uid.is_some() { + self.band_bandname.remove_by_right(bandname); + } + } + + self.layout_mut().apply(&edit.layout_edit); + + for (bandname, (.., maybe_new_band_uid)) in &edit.data_edit.bands { + if let Some(band_uid) = maybe_new_band_uid { + self.band_bandname.insert(*band_uid, bandname.clone()); + } + } + } + /// Returns the mesadata associated with the layout's drawing rules. pub fn mesadata(&self) -> &M { self.layout.drawing().rules() } } - -impl - ApplyGeometryEdit< - DotWeight, - SegWeight, - BendWeight, - CompoundWeight, - CompoundEntryLabel, - PrimitiveIndex, - DotIndex, - SegIndex, - BendIndex, - > for Board -{ - fn apply(&mut self, edit: &LayoutEdit) { - self.layout.apply(edit); - } -} diff --git a/src/router/ng/eval.rs b/src/router/ng/eval.rs index e71daf8..f7ea7c0 100644 --- a/src/router/ng/eval.rs +++ b/src/router/ng/eval.rs @@ -145,7 +145,12 @@ impl AstarContext { } } - let fin = layout.finish_in_dot(&mut recorder, sub.active_head, prim, width)?; + let fin = layout.finish_in_dot( + &mut recorder.layout_edit, + sub.active_head, + prim, + width, + )?; length += sub .active_head .maybe_cane() diff --git a/src/router/ng/mod.rs b/src/router/ng/mod.rs index 3fdb54c..fca0faf 100644 --- a/src/router/ng/mod.rs +++ b/src/router/ng/mod.rs @@ -16,7 +16,7 @@ use std::{ }; use crate::{ - board::Board, + board::{edit::BoardEdit, Board}, drawing::{ band::BandUid, bend::BendIndex, @@ -34,7 +34,7 @@ use crate::{ GenericNode, }, graph::GetPetgraphIndex as _, - layout::{Layout, LayoutEdit}, + layout::Layout, math::{CachedPolyExt, RotationSense}, router::draw::{Draw, DrawException}, }; @@ -122,7 +122,7 @@ pub struct Common { #[derive(Clone, Debug)] pub struct AstarContext { /// TODO: make sure we can trust the `LayoutEdit` - pub recorder: LayoutEdit, + pub recorder: BoardEdit, pub bands: BTreeMap, @@ -135,7 +135,7 @@ pub struct AstarContext { impl AstarContext { pub fn last_layout(&self, common: &Common) -> Layout { let mut layout = common.layout.clone(); - layout.apply(&self.recorder); + layout.apply(&self.recorder.layout_edit); layout } } @@ -557,7 +557,7 @@ impl SubContext { fn cane_around( layout: &mut Layout, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, route_length: &mut f64, old_head: Head, core: FixedDotIndex, @@ -574,7 +574,7 @@ fn cane_around( ); let ret = match inner { - None => layout.cane_around_dot(recorder, old_head, core, sense, width), + None => layout.cane_around_dot(&mut recorder.layout_edit, old_head, core, sense, width), Some(inner) => { // now, inner is expected to be a bend. // TODO: handle the case that the same path wraps multiple times around the same core @@ -595,7 +595,13 @@ fn cane_around( }) .next(); if let Some(inner_bend) = inner_bend { - layout.cane_around_bend(recorder, old_head, inner_bend.into(), sense, width) + layout.cane_around_bend( + &mut recorder.layout_edit, + old_head, + inner_bend.into(), + sense, + width, + ) } else { return Err(EvalException::BendNotFound { core: core, diff --git a/src/router/ng/poly.rs b/src/router/ng/poly.rs index 582aade..8cc8266 100644 --- a/src/router/ng/poly.rs +++ b/src/router/ng/poly.rs @@ -6,6 +6,7 @@ use geo::Point; use specctra_core::rules::AccessRules; use crate::{ + board::edit::BoardEdit, drawing::{ band::BandUid, dot::FixedDotIndex, @@ -15,7 +16,7 @@ use crate::{ }, geometry::{compound::ManageCompounds, shape::AccessShape as _, GetSetPos as _}, graph::{GenericIndex, GetPetgraphIndex as _}, - layout::{poly::PolyWeight, CompoundEntryLabel, Layout, LayoutEdit}, + layout::{poly::PolyWeight, CompoundEntryLabel, Layout}, math::{is_poly_convex_hull_cw, CachedPolyExt, RotationSense}, router::ng::{ pie::{mayrev, utils::rotate_iter}, @@ -112,7 +113,7 @@ impl PolygonRouting { fn route_next( &self, layout: &mut Layout, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, route_length: &mut f64, old_head: Head, ext_core: FixedDotIndex, @@ -133,7 +134,7 @@ impl PolygonRouting { pub fn route_to_entry( &self, layout: &mut Layout, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, old_head: Head, entry_point: FixedDotIndex, width: f64, @@ -153,7 +154,7 @@ impl PolygonRouting { pub fn route_to_exit( &self, layout: &mut Layout, - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, mut active_head: Head, exit: FixedDotIndex, width: f64, diff --git a/src/router/ng/router.rs b/src/router/ng/router.rs index e739e5b..5d8d192 100644 --- a/src/router/ng/router.rs +++ b/src/router/ng/router.rs @@ -11,10 +11,11 @@ use std::{ use crate::{ autorouter::invoker::GetDebugOverlayData, + board::edit::BoardEdit, drawing::{band::BandUid, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules}, geometry::primitive::PrimitiveShape, graph::GenericIndex, - layout::{poly::PolyWeight, Layout, LayoutEdit}, + layout::{poly::PolyWeight, Layout}, stepper::{Abort, EstimateProgress}, }; @@ -68,7 +69,7 @@ pub struct AutorouteExecutionStepper { original_edge_paths: Box<[EdgePaths]>, pub last_layout: Layout, - pub last_recorder: LayoutEdit, + pub last_recorder: BoardEdit, pub last_edge_paths: Box<[EdgePaths]>, pub last_bands: BTreeMap, @@ -90,7 +91,7 @@ impl AutorouteExecutionStepper { impl Abort<()> for AutorouteExecutionStepper { fn abort(&mut self, _: &mut ()) { self.last_layout = self.common.layout.clone(); - self.last_recorder = LayoutEdit::new(); + self.last_recorder = BoardEdit::new(); self.last_edge_paths = self.original_edge_paths.clone(); self.last_bands = BTreeMap::new(); self.finish(); @@ -121,7 +122,7 @@ impl AutorouteExecutionStepp } let context = AstarContext { - recorder: LayoutEdit::new(), + recorder: BoardEdit::new(), bands, length: 0.0, sub: None, @@ -154,7 +155,7 @@ impl AutorouteExecutionStepp common, original_edge_paths: navmesh.edge_paths.clone(), last_layout: layout.clone(), - last_recorder: LayoutEdit::new(), + last_recorder: BoardEdit::new(), last_edge_paths: navmesh.edge_paths.clone(), last_bands: context.bands.clone(), active_polygons: Vec::new(), @@ -204,7 +205,7 @@ impl AutorouteExecutionStepp // no valid result found ControlFlow::Break(None) => { self.last_layout = self.common.layout.clone(); - self.last_recorder = LayoutEdit::new(); + self.last_recorder = BoardEdit::new(); self.last_edge_paths = self.original_edge_paths.clone(); self.last_bands = BTreeMap::new(); self.finish(); @@ -286,7 +287,7 @@ pub struct ManualrouteExecutionStepper { // results pub last_layout: Layout, - pub last_recorder: LayoutEdit, + pub last_recorder: BoardEdit, // visualization / debug pub active_polygons: Vec>, @@ -321,7 +322,7 @@ impl ManualrouteExecutionStepper { impl Abort<()> for ManualrouteExecutionStepper { fn abort(&mut self, _: &mut ()) { self.last_layout = self.common.layout.clone(); - self.last_recorder = LayoutEdit::new(); + self.last_recorder = BoardEdit::new(); self.context.bands = BTreeMap::new(); self.finish(); self.aborted = true; @@ -365,7 +366,7 @@ impl ManualrouteExecutionSte } let context = AstarContext { - recorder: LayoutEdit::new(), + recorder: BoardEdit::new(), bands, length: 0.0, sub: None, @@ -382,7 +383,7 @@ impl ManualrouteExecutionSte original_edge_paths: tmp_navmesh_edge_paths, last_layout: layout.clone(), - last_recorder: LayoutEdit::new(), + last_recorder: BoardEdit::new(), active_polygons: Vec::new(), ghosts: Vec::new(), polygonal_blockers: Vec::new(), @@ -514,7 +515,7 @@ impl ManualrouteExecutionSte // no valid result found self.last_layout = self.common.layout.clone(); - self.last_recorder = LayoutEdit::new(); + self.last_recorder = BoardEdit::new(); self.context.bands = BTreeMap::new(); self.finish(); ControlFlow::Break(false) diff --git a/src/specctra/design.rs b/src/specctra/design.rs index 8c0c027..f0af2c9 100644 --- a/src/specctra/design.rs +++ b/src/specctra/design.rs @@ -11,7 +11,7 @@ use std::collections::{btree_map::Entry as BTreeMapEntry, BTreeMap}; use geo::{point, Point, Rotate}; use crate::{ - board::{AccessMesadata, Board}, + board::{edit::BoardEdit, AccessMesadata, Board}, drawing::{ dot::{FixedDotWeight, GeneralDotWeight}, graph::{GetMaybeNet, MakePrimitive}, @@ -20,7 +20,7 @@ use crate::{ Drawing, }, geometry::{primitive::PrimitiveShape, GetLayer, GetWidth}, - layout::{poly::SolidPolyWeight, Layout, LayoutEdit}, + layout::{poly::SolidPolyWeight, Layout}, math::{Circle, PointWithRotation}, specctra::{ mesadata::SpecctraMesadata, @@ -179,7 +179,7 @@ impl SpecctraDesign { /// which is used for layout and routing operations. The board is initialized with [`SpecctraMesadata`], /// which includes layer and net mappings, and is populated with components, pins, vias, and wires /// from the PCB definition. - pub fn make_board(&self, recorder: &mut LayoutEdit) -> Board { + pub fn make_board(&self, recorder: &mut BoardEdit) -> Board { let mesadata = SpecctraMesadata::from_pcb(&self.pcb); let mut board = Board::new(Layout::new(Drawing::new( mesadata, @@ -424,7 +424,7 @@ impl SpecctraDesign { } fn add_circle( - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, board: &mut Board, place: PointWithRotation, pin: PointWithRotation, @@ -450,7 +450,7 @@ impl SpecctraDesign { } fn add_rect( - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, board: &mut Board, place: PointWithRotation, pin: PointWithRotation, @@ -575,7 +575,7 @@ impl SpecctraDesign { } fn add_path( - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, board: &mut Board, place: PointWithRotation, pin: PointWithRotation, @@ -640,7 +640,7 @@ impl SpecctraDesign { } fn add_polygon( - recorder: &mut LayoutEdit, + recorder: &mut BoardEdit, board: &mut Board, place: PointWithRotation, pin: PointWithRotation,