/* * 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. * * Network.java * * Created on 22. Mai 2004, 07:44 */ package designformats.specctra; import geometry.planar.IntPoint; import geometry.planar.Point; import geometry.planar.Vector; import java.util.Collection; import java.util.LinkedList; import java.util.Set; import java.util.Iterator; import datastructures.IndentFileWriter; import datastructures.IdentifierType; import rules.BoardRules; import rules.DefaultItemClearanceClasses.ItemClass; import board.RoutingBoard; /** * Class for reading and writing net network from dsn-files. * * @author Alfons Wirtz */ public class Network extends ScopeKeyword { /** Creates a new instance of Network */ public Network() { super("network"); } public boolean read_scope(ReadScopeParameter p_par) { Collection<NetClass> classes = new LinkedList<NetClass>(); Collection<NetClass.ClassClass> class_class_list = new LinkedList<NetClass.ClassClass>(); Collection<rules.ViaInfo> via_infos = new LinkedList<rules.ViaInfo>(); Collection<Collection<String>> via_rules = new LinkedList<Collection<String>>(); Object next_token = null; for (;;) { Object prev_token = next_token; try { next_token = p_par.scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_scope: IO error scanning file"); System.out.println(e); return false; } if (next_token == null) { System.out.println("Network.read_scope: unexpected end of file"); return false; } if (next_token == CLOSED_BRACKET) { // end of scope break; } if (prev_token == OPEN_BRACKET) { if (next_token == Keyword.NET) { read_net_scope(p_par.scanner, p_par.netlist, p_par.board_handling.get_routing_board(), p_par.coordinate_transform, p_par.layer_structure, p_par.board_handling.get_locale()); } else if (next_token == Keyword.VIA) { rules.ViaInfo curr_via_info = read_via_info(p_par.scanner, p_par.board_handling.get_routing_board()); if (curr_via_info == null) { return false; } via_infos.add(curr_via_info); } else if (next_token == Keyword.VIA_RULE) { Collection<String> curr_via_rule = read_via_rule(p_par.scanner, p_par.board_handling.get_routing_board()); if (curr_via_rule == null) { return false; } via_rules.add(curr_via_rule); } else if (next_token == Keyword.CLASS) { NetClass curr_class = NetClass.read_scope(p_par.scanner); if (curr_class == null) { return false; } classes.add(curr_class); } else if (next_token == Keyword.CLASS_CLASS) { NetClass.ClassClass curr_class_class = NetClass.read_class_class_scope(p_par.scanner); if (curr_class_class == null) { return false; } class_class_list.add(curr_class_class); } else { skip_scope(p_par.scanner); } } } insert_via_infos(via_infos, p_par.board_handling.get_routing_board(), p_par.via_at_smd_allowed); insert_via_rules(via_rules, p_par.board_handling.get_routing_board()); insert_net_classes(classes, p_par); insert_class_pairs(class_class_list, p_par); insert_compoments(p_par); insert_logical_parts(p_par); return true; } public static void write_scope(WriteScopeParameter p_par) throws java.io.IOException { p_par.file.start_scope(); p_par.file.write("network"); Collection<board.Pin> board_pins = p_par.board.get_pins(); for (int i = 1; i <= p_par.board.rules.nets.max_net_no(); ++i) { Net.write_scope(p_par, p_par.board.rules.nets.get(i), board_pins); } write_via_infos(p_par.board.rules, p_par.file, p_par.identifier_type); write_via_rules(p_par.board.rules, p_par.file, p_par.identifier_type); write_net_classes(p_par); p_par.file.end_scope(); } public static void write_via_infos(rules.BoardRules p_rules, IndentFileWriter p_file, IdentifierType p_identifier_type) throws java.io.IOException { for (int i = 0; i < p_rules.via_infos.count(); ++i) { rules.ViaInfo curr_via = p_rules.via_infos.get(i); p_file.start_scope(); p_file.write("via "); p_file.new_line(); p_identifier_type.write(curr_via.get_name(), p_file); p_file.write(" "); p_identifier_type.write(curr_via.get_padstack().name, p_file); p_file.write(" "); p_identifier_type.write(p_rules.clearance_matrix.get_name(curr_via.get_clearance_class()), p_file); if (curr_via.attach_smd_allowed()) { p_file.write(" attach"); } p_file.end_scope(); } } public static void write_via_rules(rules.BoardRules p_rules, IndentFileWriter p_file, IdentifierType p_identifier_type) throws java.io.IOException { for (rules.ViaRule curr_rule : p_rules.via_rules) { p_file.start_scope(); p_file.write("via_rule"); p_file.new_line(); p_identifier_type.write(curr_rule.name, p_file); for (int i = 0; i < curr_rule.via_count(); ++i) { p_file.write(" "); p_identifier_type.write(curr_rule.get_via(i).get_name(), p_file); } p_file.end_scope(); } } public static void write_net_classes(WriteScopeParameter p_par) throws java.io.IOException { for (int i = 0; i < p_par.board.rules.net_classes.count(); ++i) { write_net_class(p_par.board.rules.net_classes.get(i), p_par); } } public static void write_net_class(rules.NetClass p_net_class, WriteScopeParameter p_par) throws java.io.IOException { p_par.file.start_scope(); p_par.file.write("class "); p_par.identifier_type.write(p_net_class.get_name(), p_par.file); final int nets_per_row = 8; int net_counter = 0; for (int i = 1; i <= p_par.board.rules.nets.max_net_no(); ++i) { if (p_par.board.rules.nets.get(i).get_class() == p_net_class) { if (net_counter % nets_per_row == 0) { p_par.file.new_line(); } else { p_par.file.write(" "); } p_par.identifier_type.write(p_par.board.rules.nets.get(i).name, p_par.file); ++net_counter; } } // write the trace clearance class Rule.write_item_clearance_class(p_par.board.rules.clearance_matrix.get_name(p_net_class.get_trace_clearance_class()), p_par.file, p_par.identifier_type); // write the via rule p_par.file.new_line(); p_par.file.write("(via_rule "); p_par.file.write(p_net_class.get_via_rule().name); p_par.file.write(")"); // write the rules, if they are different from the default rule. Rule.write_scope(p_net_class, p_par); write_circuit(p_net_class, p_par); if (!p_net_class.get_pull_tight()) { p_par.file.new_line(); p_par.file.write("(pull_tight off)"); } if (p_net_class.is_shove_fixed()) { p_par.file.new_line(); p_par.file.write("(shove_fixed on)"); } p_par.file.end_scope(); } private static void write_circuit(rules.NetClass p_net_class, WriteScopeParameter p_par) throws java.io.IOException { double min_trace_length = p_net_class.get_minimum_trace_length(); double max_trace_length = p_net_class.get_maximum_trace_length(); p_par.file.start_scope(); p_par.file.write("circuit "); p_par.file.new_line(); p_par.file.write("(use_layer"); int layer_count = p_net_class.layer_count(); for (int i = 0; i < layer_count; ++i) { if (p_net_class.is_active_routing_layer(i)) { p_par.file.write(" "); p_par.file.write(p_par.board.layer_structure.arr[i].name); } } p_par.file.write(")"); if (min_trace_length > 0 || max_trace_length > 0) { p_par.file.new_line(); p_par.file.write("(length "); Double transformed_max_length; if (max_trace_length <= 0) { transformed_max_length = (double) -1; } else { transformed_max_length = p_par.coordinate_transform.board_to_dsn(max_trace_length); } p_par.file.write(transformed_max_length.toString()); p_par.file.write(" "); Double transformed_min_length; if (min_trace_length <= 0) { transformed_min_length = (double) 0; } else { transformed_min_length = p_par.coordinate_transform.board_to_dsn(min_trace_length); } p_par.file.write(transformed_min_length.toString()); p_par.file.write(")"); } p_par.file.end_scope(); } private boolean read_net_scope(Scanner p_scanner, NetList p_net_list, RoutingBoard p_board, CoordinateTransform p_coordinate_transform, LayerStructure p_layer_structure, java.util.Locale p_locale) { // read the net name Object next_token; try { next_token = p_scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_net_scope: IO error while scanning file"); return false; } if (!(next_token instanceof String)) { System.out.println("Network.read_net_scope: String expected"); return false; } String net_name = (String) next_token; int subnet_number = 1; try { next_token = p_scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_net_scope: IO error while scanning file"); return false; } boolean scope_is_empty = (next_token == CLOSED_BRACKET); if (next_token instanceof Integer) { subnet_number = ((Integer) next_token).intValue(); } boolean pin_order_found = false; Collection<Net.Pin> pin_list = new LinkedList<Net.Pin>(); Collection<Rule> net_rules = new LinkedList<Rule>(); Collection<Collection<Net.Pin>> subnet_pin_lists = new LinkedList<Collection<Net.Pin>>(); if (!scope_is_empty) { for (;;) { Object prev_token = next_token; try { next_token = p_scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_net_scope: IO error scanning file"); return false; } if (next_token == null) { System.out.println("Network.read_net_scope: unexpected end of file"); return false; } if (next_token == CLOSED_BRACKET) { // end of scope break; } if (prev_token == OPEN_BRACKET) { if (next_token == Keyword.PINS) { if (!read_net_pins(p_scanner, pin_list)) { return false; } } else if (next_token == Keyword.ORDER) { pin_order_found = true; if (!read_net_pins(p_scanner, pin_list)) { return false; } } else if (next_token == Keyword.FROMTO) { Set<Net.Pin> curr_subnet_pin_list = new java.util.TreeSet<Net.Pin>(); if (!read_net_pins(p_scanner, curr_subnet_pin_list)) { return false; } subnet_pin_lists.add(curr_subnet_pin_list); } else if (next_token == Keyword.RULE) { net_rules.addAll(Rule.read_scope(p_scanner)); } else if (next_token == Keyword.LAYER_RULE) { System.out.println("Netwark.read_net_scope: layer_rule not yet implemented"); skip_scope(p_scanner); } else { skip_scope(p_scanner); } } } } if (subnet_pin_lists.isEmpty()) { if (pin_order_found) { subnet_pin_lists = create_ordered_subnets(pin_list); } else { subnet_pin_lists.add(pin_list); } } for (Collection<Net.Pin> curr_pin_list : subnet_pin_lists) { Net.Id net_id = new Net.Id(net_name, subnet_number); if (!p_net_list.contains(net_id)) { Net new_net = p_net_list.add_net(net_id); boolean contains_plane = p_layer_structure.contains_plane(net_name); if (new_net != null) { p_board.rules.nets.add(new_net.id.name, new_net.id.subnet_number, contains_plane); } } Net curr_subnet = p_net_list.get_net(net_id); if (curr_subnet == null) { System.out.println("Network.read_net_scope: net not found in netlist"); return false; } curr_subnet.set_pins(curr_pin_list); if (!net_rules.isEmpty()) { // Evaluate the net rules. rules.Net board_net = p_board.rules.nets.get(curr_subnet.id.name, curr_subnet.id.subnet_number); if (board_net == null) { System.out.println("Network.read_net_scope: board net not found"); return false; } Iterator<Rule> it = net_rules.iterator(); while (it.hasNext()) { Rule curr_ob = it.next(); if (curr_ob instanceof Rule.WidthRule) { rules.NetClass default_net_rule = p_board.rules.get_default_net_class(); double wire_width = ((Rule.WidthRule) curr_ob).value; int trace_halfwidth = (int) Math.round(p_coordinate_transform.dsn_to_board(wire_width) / 2); rules.NetClass net_rule = p_board.rules.net_classes.find(trace_halfwidth, default_net_rule.get_trace_clearance_class(), default_net_rule.get_via_rule()); if (net_rule == null) { // create a new net rule net_rule = p_board.rules.get_new_net_class(p_locale); } net_rule.set_trace_half_width(trace_halfwidth); board_net.set_class(net_rule); } else { System.out.println("Network.read_net_scope: Rule not yet implemented"); } } } ++subnet_number; } return true; } /** * Creates a sequence of subnets with 2 pins from p_pin_list */ private static Collection<Collection<Net.Pin>> create_ordered_subnets(Collection<Net.Pin> p_pin_list) { Collection<Collection<Net.Pin>> result = new LinkedList<Collection<Net.Pin>>(); if (p_pin_list.isEmpty()) { return result; } Iterator<Net.Pin> it = p_pin_list.iterator(); Net.Pin prev_pin = it.next(); while (it.hasNext()) { Net.Pin next_pin = it.next(); Set<Net.Pin> curr_subnet_pin_list = new java.util.TreeSet<Net.Pin>(); curr_subnet_pin_list.add(prev_pin); curr_subnet_pin_list.add(next_pin); result.add(curr_subnet_pin_list); prev_pin = next_pin; } return result; } private static boolean read_net_pins(Scanner p_scanner, Collection<Net.Pin> p_pin_list) { Object next_token; for (;;) { try { p_scanner.yybegin(SpecctraFileScanner.COMPONENT_NAME); next_token = p_scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_net_pins: IO error while scanning file"); return false; } if (next_token == Keyword.CLOSED_BRACKET) { break; } if (!(next_token instanceof String)) { System.out.println("Network.read_net_pins: String expected"); return false; } String component_name = (String) next_token; try { p_scanner.yybegin(SpecctraFileScanner.SPEC_CHAR); next_token = p_scanner.next_token(); // overread the hyphen p_scanner.yybegin(SpecctraFileScanner.NAME); next_token = p_scanner.next_token(); } catch (java.io.IOException e) { System.out.println("Network.read_net_pins: IO error while scanning file"); return false; } if (!(next_token instanceof String)) { System.out.println("Network.read_net_pins: String expected"); return false; } String pin_name = (String) next_token; Net.Pin curr_entry = new Net.Pin(component_name, pin_name); p_pin_list.add(curr_entry); } return true; } static rules.ViaInfo read_via_info(Scanner p_scanner, board.BasicBoard p_board) { try { p_scanner.yybegin(SpecctraFileScanner.NAME); Object next_token = p_scanner.next_token(); if (!(next_token instanceof String)) { System.out.println("Network.read_via_info: string expected"); return null; } String name = (String) next_token; p_scanner.yybegin(SpecctraFileScanner.NAME); next_token = p_scanner.next_token(); if (!(next_token instanceof String)) { System.out.println("Network.read_via_info: string expected"); return null; } String padstack_name = (String) next_token; library.Padstack via_padstack = p_board.library.get_via_padstack(padstack_name); if (via_padstack == null) { // The padstack may not yet be inserted into the list of via padstacks via_padstack = p_board.library.padstacks.get(padstack_name); if (via_padstack == null) { System.out.println("Network.read_via_info: padstack not found"); return null; } p_board.library.add_via_padstack(via_padstack); } p_scanner.yybegin(SpecctraFileScanner.NAME); next_token = p_scanner.next_token(); if (!(next_token instanceof String)) { System.out.println("Network.read_via_info: string expected"); return null; } int clearance_class = p_board.rules.clearance_matrix.get_no((String) next_token); if (clearance_class < 0) { // Clearance class not stored, because it is identical to the default clearance class. clearance_class = BoardRules.default_clearance_class(); } boolean attach_allowed = false; next_token = p_scanner.next_token(); if (next_token != Keyword.CLOSED_BRACKET) { if (next_token != Keyword.ATTACH) { System.out.println("Network.read_via_info: Keyword.ATTACH expected"); return null; } attach_allowed = true; next_token = p_scanner.next_token(); if (next_token != Keyword.CLOSED_BRACKET) { System.out.println("Network.read_via_info: closing bracket expected"); return null; } } return new rules.ViaInfo(name, via_padstack, clearance_class, attach_allowed, p_board.rules); } catch (java.io.IOException e) { System.out.println("Network.read_via_info: IO error while scanning file"); return null; } } static Collection<String> read_via_rule(Scanner p_scanner, board.BasicBoard p_board) { try { Collection<String> result = new LinkedList<String>(); for (;;) { p_scanner.yybegin(SpecctraFileScanner.NAME); Object next_token = p_scanner.next_token(); if (next_token == Keyword.CLOSED_BRACKET) { break; } if (!(next_token instanceof String)) { System.out.println("Network.read_via_rule: string expected"); return null; } result.add((String) next_token); } return result; } catch (java.io.IOException e) { System.out.println("Network.read_via_rule: IO error while scanning file"); return null; } } private static void insert_via_infos(Collection<rules.ViaInfo> p_via_infos, RoutingBoard p_board, boolean p_attach_allowed) { if (p_via_infos.size() > 0) { for (rules.ViaInfo curr_info : p_via_infos) { p_board.rules.via_infos.add(curr_info); } } else // no via infos found, create default via infos from the via padstacks. { create_default_via_infos(p_board, p_board.rules.get_default_net_class(), p_attach_allowed); } } private static void create_default_via_infos(board.BasicBoard p_board, rules.NetClass p_net_class, boolean p_attach_allowed) { int cl_class = p_net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.VIA); boolean is_default_class = (p_net_class == p_board.rules.get_default_net_class()); for (int i = 0; i < p_board.library.via_padstack_count(); ++i) { library.Padstack curr_padstack = p_board.library.get_via_padstack(i); boolean attach_allowed = p_attach_allowed && curr_padstack.attach_allowed; String via_name; if (is_default_class) { via_name = curr_padstack.name; } else { via_name = curr_padstack.name + DsnFile.CLASS_CLEARANCE_SEPARATOR + p_net_class.get_name(); } rules.ViaInfo found_via_info = new rules.ViaInfo(via_name, curr_padstack, cl_class, attach_allowed, p_board.rules); p_board.rules.via_infos.add(found_via_info); } } private static void insert_via_rules(Collection<Collection<String>> p_via_rules, board.BasicBoard p_board) { boolean rule_found = false; for (Collection<String> curr_list : p_via_rules) { if (curr_list.size() < 2) { continue; } if (add_via_rule(curr_list, p_board)) { rule_found = true; } } if (!rule_found) { p_board.rules.create_default_via_rule(p_board.rules.get_default_net_class(), "default"); } for (int i = 0; i < p_board.rules.net_classes.count(); ++i) { p_board.rules.net_classes.get(i).set_via_rule(p_board.rules.get_default_via_rule()); } } /** * Inserts a via rule into the board. * Replaces an already existing via rule with the same */ static boolean add_via_rule(Collection<String> p_name_list, board.BasicBoard p_board) { Iterator<String> it = p_name_list.iterator(); String rule_name = it.next(); rules.ViaRule existing_rule = p_board.rules.get_via_rule(rule_name); rules.ViaRule curr_rule = new rules.ViaRule(rule_name); boolean rule_ok = true; while (it.hasNext()) { rules.ViaInfo curr_via = p_board.rules.via_infos.get(it.next()); if (curr_via != null) { curr_rule.append_via(curr_via); } else { System.out.println("Network.insert_via_rules: via_info not found"); rule_ok = false; } } if (rule_ok) { if (existing_rule != null) { // Replace already existing rule. p_board.rules.via_rules.remove(existing_rule); } p_board.rules.via_rules.add(curr_rule); } return rule_ok; } private static void insert_net_classes(Collection<NetClass> p_net_classes, ReadScopeParameter p_par) { board.BasicBoard routing_board = p_par.board_handling.get_routing_board(); for (NetClass curr_class : p_net_classes) { insert_net_class(curr_class, p_par.layer_structure, routing_board, p_par.coordinate_transform, p_par.via_at_smd_allowed); } } static void insert_net_class(NetClass p_class, LayerStructure p_layer_structure, board.BasicBoard p_board, CoordinateTransform p_coordinate_transform, boolean p_via_at_smd_allowed) { rules.NetClass board_net_class = p_board.rules.append_net_class(p_class.name); if (p_class.trace_clearance_class != null) { int trace_clearance_class = p_board.rules.clearance_matrix.get_no(p_class.trace_clearance_class); if (trace_clearance_class >= 0) { board_net_class.set_trace_clearance_class(trace_clearance_class); } else { System.out.println("Network.insert_net_class: clearance class not found"); } } if (p_class.via_rule != null) { rules.ViaRule via_rule = p_board.rules.get_via_rule(p_class.via_rule); if (via_rule != null) { board_net_class.set_via_rule(via_rule); } else { System.out.println("Network.insert_net_class: via rule not found"); } } if (p_class.max_trace_length > 0) { board_net_class.set_maximum_trace_length(p_coordinate_transform.dsn_to_board(p_class.max_trace_length)); } if (p_class.min_trace_length > 0) { board_net_class.set_minimum_trace_length(p_coordinate_transform.dsn_to_board(p_class.min_trace_length)); } for (String curr_net_name : p_class.net_list) { Collection<rules.Net> curr_net_list = p_board.rules.nets.get(curr_net_name); for (rules.Net curr_net : curr_net_list) { curr_net.set_class(board_net_class); } } // read the trace width and clearance rules. boolean clearance_rule_found = false; for (Rule curr_rule : p_class.rules) { if (curr_rule instanceof Rule.WidthRule) { int trace_halfwidth = (int) Math.round(p_coordinate_transform.dsn_to_board(((Rule.WidthRule) curr_rule).value / 2)); board_net_class.set_trace_half_width(trace_halfwidth); } else if (curr_rule instanceof Rule.ClearanceRule) { add_clearance_rule(p_board.rules.clearance_matrix, board_net_class, (Rule.ClearanceRule) curr_rule, -1, p_coordinate_transform); clearance_rule_found = true; } else { System.out.println("Network.insert_net_class: rule type not yet implemented"); } } // read the layer dependent rules. for (Rule.LayerRule curr_layer_rule : p_class.layer_rules) { for (String curr_layer_name : curr_layer_rule.layer_names) { int layer_no = p_board.layer_structure.get_no(curr_layer_name); if (layer_no < 0) { System.out.println("Network.insert_net_class: layer not found"); continue; } for (Rule curr_rule : curr_layer_rule.rules) { if (curr_rule instanceof Rule.WidthRule) { int trace_halfwidth = (int) Math.round(p_coordinate_transform.dsn_to_board(((Rule.WidthRule) curr_rule).value / 2)); board_net_class.set_trace_half_width(layer_no, trace_halfwidth); } else if (curr_rule instanceof Rule.ClearanceRule) { add_clearance_rule(p_board.rules.clearance_matrix, board_net_class, (Rule.ClearanceRule) curr_rule, layer_no, p_coordinate_transform); clearance_rule_found = true; } else { System.out.println("Network.insert_net_class: layer rule type not yet implemented"); } } } } board_net_class.set_pull_tight(p_class.pull_tight); board_net_class.set_shove_fixed(p_class.shove_fixed); boolean via_infos_created = false; if (clearance_rule_found && board_net_class != p_board.rules.get_default_net_class()) { create_default_via_infos(p_board, board_net_class, p_via_at_smd_allowed); via_infos_created = true; } if (!p_class.use_via.isEmpty()) { create_via_rule(p_class.use_via, board_net_class, p_board, p_via_at_smd_allowed); } else if (via_infos_created) { p_board.rules.create_default_via_rule(board_net_class, board_net_class.get_name()); } if (!p_class.use_layer.isEmpty()) { create_active_trace_layers(p_class.use_layer, p_layer_structure, board_net_class); } } static private void insert_class_pairs(Collection<NetClass.ClassClass> p_class_classes, ReadScopeParameter p_par) { for (NetClass.ClassClass curr_class_class : p_class_classes) { java.util.Iterator<String> it1 = curr_class_class.class_names.iterator(); board.BasicBoard routing_board = p_par.board_handling.get_routing_board(); while (it1.hasNext()) { String first_name = it1.next(); rules.NetClass first_class = routing_board.rules.net_classes.get(first_name); if (first_class == null) { System.out.println("Network.insert_class_pairs: first class not found"); } else { java.util.Iterator<String> it2 = it1; while (it2.hasNext()) { String second_name = it2.next(); rules.NetClass second_class = routing_board.rules.net_classes.get(second_name); if (second_class == null) { System.out.println("Network.insert_class_pairs: second class not found"); } else { insert_class_pair_info(curr_class_class, first_class, second_class, routing_board, p_par.coordinate_transform); } } } } } } static private void insert_class_pair_info(NetClass.ClassClass p_class_class, rules.NetClass p_first_class, rules.NetClass p_second_class, board.BasicBoard p_board, CoordinateTransform p_coordinate_transform) { for (Rule curr_rule : p_class_class.rules) { if (curr_rule instanceof Rule.ClearanceRule) { Rule.ClearanceRule curr_clearance_rule = (Rule.ClearanceRule) curr_rule; add_mixed_clearance_rule(p_board.rules.clearance_matrix, p_first_class, p_second_class, curr_clearance_rule, -1, p_coordinate_transform); } else { System.out.println("Network.insert_class_pair_info: unexpected rule"); } } for (Rule.LayerRule curr_layer_rule : p_class_class.layer_rules) { for (String curr_layer_name : curr_layer_rule.layer_names) { int layer_no = p_board.layer_structure.get_no(curr_layer_name); if (layer_no < 0) { System.out.println("Network.insert_class_pair_info: layer not found"); continue; } for (Rule curr_rule : curr_layer_rule.rules) { if (curr_rule instanceof Rule.ClearanceRule) { add_mixed_clearance_rule(p_board.rules.clearance_matrix, p_first_class, p_second_class, (Rule.ClearanceRule) curr_rule, layer_no, p_coordinate_transform); } else { System.out.println("Network.insert_class_pair_info: unexpected layer rule type"); } } } } } static private void add_mixed_clearance_rule(rules.ClearanceMatrix p_clearance_matrix, rules.NetClass p_first_class, rules.NetClass p_second_class, Rule.ClearanceRule p_clearance_rule, int p_layer_no, CoordinateTransform p_coordinate_transform) { int curr_clearance = (int) Math.round(p_coordinate_transform.dsn_to_board(p_clearance_rule.value)); final String first_class_name = p_first_class.get_name(); int first_class_no = p_clearance_matrix.get_no(first_class_name); if (first_class_no < 0) { p_clearance_matrix.append_class(first_class_name); first_class_no = p_clearance_matrix.get_no(first_class_name); } final String second_class_name = p_second_class.get_name(); int second_class_no = p_clearance_matrix.get_no(second_class_name); if (second_class_no < 0) { p_clearance_matrix.append_class(second_class_name); second_class_no = p_clearance_matrix.get_no(second_class_name); } if (p_clearance_rule.clearance_class_pairs.isEmpty()) { if (p_layer_no < 0) { p_clearance_matrix.set_value(first_class_no, second_class_no, curr_clearance); p_clearance_matrix.set_value(second_class_no, first_class_no, curr_clearance); } else { p_clearance_matrix.set_value(first_class_no, second_class_no, p_layer_no, curr_clearance); p_clearance_matrix.set_value(second_class_no, first_class_no, p_layer_no, curr_clearance); } } else { Iterator<String> it = p_clearance_rule.clearance_class_pairs.iterator(); while (it.hasNext()) { String curr_string = it.next(); String[] curr_pair = curr_string.split("_"); if (curr_pair.length != 2) { continue; } int curr_first_class_no; int curr_second_class_no; for (int i = 0; i < 2; ++i) { if (i == 0) { curr_first_class_no = get_clearance_class(p_clearance_matrix, p_first_class, curr_pair[0]); curr_second_class_no = get_clearance_class(p_clearance_matrix, p_second_class, curr_pair[1]); } else { curr_first_class_no = get_clearance_class(p_clearance_matrix, p_second_class, curr_pair[0]); curr_second_class_no = get_clearance_class(p_clearance_matrix, p_first_class, curr_pair[1]); } if (p_layer_no < 0) { p_clearance_matrix.set_value(curr_first_class_no, curr_second_class_no, curr_clearance); p_clearance_matrix.set_value(curr_second_class_no, curr_first_class_no, curr_clearance); } else { p_clearance_matrix.set_value(curr_first_class_no, curr_second_class_no, p_layer_no, curr_clearance); p_clearance_matrix.set_value(curr_second_class_no, curr_first_class_no, p_layer_no, curr_clearance); } } } } } static private void create_default_clearance_classes(rules.NetClass p_net_class, rules.ClearanceMatrix p_clearance_matrix) { get_clearance_class(p_clearance_matrix, p_net_class, "via"); get_clearance_class(p_clearance_matrix, p_net_class, "smd"); get_clearance_class(p_clearance_matrix, p_net_class, "pin"); get_clearance_class(p_clearance_matrix, p_net_class, "area"); } private static void create_via_rule(Collection<String> p_use_via, rules.NetClass p_net_class, board.BasicBoard p_board, boolean p_attach_allowed) { rules.ViaRule new_via_rule = new rules.ViaRule(p_net_class.get_name()); int default_via_cl_class = p_net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.VIA); for (String curr_via_name : p_use_via) { for (int i = 0; i < p_board.rules.via_infos.count(); ++i) { rules.ViaInfo curr_via_info = p_board.rules.via_infos.get(i); if (curr_via_info.get_clearance_class() == default_via_cl_class) { if (curr_via_info.get_padstack().name.equals(curr_via_name)) { new_via_rule.append_via(curr_via_info); } } } } p_board.rules.via_rules.add(new_via_rule); p_net_class.set_via_rule(new_via_rule); } private static void create_active_trace_layers(Collection<String> p_use_layer, LayerStructure p_layer_structure, rules.NetClass p_net_class) { for (int i = 0; i < p_layer_structure.arr.length; ++i) { p_net_class.set_active_routing_layer(i, false); } for (String cur_layer_name : p_use_layer) { int curr_no = p_layer_structure.get_no(cur_layer_name); p_net_class.set_active_routing_layer(curr_no, true); } // currently all inactive layers have tracewidth 0. for (int i = 0; i < p_layer_structure.arr.length; ++i) { if (!p_net_class.is_active_routing_layer(i)) { p_net_class.set_trace_half_width(i, 0); } } } private static void add_clearance_rule(rules.ClearanceMatrix p_clearance_matrix, rules.NetClass p_net_class, Rule.ClearanceRule p_rule, int p_layer_no, CoordinateTransform p_coordinate_transform) { int curr_clearance = (int) Math.round(p_coordinate_transform.dsn_to_board(p_rule.value)); final String class_name = p_net_class.get_name(); int class_no = p_clearance_matrix.get_no(class_name); if (class_no < 0) { // class not yet existing, create a new class p_clearance_matrix.append_class(class_name); class_no = p_clearance_matrix.get_no(class_name); // set the clearance values of the new class to the maximum of curr_clearance and the // the existing values. for (int i = 1; i < p_clearance_matrix.get_class_count(); ++i) { for (int j = 0; j < p_clearance_matrix.get_layer_count(); ++j) { int curr_value = Math.max(p_clearance_matrix.value(class_no, i, j), curr_clearance); p_clearance_matrix.set_value(class_no, i, j, curr_value); p_clearance_matrix.set_value(i, class_no, j, curr_value); } } p_net_class.default_item_clearance_classes.set_all(class_no); } p_net_class.set_trace_clearance_class(class_no); if (p_rule.clearance_class_pairs.isEmpty()) { if (p_layer_no < 0) { p_clearance_matrix.set_value(class_no, class_no, curr_clearance); } else { p_clearance_matrix.set_value(class_no, class_no, p_layer_no, curr_clearance); } return; } if (Structure.contains_wire_clearance_pair(p_rule.clearance_class_pairs)) { create_default_clearance_classes(p_net_class, p_clearance_matrix); } Iterator<String> it = p_rule.clearance_class_pairs.iterator(); while (it.hasNext()) { String curr_string = it.next(); String[] curr_pair = curr_string.split("_"); if (curr_pair.length != 2) { continue; } int first_class_no = get_clearance_class(p_clearance_matrix, p_net_class, curr_pair[0]); int second_class_no = get_clearance_class(p_clearance_matrix, p_net_class, curr_pair[1]); if (p_layer_no < 0) { p_clearance_matrix.set_value(first_class_no, second_class_no, curr_clearance); p_clearance_matrix.set_value(second_class_no, first_class_no, curr_clearance); } else { p_clearance_matrix.set_value(first_class_no, second_class_no, p_layer_no, curr_clearance); p_clearance_matrix.set_value(second_class_no, first_class_no, p_layer_no, curr_clearance); } } } /** * Gets the number of the clearance class with name combined of p_net_class_name and p_item_class_name. * Creates a new class, if that class is not yet existing. */ static private int get_clearance_class(rules.ClearanceMatrix p_clearance_matrix, rules.NetClass p_net_class, String p_item_class_name) { String net_class_name = p_net_class.get_name(); String new_class_name = net_class_name; if (!p_item_class_name.equals("wire")) { new_class_name = new_class_name + DsnFile.CLASS_CLEARANCE_SEPARATOR + p_item_class_name; } int found_class_no = p_clearance_matrix.get_no(new_class_name); if (found_class_no >= 0) { return found_class_no; } p_clearance_matrix.append_class(new_class_name); int result = p_clearance_matrix.get_no(new_class_name); int net_class_no = p_clearance_matrix.get_no(net_class_name); if (net_class_no < 0 || result < 0) { System.out.println("Network.get_clearance_class: clearance class not found"); return result; } // initalise the clearance values of p_new_class_name from p_net_class_name for (int i = 1; i < p_clearance_matrix.get_class_count(); ++i) { for (int j = 0; j < p_clearance_matrix.get_layer_count(); ++j) { int curr_value = p_clearance_matrix.value(net_class_no, i, j); p_clearance_matrix.set_value(result, i, j, curr_value); p_clearance_matrix.set_value(i, result, j, curr_value); } } if (p_item_class_name.equals("via")) { p_net_class.default_item_clearance_classes.set(ItemClass.VIA, result); } else if (p_item_class_name.equals("pin")) { p_net_class.default_item_clearance_classes.set(ItemClass.PIN, result); } else if (p_item_class_name.equals("smd")) { p_net_class.default_item_clearance_classes.set(ItemClass.SMD, result); } else if (p_item_class_name.equals("area")) { p_net_class.default_item_clearance_classes.set(ItemClass.AREA, result); } return result; } private static void insert_compoments(ReadScopeParameter p_par) { Iterator<ComponentPlacement> it = p_par.placement_list.iterator(); while (it.hasNext()) { ComponentPlacement next_lib_component = it.next(); Iterator<ComponentPlacement.ComponentLocation> it2 = next_lib_component.locations.iterator(); while (it2.hasNext()) { ComponentPlacement.ComponentLocation next_component = it2.next(); insert_component(next_component, next_lib_component.lib_name, p_par); } } } /** * Create the part library on the board. Can be called after the components are inserted. * Returns false, if an error occured. */ private static boolean insert_logical_parts(ReadScopeParameter p_par) { board.BasicBoard routing_board = p_par.board_handling.get_routing_board(); for (PartLibrary.LogicalPart next_part : p_par.logical_parts) { library.Package lib_package = search_lib_package(next_part.name, p_par.logical_part_mappings, routing_board); if (lib_package == null) { return false; } library.LogicalPart.PartPin[] board_part_pins = new library.LogicalPart.PartPin[next_part.part_pins.size()]; int curr_index = 0; for (PartLibrary.PartPin curr_part_pin : next_part.part_pins) { int pin_no = lib_package.get_pin_no(curr_part_pin.pin_name); if (pin_no < 0) { System.out.println("Network.insert_logical_parts: package pin not found"); return false; } board_part_pins[curr_index] = new library.LogicalPart.PartPin(pin_no, curr_part_pin.pin_name, curr_part_pin.gate_name, curr_part_pin.gate_swap_code, curr_part_pin.gate_pin_name, curr_part_pin.gate_pin_swap_code); ++curr_index; } routing_board.library.logical_parts.add(next_part.name, board_part_pins); } for (PartLibrary.LogicalPartMapping next_mapping : p_par.logical_part_mappings) { library.LogicalPart curr_logical_part = routing_board.library.logical_parts.get(next_mapping.name); { if (curr_logical_part == null) { System.out.println("Network.insert_logical_parts: logical part not found"); } } for (String curr_cmp_name : next_mapping.components) { board.Component curr_component = routing_board.components.get(curr_cmp_name); if (curr_component != null) { curr_component.set_logical_part(curr_logical_part); } else { System.out.println("Network.insert_logical_parts: board component not found"); } } } return true; } /** * Calculates the library package belonging to the logical part with name p_part_name. * Returns null, if the package was not found. */ private static library.Package search_lib_package(String p_part_name, java.util.Collection<PartLibrary.LogicalPartMapping> p_logical_part_mappings, board.BasicBoard p_board) { for (PartLibrary.LogicalPartMapping curr_mapping : p_logical_part_mappings) { if (curr_mapping.name.equals(p_part_name)) { if (curr_mapping.components.isEmpty()) { System.out.println("Network.search_lib_package: component list empty"); return null; } String component_name = curr_mapping.components.first(); if (component_name == null) { System.out.println("Network.search_lib_package: component list empty"); return null; } board.Component curr_component = p_board.components.get(component_name); if (curr_component == null) { System.out.println("Network.search_lib_package: component not found"); return null; } return curr_component.get_package(); } } System.out.print("Network.search_lib_package: library package "); System.out.print(p_part_name); System.out.println(" not found"); return null; } /** * Inserts all board components belonging to the input library component. */ private static void insert_component(ComponentPlacement.ComponentLocation p_location, String p_lib_key, ReadScopeParameter p_par) { board.RoutingBoard routing_board = p_par.board_handling.get_routing_board(); library.Package curr_front_package = routing_board.library.packages.get(p_lib_key, true); library.Package curr_back_package = routing_board.library.packages.get(p_lib_key, false); if (curr_front_package == null || curr_back_package == null) { System.out.println("Network.insert_component: component package not found"); return; } IntPoint component_location; if (p_location.coor != null) { component_location = p_par.coordinate_transform.dsn_to_board(p_location.coor).round(); } else { component_location = null; } double rotation_in_degree = p_location.rotation; board.Component new_component = routing_board.components.add(p_location.name, component_location, rotation_in_degree, p_location.is_front, curr_front_package, curr_back_package, p_location.position_fixed); if (component_location == null) { return; // component is not yet placed. } Vector component_translation = component_location.difference_by(Point.ZERO); board.FixedState fixed_state; if (p_location.position_fixed) { fixed_state = board.FixedState.SYSTEM_FIXED; } else { fixed_state = board.FixedState.UNFIXED; } library.Package curr_package = new_component.get_package(); for (int i = 0; i < curr_package.pin_count(); ++i) { library.Package.Pin curr_pin = curr_package.get_pin(i); library.Padstack curr_padstack = routing_board.library.padstacks.get(curr_pin.padstack_no); if (curr_padstack == null) { System.out.println("Network.insert_component: pin padstack not found"); return; } Collection<Net> pin_nets = p_par.netlist.get_nets(p_location.name, curr_pin.name); Collection<Integer> net_numbers = new LinkedList<Integer>(); for (Net curr_pin_net : pin_nets) { rules.Net curr_board_net = routing_board.rules.nets.get(curr_pin_net.id.name, curr_pin_net.id.subnet_number); if (curr_board_net == null) { System.out.println("Network.insert_component: board net not found"); } else { net_numbers.add(curr_board_net.net_number); } } int[] net_no_arr = new int[net_numbers.size()]; int net_index = 0; for (Integer curr_net_no : net_numbers) { net_no_arr[net_index] = curr_net_no; ++net_index; } rules.NetClass net_class; rules.Net board_net; if (net_no_arr.length > 0) { board_net = routing_board.rules.nets.get(net_no_arr[0]); } else { board_net = null; } if (board_net != null) { net_class = board_net.get_class(); } else { net_class = routing_board.rules.get_default_net_class(); } int clearance_class = -1; ComponentPlacement.ItemClearanceInfo pin_info = p_location.pin_infos.get(curr_pin.name); if (pin_info != null) { clearance_class = routing_board.rules.clearance_matrix.get_no(pin_info.clearance_class); } if (clearance_class < 0) { if (curr_padstack.from_layer() == curr_padstack.to_layer()) { clearance_class = net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.SMD); } else { clearance_class = net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.PIN); } } routing_board.insert_pin(new_component.no, i, net_no_arr, clearance_class, fixed_state); } // insert the keepouts belonging to the package (k = 1 for via keepouts) for (int k = 0; k <= 2; ++k) { library.Package.Keepout[] keepout_arr; java.util.Map<String, ComponentPlacement.ItemClearanceInfo> curr_keepout_infos; if (k == 0) { keepout_arr = curr_package.keepout_arr; curr_keepout_infos = p_location.keepout_infos; } else if (k == 1) { keepout_arr = curr_package.via_keepout_arr; curr_keepout_infos = p_location.via_keepout_infos; } else { keepout_arr = curr_package.place_keepout_arr; curr_keepout_infos = p_location.place_keepout_infos; } for (int i = 0; i < keepout_arr.length; ++i) { library.Package.Keepout curr_keepout = keepout_arr[i]; int layer = curr_keepout.layer; if (layer >= routing_board.get_layer_count()) { System.out.println("Network.insert_component: keepout layer is to big"); continue; } if (layer >= 0 && !p_location.is_front) { layer = routing_board.get_layer_count() - curr_keepout.layer - 1; } int clearance_class = routing_board.rules.get_default_net_class().default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.AREA); ComponentPlacement.ItemClearanceInfo keepout_info = curr_keepout_infos.get(curr_keepout.name); if (keepout_info != null) { int curr_clearance_class = routing_board.rules.clearance_matrix.get_no(keepout_info.clearance_class); if (curr_clearance_class > 0) { clearance_class = curr_clearance_class; } } if (layer >= 0) { if (k == 0) { routing_board.insert_obstacle(curr_keepout.area, layer, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } else if (k == 1) { routing_board.insert_via_obstacle(curr_keepout.area, layer, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } else { routing_board.insert_component_obstacle(curr_keepout.area, layer, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } } else { // insert the obstacle on all signal layers for (int j = 0; j < routing_board.layer_structure.arr.length; ++j) { if (routing_board.layer_structure.arr[j].is_signal) { if (k == 0) { routing_board.insert_obstacle(curr_keepout.area, j, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } else if (k == 1) { routing_board.insert_via_obstacle(curr_keepout.area, j, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } else { routing_board.insert_component_obstacle(curr_keepout.area, j, component_translation, rotation_in_degree, !p_location.is_front, clearance_class, new_component.no, curr_keepout.name, fixed_state); } } } } } } // insert the outline as component keepout for (int i = 0; i < curr_package.outline.length; ++i) { routing_board.insert_component_outline(curr_package.outline[i], p_location.is_front, component_translation, rotation_in_degree, new_component.no, fixed_state); } } }