/* * Copyright (C) 2014 Alfons Wirtz * website www.freerouting.net * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License at <http://www.gnu.org/licenses/> * for more details. * * Validate.java * * Created on 7. Dezember 2002, 18:26 */ package tests; import geometry.planar.IntOctagon; import geometry.planar.IntPoint; import geometry.planar.Polyline; import geometry.planar.TileShape; import java.util.Collection; import java.util.Iterator; import board.Item; import board.BasicBoard; import board.PolylineTrace; import board.SearchTreeObject; /** * Some consistancy checking on a routing board. * * @author Alfons Wirtz */ public class Validate { /** * Does some consistancy checking on the routing board and may be some * other actions. * Returns false, if problems were detected. */ public static boolean check(String p_s, BasicBoard p_board) { if (p_board.get_test_level() == board.TestLevel.RELEASE_VERSION) { return true; } boolean result = true; IntOctagon surr_oct = p_board.bounding_box.to_IntOctagon(); int layer_count = p_board.get_layer_count(); if (last_violation_count == null) { last_violation_count = new int [layer_count]; } for (int layer = 0; layer < layer_count; ++layer) { if (first_time) { System.out.println(" validate board is on "); first_time = false; } Collection<SearchTreeObject> l = p_board.overlapping_objects(surr_oct, layer) ; Iterator<SearchTreeObject> i = l.iterator(); int clearance_violation_count = 0; int conflict_ob_count = 0; int trace_count = 0; while(i.hasNext()) { Item curr_ob = (Item) i.next(); if (!curr_ob.validate()) { System.out.println(p_s) ; } int cl_count = curr_ob.clearance_violation_count(); if (cl_count > 0) { ++conflict_ob_count; clearance_violation_count += cl_count; } if (curr_ob instanceof PolylineTrace) { ++ trace_count; } } if (conflict_ob_count == 1) { System.out.println("conflicts not symmetric"); } if (clearance_violation_count != last_violation_count[layer]) { result = false; System.out.print(clearance_violation_count); System.out.print(" clearance violations on layer ") ; System.out.print(layer); System.out.print(" ") ; System.out.println(p_s); if (clearance_violation_count > 0) { System.out.print("with items of nets: ") ; } i = l.iterator(); while(i.hasNext()) { Item curr_ob = (Item) i.next(); int cl_count = curr_ob.clearance_violation_count(); if (cl_count == 0) { continue; } int curr_net_no = 0; if (curr_ob instanceof PolylineTrace) { PolylineTrace curr_trace = (PolylineTrace) curr_ob; if (curr_trace.net_count() > 0) { curr_net_no = curr_trace.get_net_no(0); } } System.out.print(curr_net_no); System.out.print(", "); } System.out.println(); } if (clearance_violation_count != last_violation_count[layer]) { last_violation_count[layer] = clearance_violation_count; } } return result; } static public boolean check(String p_s, BasicBoard p_board, Polyline p_polyline, int p_layer, int p_half_width, int[] p_net_no_arr, int p_cl_type) { TileShape[] offset_shapes = p_polyline.offset_shapes(p_half_width, 0, p_polyline.arr.length -1); for (int i = 0; i < offset_shapes.length; ++i) { Collection<Item> obstacles = p_board.search_tree_manager.get_default_tree().overlapping_items_with_clearance(offset_shapes[i], p_layer, p_net_no_arr, p_cl_type); Iterator<Item> it = obstacles.iterator(); while(it.hasNext()) { Item curr_obs = it.next(); if (!curr_obs.shares_net_no(p_net_no_arr)) { System.out.print(p_s); System.out.println(": cannot insert trace without violations"); return false; } } } return true; } /** * check, that all traces on p_board are orthogonal */ static public void orthogonal(String p_s, BasicBoard p_board) { Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_ob = it.next(); if(curr_ob instanceof PolylineTrace) { PolylineTrace curr_trace = (PolylineTrace) curr_ob; if (!curr_trace.polyline().is_orthogonal()) { System.out.print(p_s); System.out.println(": trace not orthogonal"); break; } } } } /** * check, that all traces on p_board are multiples of 45 degree */ static public void multiple_of_45_degree(String p_s, BasicBoard p_board) { int count = 0; Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_ob = it.next(); if(curr_ob instanceof PolylineTrace) { PolylineTrace curr_trace = (PolylineTrace) curr_ob; if (!curr_trace.polyline().is_multiple_of_45_degree()) { ++count; } } } if (count > 1) { System.out.print(p_s); System.out.print(count); System.out.println(" traces not 45 degree"); } } static public boolean corners_on_grid(String p_s, Polyline p_polyline) { for (int i = 0; i < p_polyline.corner_count(); ++i) { if (!(p_polyline.corner(i) instanceof IntPoint)) { System.out.print(p_s); System.out.println(": corner not on grid"); return false; } } return true; } static public int stub_count(String p_s, BasicBoard p_board, int p_net_no) { if (first_time) { System.out.println(" stub_count is on "); first_time = false; } int result = 0; Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_ob = it.next(); if(curr_ob instanceof PolylineTrace) { PolylineTrace curr_trace = (PolylineTrace) curr_ob; if(curr_trace.contains_net(p_net_no)) { if (curr_trace.get_start_contacts().size() == 0) { ++result; } if (curr_trace.get_end_contacts().size() == 0) { ++result; } } } } if (result != prev_stub_count) { System.out.print(result + " stubs "); System.out.println(p_s); prev_stub_count = result; } return result; } static public boolean has_cycles(String p_s, BasicBoard p_board) { boolean result = false; Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_item = it.next(); if (!(curr_item instanceof board.Trace)) { continue; } if(((board.Trace)curr_item).is_cycle()) { System.out.print(p_s); System.out.println(": cycle found"); result = true; break; } } return result; } /** checks, if there are more than p_max_count traces with * net number p_net_no */ static public boolean trace_count_exceeded(String p_s, BasicBoard p_board, int p_net_no, int p_max_count) { int found_traces = 0; Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_ob = it.next(); if(curr_ob instanceof board.Trace) { if (((board.Trace)curr_ob).contains_net(p_net_no)) { ++found_traces; } } } if ( found_traces > p_max_count) { System.out.print(p_s); System.out.print(": "); System.out.print(p_max_count); System.out.println(" traces exceeded"); return true; } return false; } /** * checks, if there are unconnectedtraces ore vias on the board */ static public boolean unconnnected_routing_items(String p_s, BasicBoard p_board) { Iterator<Item> it = p_board.get_items().iterator(); while (it.hasNext()) { Item curr_item = it.next(); if(curr_item.is_route()) { Collection<Item> contact_list = curr_item.get_normal_contacts(); if (contact_list.size() == 0) { System.out.print(p_s); System.out.print(": uncontacted routing item found "); return true; } } } return false; } static private int [] last_violation_count = null; static private boolean first_time = true; static private int prev_stub_count = 0; }