freerouting/src/main/java/eu/mihosoft/freerouting/designformats/specctra/Network.java

1537 lines
61 KiB
Java

/*
* 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);
}
}
}