diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 1a722d1..499deee 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -8,19 +8,28 @@ use topola::{ Autorouter, }, board::{mesadata::AccessMesadata, Board}, - drawing::graph::{GetLayer, GetMaybeNet}, - geometry::shape::MeasureLength, + drawing::{ + dot::FixedDotIndex, + graph::{GetLayer, GetMaybeNet}, + }, + geometry::{shape::MeasureLength, GenericNode}, graph::{GetPetgraphIndex, MakeRef}, layout::LayoutEdit, + router::{navmesh::Navmesh, RouterOptions}, specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata}, }; -pub fn load_design_and_assert(filename: &str) -> Invoker { +pub fn load_design(filename: &str) -> Autorouter { let design_file = File::open(filename).unwrap(); let design_bufread = BufReader::new(design_file); let design = SpecctraDesign::load(design_bufread).unwrap(); - let mut invoker = - Invoker::new(Autorouter::new(design.make_board(&mut LayoutEdit::new())).unwrap()); + Autorouter::new(design.make_board(&mut LayoutEdit::new())).unwrap() +} + +pub fn create_invoker_and_assert( + autorouter: Autorouter, +) -> Invoker { + let mut invoker = Invoker::new(autorouter); assert!(matches!( invoker.undo(), @@ -60,6 +69,50 @@ pub fn replay_and_assert(invoker: &mut Invoker, filename: &str ); } +pub fn assert_navvertex_count( + autorouter: &mut Autorouter, + origin_pin: &str, + destination_pin: &str, + expected_count: usize, +) { + let (origin, destination) = autorouter + .ratsnest() + .graph() + .edge_indices() + .collect::>() + .iter() + .find_map(|ratline| { + let (candidate_origin, candidate_destination) = autorouter.ratline_endpoints(*ratline); + let candidate_origin_pin = autorouter + .board() + .node_pinname(&GenericNode::Primitive(candidate_origin.into())) + .unwrap(); + let candidate_destination_pin = autorouter + .board() + .node_pinname(&GenericNode::Primitive(candidate_destination.into())) + .unwrap(); + + ((candidate_origin_pin == origin_pin && candidate_destination_pin == destination_pin) + || (candidate_origin_pin == destination_pin + && candidate_destination_pin == origin_pin)) + .then_some((candidate_origin, candidate_destination)) + }) + .unwrap(); + + let navmesh = Navmesh::new( + autorouter.board().layout(), + origin, + destination, + RouterOptions { + wrap_around_bands: true, + squeeze_through_under_bands: false, + routed_band_width: 100.0, + }, + ) + .unwrap(); + assert_eq!(navmesh.graph().node_count(), expected_count); +} + pub fn assert_single_layer_groundless_autoroute( autorouter: &mut Autorouter, layername: &str, @@ -67,64 +120,64 @@ pub fn assert_single_layer_groundless_autoroute( let unionfind = unionfind(autorouter); for ratline in autorouter.ratsnest().graph().edge_indices() { - let (source_dot, target_dot) = autorouter.ratline_endpoints(ratline); + let (origin_dot, destination_dot) = autorouter.ratline_endpoints(ratline); - let source_layer = autorouter + let origin_layer = autorouter .board() .layout() .drawing() - .primitive(source_dot) + .primitive(origin_dot) .layer(); - let target_layer = autorouter + let destination_layer = autorouter .board() .layout() .drawing() - .primitive(target_dot) + .primitive(destination_dot) .layer(); - if let (Some(source_layername), Some(target_layername)) = ( + if let (Some(origin_layername), Some(destination_layername)) = ( autorouter .board() .layout() .rules() - .layer_layername(source_layer), + .layer_layername(origin_layer), autorouter .board() .layout() .rules() - .layer_layername(target_layer), + .layer_layername(destination_layer), ) { - assert_eq!(source_layername, target_layername); + assert_eq!(origin_layername, destination_layername); - if source_layername != layername { + if origin_layername != layername { continue; } } else { assert!(false); } - let source_net = autorouter + let origin_net = autorouter .board() .layout() .drawing() - .primitive(source_dot) + .primitive(origin_dot) .maybe_net(); - let target_net = autorouter + let destination_net = autorouter .board() .layout() .drawing() - .primitive(target_dot) + .primitive(destination_dot) .maybe_net(); - assert_eq!(source_net, target_net); + assert_eq!(origin_net, destination_net); - let net = source_net.unwrap(); + let net = origin_net.unwrap(); if let Some(netname) = autorouter.board().layout().rules().net_netname(net) { // We don't route ground. if netname != "GND" { assert_eq!( - unionfind.find(source_dot.petgraph_index()), - unionfind.find(target_dot.petgraph_index()) + unionfind.find(origin_dot.petgraph_index()), + unionfind.find(destination_dot.petgraph_index()) ); } } @@ -145,12 +198,12 @@ pub fn assert_single_layer_groundless_autoroute( pub fn assert_band_length( board: &Board, - source: &str, - target: &str, + source_pin: &str, + target_pin: &str, expected_length: f64, rel_err: f64, ) { - let band = board.band_between_pins(source, target).unwrap(); + let band = board.band_between_pins(source_pin, target_pin).unwrap(); let band_length = band.0.ref_(board.layout().drawing()).length(); assert!( (band_length - expected_length).abs() < expected_length * rel_err, diff --git a/tests/multilayer.rs b/tests/multilayer.rs index eb38870..d828330 100644 --- a/tests/multilayer.rs +++ b/tests/multilayer.rs @@ -9,9 +9,9 @@ mod common; #[test] fn test_unrouted_lm317_breakout() { - let mut invoker = common::load_design_and_assert( + let mut invoker = common::create_invoker_and_assert(common::load_design( "tests/multilayer/prerouted_lm317_breakout/unrouted_lm317_breakout.dsn", - ); + )); let result = invoker.execute(Command::PlaceVia(ViaWeight { from_layer: 0, @@ -32,9 +32,9 @@ fn test_unrouted_lm317_breakout() { #[test] fn test_signal_integrity_test() { - let invoker = common::load_design_and_assert( + let invoker = common::create_invoker_and_assert(common::load_design( "tests/multilayer/signal_integrity_test/signal_integrity_test.dsn", - ); + )); assert_eq!( invoker diff --git a/tests/single_layer.rs b/tests/single_layer.rs index cb4ddcf..efc9461 100644 --- a/tests/single_layer.rs +++ b/tests/single_layer.rs @@ -12,8 +12,9 @@ mod common; #[test] fn test_0603_breakout() { - let mut invoker = - common::load_design_and_assert("tests/single_layer/0603_breakout/0603_breakout.dsn"); + let mut autorouter = common::load_design("tests/single_layer/0603_breakout/0603_breakout.dsn"); + common::assert_navvertex_count(&mut autorouter, "R1-2", "J1-2", 50); + let mut invoker = common::create_invoker_and_assert(autorouter); common::replay_and_assert( &mut invoker, "tests/single_layer/0603_breakout/autoroute_all.cmd", @@ -27,9 +28,11 @@ fn test_0603_breakout() { #[test] fn test_tht_diode_bridge_rectifier() { - let mut invoker = common::load_design_and_assert( + let mut autorouter = common::load_design( "tests/single_layer/tht_diode_bridge_rectifier/tht_diode_bridge_rectifier.dsn", ); + common::assert_navvertex_count(&mut autorouter, "J2-2", "D4-2", 56); + let mut invoker = common::create_invoker_and_assert(autorouter); common::replay_and_assert( &mut invoker, "tests/single_layer/tht_diode_bridge_rectifier/autoroute_all.cmd", @@ -61,9 +64,11 @@ fn test_tht_diode_bridge_rectifier() { #[test] fn test_4x_3rd_order_smd_lc_filters() { - let mut invoker = common::load_design_and_assert( + let mut autorouter = common::load_design( "tests/single_layer/4x_3rd_order_smd_lc_filters/4x_3rd_order_smd_lc_filters.dsn", ); + common::assert_navvertex_count(&mut autorouter, "J1-1", "L1-1", 1954); + let mut invoker = common::create_invoker_and_assert(autorouter); common::replay_and_assert( &mut invoker, "tests/single_layer/4x_3rd_order_smd_lc_filters/autoroute_signals.cmd", @@ -79,9 +84,11 @@ fn test_4x_3rd_order_smd_lc_filters() { // NOTE: Disabled until determinism is fixed. //#[test] fn test_tht_3pin_xlr_to_tht_3pin_xlr() { - let mut invoker = common::load_design_and_assert( + let mut autorouter = common::load_design( "tests/single_layer/tht_3pin_xlr_to_tht_3pin_xlr/tht_3pin_xlr_to_tht_3pin_xlr.dsn", ); + //common::assert_navvertex_count(&mut autorouter, "R1-2", "J1-2", ?); + let mut invoker = common::create_invoker_and_assert(autorouter); common::replay_and_assert( &mut invoker, "tests/single_layer/tht_3pin_xlr_to_tht_3pin_xlr/autoroute_all.cmd",