787 lines
29 KiB
Java
787 lines
29 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.
|
|
*
|
|
* Wiring.java
|
|
*
|
|
* Created on 24. Mai 2004, 07:20
|
|
*/
|
|
|
|
package designformats.specctra;
|
|
|
|
import java.util.Collection;
|
|
import java.util.LinkedList;
|
|
import java.util.Iterator;
|
|
|
|
import datastructures.UndoableObjects;
|
|
|
|
import geometry.planar.FloatPoint;
|
|
import geometry.planar.Point;
|
|
import geometry.planar.IntBox;
|
|
import geometry.planar.IntPoint;
|
|
import geometry.planar.Line;
|
|
import geometry.planar.Polyline;
|
|
|
|
import board.RoutingBoard;
|
|
import board.Item;
|
|
import board.Via;
|
|
import board.Trace;
|
|
import board.PolylineTrace;
|
|
import board.FixedState;
|
|
import board.ItemSelectionFilter;
|
|
|
|
import datastructures.IndentFileWriter;
|
|
import datastructures.IdentifierType;
|
|
|
|
/**
|
|
* Class for reading and writing wiring scopes from dsn-files.
|
|
*
|
|
* @author Alfons Wirtz
|
|
*/
|
|
class Wiring extends ScopeKeyword
|
|
{
|
|
|
|
/** Creates a new instance of Wiring */
|
|
public Wiring()
|
|
{
|
|
super("wiring");
|
|
}
|
|
|
|
public boolean read_scope(ReadScopeParameter p_par)
|
|
{
|
|
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("Wiring.read_scope: IO error scanning file");
|
|
return false;
|
|
}
|
|
if (next_token == null)
|
|
{
|
|
System.out.println("Wiring.read_scope: unexpected end of file");
|
|
return false;
|
|
}
|
|
if (next_token == CLOSED_BRACKET)
|
|
{
|
|
// end of scope
|
|
break;
|
|
}
|
|
boolean read_ok = true;
|
|
if (prev_token == OPEN_BRACKET)
|
|
{
|
|
if (next_token == Keyword.WIRE)
|
|
{
|
|
read_wire_scope(p_par);
|
|
}
|
|
else if (next_token == Keyword.VIA)
|
|
{
|
|
read_ok = read_via_scope(p_par);
|
|
}
|
|
else
|
|
{
|
|
skip_scope(p_par.scanner);
|
|
}
|
|
}
|
|
if (!read_ok)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
RoutingBoard board = p_par.board_handling.get_routing_board();
|
|
for (int i = 1; i <= board.rules.nets.max_net_no(); ++i)
|
|
{
|
|
board.normalize_traces(i);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static void write_scope(WriteScopeParameter p_par) throws java.io.IOException
|
|
{
|
|
p_par.file.start_scope();
|
|
p_par.file.write("wiring");
|
|
// write the wires
|
|
Collection<Trace> board_wires = p_par.board.get_traces();
|
|
Iterator<Trace> it = board_wires.iterator();
|
|
while (it.hasNext())
|
|
{
|
|
write_wire_scope(p_par, it.next());
|
|
}
|
|
Collection<Via> board_vias = p_par.board.get_vias();
|
|
for (Via curr_via : board_vias)
|
|
{
|
|
write_via_scope(p_par, curr_via);
|
|
}
|
|
// write the conduction areas
|
|
Iterator<UndoableObjects.UndoableObjectNode> it2 = p_par.board.item_list.start_read_object();
|
|
for(;;)
|
|
{
|
|
Object curr_ob = p_par.board.item_list.read_object(it2);
|
|
if (curr_ob == null)
|
|
{
|
|
break;
|
|
}
|
|
if (!(curr_ob instanceof board.ConductionArea))
|
|
{
|
|
continue;
|
|
}
|
|
board.ConductionArea curr_area = (board.ConductionArea) curr_ob;
|
|
if (!(p_par.board.layer_structure.arr [curr_area.get_layer()].is_signal))
|
|
{
|
|
// This conduction areas arw written in the structure scope.
|
|
continue;
|
|
}
|
|
write_conduction_area_scope(p_par, (board.ConductionArea) curr_ob);
|
|
}
|
|
p_par.file.end_scope();
|
|
}
|
|
|
|
private static void write_via_scope(WriteScopeParameter p_par, Via p_via) throws java.io.IOException
|
|
{
|
|
library.Padstack via_padstack = p_via.get_padstack();
|
|
FloatPoint via_location = p_via.get_center().to_float();
|
|
double [] via_coor = p_par.coordinate_transform.board_to_dsn(via_location);
|
|
int net_no;
|
|
rules.Net via_net;
|
|
if (p_via.net_count() > 0)
|
|
{
|
|
net_no = p_via.get_net_no(0);
|
|
via_net = p_par.board.rules.nets.get(net_no);
|
|
}
|
|
else
|
|
{
|
|
net_no = 0;
|
|
via_net = null;
|
|
}
|
|
p_par.file.start_scope();
|
|
p_par.file.write("via ");
|
|
p_par.identifier_type.write(via_padstack.name, p_par.file);
|
|
for (int i = 0; i < via_coor.length; ++i)
|
|
{
|
|
p_par.file.write(" ");
|
|
p_par.file.write((new Double(via_coor[i])).toString());
|
|
}
|
|
if (via_net != null)
|
|
{
|
|
write_net(via_net, p_par.file, p_par.identifier_type);
|
|
}
|
|
Rule.write_item_clearance_class(p_par.board.rules.clearance_matrix.get_name(p_via.clearance_class_no()),
|
|
p_par.file, p_par.identifier_type);
|
|
write_fixed_state(p_par.file, p_via.get_fixed_state());
|
|
p_par.file.end_scope();
|
|
}
|
|
|
|
private static void write_wire_scope(WriteScopeParameter p_par, Trace p_wire) throws java.io.IOException
|
|
{
|
|
if (!(p_wire instanceof PolylineTrace))
|
|
{
|
|
System.out.println("Wiring.write_wire_scope: trace type not yet implemented");
|
|
return;
|
|
}
|
|
PolylineTrace curr_wire = (PolylineTrace) p_wire;
|
|
int layer_no = curr_wire.get_layer();
|
|
board.Layer board_layer = p_par.board.layer_structure.arr[layer_no];
|
|
Layer curr_layer = new Layer(board_layer.name, layer_no, board_layer.is_signal);
|
|
double wire_width = p_par.coordinate_transform.board_to_dsn(2 * curr_wire.get_half_width());
|
|
rules.Net wire_net = null;
|
|
if (curr_wire.net_count() > 0)
|
|
{
|
|
wire_net = p_par.board.rules.nets.get(curr_wire.get_net_no(0));
|
|
}
|
|
if (wire_net == null)
|
|
{
|
|
System.out.println("Wiring.write_wire_scope: net not found");
|
|
return;
|
|
}
|
|
p_par.file.start_scope();
|
|
p_par.file.write("wire");
|
|
|
|
if(p_par.compat_mode)
|
|
{
|
|
Point[] corner_arr = curr_wire.polyline().corner_arr();
|
|
FloatPoint[] float_corner_arr = new FloatPoint [corner_arr.length];
|
|
for (int i = 0; i < corner_arr.length; ++i)
|
|
{
|
|
float_corner_arr[i] = corner_arr[i].to_float();
|
|
}
|
|
double [] coors = p_par.coordinate_transform.board_to_dsn(float_corner_arr);
|
|
PolygonPath curr_path = new PolygonPath(curr_layer, wire_width, coors);
|
|
curr_path.write_scope(p_par.file, p_par.identifier_type);
|
|
}
|
|
else
|
|
{
|
|
double [] coors = p_par.coordinate_transform.board_to_dsn(curr_wire.polyline().arr);
|
|
PolylinePath curr_path = new PolylinePath(curr_layer, wire_width, coors);
|
|
curr_path.write_scope(p_par.file, p_par.identifier_type);
|
|
}
|
|
write_net(wire_net, p_par.file, p_par.identifier_type);
|
|
Rule.write_item_clearance_class(p_par.board.rules.clearance_matrix.get_name(p_wire.clearance_class_no()),
|
|
p_par.file, p_par.identifier_type);
|
|
write_fixed_state(p_par.file, curr_wire.get_fixed_state());
|
|
p_par.file.end_scope();
|
|
}
|
|
|
|
private static void write_conduction_area_scope(WriteScopeParameter p_par, board.ConductionArea p_conduction_area) throws java.io.IOException
|
|
{
|
|
int net_count = p_conduction_area.net_count();
|
|
if (net_count <= 0 || net_count > 1)
|
|
{
|
|
System.out.println("Plane.write_scope: unexpected net count");
|
|
return;
|
|
}
|
|
rules.Net curr_net = p_par.board.rules.nets.get(p_conduction_area.get_net_no(0));
|
|
geometry.planar.Area curr_area = p_conduction_area.get_area();
|
|
int layer_no = p_conduction_area.get_layer();
|
|
board.Layer board_layer = p_par.board.layer_structure.arr[ layer_no];
|
|
Layer conduction_layer = new Layer(board_layer.name, layer_no, board_layer.is_signal);
|
|
geometry.planar.Shape boundary_shape;
|
|
geometry.planar.Shape [] holes;
|
|
if (curr_area instanceof geometry.planar.Shape)
|
|
{
|
|
boundary_shape = (geometry.planar.Shape) curr_area;
|
|
holes = new geometry.planar.Shape [0];
|
|
}
|
|
else
|
|
{
|
|
boundary_shape = curr_area.get_border();
|
|
holes = curr_area.get_holes();
|
|
}
|
|
p_par.file.start_scope();
|
|
p_par.file.write("wire ");
|
|
Shape dsn_shape = p_par.coordinate_transform.board_to_dsn(boundary_shape, conduction_layer);
|
|
if (dsn_shape != null)
|
|
{
|
|
dsn_shape.write_scope(p_par.file, p_par.identifier_type);
|
|
}
|
|
for (int i = 0; i < holes.length; ++i)
|
|
{
|
|
Shape dsn_hole = p_par.coordinate_transform.board_to_dsn(holes[i], conduction_layer);
|
|
dsn_hole.write_hole_scope(p_par.file, p_par.identifier_type);
|
|
}
|
|
write_net(curr_net, p_par.file, p_par.identifier_type);
|
|
Rule.write_item_clearance_class(p_par.board.rules.clearance_matrix.get_name(p_conduction_area.clearance_class_no()),
|
|
p_par.file, p_par.identifier_type);
|
|
p_par.file.end_scope();
|
|
}
|
|
|
|
static private void write_net(rules.Net p_net, IndentFileWriter p_file, IdentifierType p_identifier_type) throws java.io.IOException
|
|
{
|
|
p_file.new_line();
|
|
p_file.write("(");
|
|
Net.write_net_id(p_net, p_file, p_identifier_type);
|
|
p_file.write(")");
|
|
}
|
|
|
|
static private void write_fixed_state(IndentFileWriter p_file, FixedState p_fixed_state) throws java.io.IOException
|
|
{
|
|
if (p_fixed_state == FixedState.UNFIXED)
|
|
{
|
|
return;
|
|
}
|
|
p_file.new_line();
|
|
p_file.write("(type ");
|
|
if (p_fixed_state == FixedState.SHOVE_FIXED)
|
|
{
|
|
p_file.write("shove_fixed)");
|
|
}
|
|
else if (p_fixed_state == FixedState.SYSTEM_FIXED)
|
|
{
|
|
p_file.write("fix)");
|
|
}
|
|
else
|
|
{
|
|
p_file.write("protect)");
|
|
}
|
|
}
|
|
|
|
private Item read_wire_scope(ReadScopeParameter p_par)
|
|
{
|
|
Net.Id net_id = null;
|
|
String clearance_class_name = null;
|
|
board.FixedState fixed = board.FixedState.UNFIXED;
|
|
Path path = null; // Used, if a trace is read.
|
|
Shape border_shape = null; // Used, if a conduction area is read.
|
|
Collection<Shape> hole_list = new LinkedList<Shape>();
|
|
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("Wiring.read_wire_scope: IO error scanning file");
|
|
return null;
|
|
}
|
|
if (next_token == null)
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: unexpected end of file");
|
|
return null;
|
|
}
|
|
if (next_token == CLOSED_BRACKET)
|
|
{
|
|
// end of scope
|
|
break;
|
|
}
|
|
if (prev_token == OPEN_BRACKET)
|
|
{
|
|
if (next_token == Keyword.POLYGON_PATH)
|
|
{
|
|
path = Shape.read_polygon_path_scope(p_par.scanner, p_par.layer_structure);
|
|
}
|
|
else if (next_token == Keyword.POLYLINE_PATH)
|
|
{
|
|
path = Shape.read_polyline_path_scope(p_par.scanner, p_par.layer_structure);
|
|
}
|
|
else if (next_token == Keyword.RECTANGLE)
|
|
{
|
|
|
|
border_shape = Shape.read_rectangle_scope(p_par.scanner, p_par.layer_structure);
|
|
}
|
|
else if (next_token == Keyword.POLYGON)
|
|
{
|
|
|
|
border_shape = Shape.read_polygon_scope(p_par.scanner, p_par.layer_structure);
|
|
}
|
|
else if (next_token == Keyword.CIRCLE)
|
|
{
|
|
|
|
border_shape = Shape.read_circle_scope(p_par.scanner, p_par.layer_structure);
|
|
}
|
|
else if (next_token == Keyword.WINDOW)
|
|
{
|
|
Shape hole_shape = Shape.read_scope(p_par.scanner, p_par.layer_structure);
|
|
hole_list.add(hole_shape);
|
|
// overread the closing bracket
|
|
try
|
|
{
|
|
next_token = p_par.scanner.next_token();
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: IO error scanning file");
|
|
return null;
|
|
}
|
|
if (next_token != Keyword.CLOSED_BRACKET)
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: closing bracket expected");
|
|
return null;
|
|
}
|
|
}
|
|
else if (next_token == Keyword.NET)
|
|
{
|
|
net_id = read_net_id(p_par.scanner);
|
|
}
|
|
else if (next_token == Keyword.CLEARANCE_CLASS)
|
|
{
|
|
clearance_class_name = DsnFile.read_string_scope(p_par.scanner);
|
|
}
|
|
else if (next_token == Keyword.TYPE)
|
|
{
|
|
fixed = calc_fixed(p_par.scanner);
|
|
}
|
|
else
|
|
{
|
|
skip_scope(p_par.scanner);
|
|
}
|
|
}
|
|
}
|
|
if (path == null && border_shape == null)
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: shape missing");
|
|
return null;
|
|
}
|
|
RoutingBoard board = p_par.board_handling.get_routing_board();
|
|
|
|
rules.NetClass net_class = board.rules.get_default_net_class();
|
|
Collection<rules.Net> found_nets = get_subnets(net_id, board.rules);
|
|
int[] net_no_arr = new int[found_nets.size()];
|
|
int curr_index = 0;
|
|
for (rules.Net curr_net : found_nets)
|
|
{
|
|
net_no_arr[curr_index] = curr_net.net_number;
|
|
net_class = curr_net.get_class();
|
|
++curr_index;
|
|
}
|
|
int clearance_class_no = -1;
|
|
if (clearance_class_name != null)
|
|
{
|
|
clearance_class_no = board.rules.clearance_matrix.get_no(clearance_class_name);
|
|
}
|
|
int layer_no;
|
|
int half_width;
|
|
if (path != null)
|
|
{
|
|
layer_no = path.layer.no;
|
|
half_width = (int) Math.round(p_par.coordinate_transform.dsn_to_board(path.width / 2));
|
|
}
|
|
else
|
|
{
|
|
layer_no = border_shape.layer.no;
|
|
half_width = 0;
|
|
}
|
|
if (layer_no < 0 || layer_no >= board.get_layer_count())
|
|
{
|
|
System.out.print("Wiring.read_wire_scope: unexpected layer ");
|
|
if (path != null)
|
|
{
|
|
System.out.println(path.layer.name);
|
|
}
|
|
else
|
|
{
|
|
System.out.println(border_shape.layer.name);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
IntBox bounding_box = board.get_bounding_box();
|
|
|
|
Item result = null;
|
|
if (border_shape != null)
|
|
{
|
|
if (clearance_class_no < 0)
|
|
{
|
|
clearance_class_no =
|
|
net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.AREA);
|
|
}
|
|
Collection<Shape> area = new LinkedList<Shape>();
|
|
area.add(border_shape);
|
|
area.addAll(hole_list);
|
|
geometry.planar.Area conduction_area =
|
|
Shape.transform_area_to_board(area, p_par.coordinate_transform);
|
|
result = board.insert_conduction_area(conduction_area, layer_no, net_no_arr, clearance_class_no,
|
|
false, fixed);
|
|
}
|
|
else if (path instanceof PolygonPath)
|
|
{
|
|
if (clearance_class_no < 0)
|
|
{
|
|
clearance_class_no =
|
|
net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.TRACE);
|
|
}
|
|
IntPoint [] corner_arr = new IntPoint[path.coordinate_arr.length / 2];
|
|
double [] curr_point = new double [2];
|
|
for (int i = 0; i < corner_arr.length; ++i)
|
|
{
|
|
curr_point[0] = path.coordinate_arr[2 * i];
|
|
curr_point[1] = path.coordinate_arr[2 * i + 1];
|
|
FloatPoint curr_corner = p_par.coordinate_transform.dsn_to_board(curr_point);
|
|
if (!bounding_box.contains(curr_corner))
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: wire corner outside board");
|
|
return null;
|
|
}
|
|
corner_arr[i] = curr_corner.round();
|
|
}
|
|
Polyline trace_polyline = new Polyline(corner_arr);
|
|
// Traces are not yet normalized here because cycles may be removed premature.
|
|
result = board.insert_trace_without_cleaning(trace_polyline, layer_no, half_width, net_no_arr, clearance_class_no, fixed);
|
|
}
|
|
else if (path instanceof PolylinePath)
|
|
{
|
|
if (clearance_class_no < 0)
|
|
{
|
|
clearance_class_no =
|
|
net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.TRACE);
|
|
}
|
|
Line [] line_arr = new Line[path.coordinate_arr.length / 4];
|
|
double [] curr_point = new double [2];
|
|
for (int i = 0; i < line_arr.length; ++i)
|
|
{
|
|
curr_point[0] = path.coordinate_arr[4 * i];
|
|
curr_point[1] = path.coordinate_arr[4 * i + 1];
|
|
FloatPoint curr_a = p_par.coordinate_transform.dsn_to_board(curr_point);
|
|
curr_point[0] = path.coordinate_arr[4 * i + 2];
|
|
curr_point[1] = path.coordinate_arr[4 * i + 3];
|
|
FloatPoint curr_b = p_par.coordinate_transform.dsn_to_board(curr_point);
|
|
line_arr[i] = new Line(curr_a.round(), curr_b.round());
|
|
}
|
|
Polyline trace_polyline = new Polyline(line_arr);
|
|
result = board.insert_trace_without_cleaning(trace_polyline, layer_no, half_width, net_no_arr, clearance_class_no, fixed);
|
|
}
|
|
else
|
|
{
|
|
System.out.println("Wiring.read_wire_scope: unexpected Path subclass");
|
|
return null;
|
|
}
|
|
if (result != null && result.net_count() == 0)
|
|
{
|
|
try_correct_net(result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Maybe trace of type turret without net in Mentor design.
|
|
* Try to assig the net by calculating the overlaps.
|
|
*/
|
|
private void try_correct_net(Item p_item)
|
|
{
|
|
if (!(p_item instanceof Trace))
|
|
{
|
|
return;
|
|
}
|
|
Trace curr_trace = (Trace) p_item;
|
|
java.util.Set<Item> contacts = curr_trace.get_normal_contacts(curr_trace.first_corner(), true);
|
|
contacts.addAll(curr_trace.get_normal_contacts(curr_trace.last_corner(), true));
|
|
int corrected_net_no = 0;
|
|
for (Item curr_contact : contacts)
|
|
{
|
|
if (curr_contact.net_count() == 1)
|
|
{
|
|
corrected_net_no = curr_contact.get_net_no(0);
|
|
break;
|
|
}
|
|
}
|
|
if (corrected_net_no != 0)
|
|
{
|
|
p_item.assign_net_no(corrected_net_no);
|
|
}
|
|
}
|
|
|
|
private static Collection<rules.Net> get_subnets(Net.Id p_net_id, rules.BoardRules p_rules)
|
|
{
|
|
Collection<rules.Net> found_nets = new LinkedList<rules.Net>();
|
|
if (p_net_id != null)
|
|
{
|
|
if (p_net_id.subnet_number > 0)
|
|
{
|
|
rules.Net found_net = p_rules.nets.get(p_net_id.name, p_net_id.subnet_number);
|
|
if (found_net != null)
|
|
{
|
|
found_nets.add(found_net);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
found_nets = p_rules.nets.get(p_net_id.name);
|
|
}
|
|
}
|
|
return found_nets;
|
|
}
|
|
|
|
private boolean read_via_scope(ReadScopeParameter p_par)
|
|
{
|
|
try
|
|
{
|
|
board.FixedState fixed = board.FixedState.UNFIXED;
|
|
// read the padstack name
|
|
Object next_token = p_par.scanner.next_token();
|
|
if (!(next_token instanceof String))
|
|
{
|
|
System.out.println("Wiring.read_via_scope: padstack name expected");
|
|
return false;
|
|
}
|
|
String padstack_name = (String) next_token;
|
|
// read the location
|
|
double []location = new double [2];
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
next_token = p_par.scanner.next_token();
|
|
if (next_token instanceof Double)
|
|
{
|
|
location[i] = ((Double) next_token).doubleValue();
|
|
}
|
|
else if (next_token instanceof Integer)
|
|
{
|
|
location[i] = ((Integer) next_token).intValue();
|
|
}
|
|
else
|
|
{
|
|
System.out.println("Wiring.read_via_scope: number expected");
|
|
return false;
|
|
}
|
|
}
|
|
Net.Id net_id = null;
|
|
String clearance_class_name = null;
|
|
for (;;)
|
|
{
|
|
Object prev_token = next_token;
|
|
next_token = p_par.scanner.next_token();
|
|
if (next_token == null)
|
|
{
|
|
System.out.println("Wiring.read_via_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)
|
|
{
|
|
net_id = read_net_id(p_par.scanner);
|
|
}
|
|
else if (next_token == Keyword.CLEARANCE_CLASS)
|
|
{
|
|
clearance_class_name = DsnFile.read_string_scope(p_par.scanner);
|
|
}
|
|
else if (next_token == Keyword.TYPE)
|
|
{
|
|
fixed = calc_fixed(p_par.scanner);
|
|
}
|
|
else
|
|
{
|
|
skip_scope(p_par.scanner);
|
|
}
|
|
}
|
|
}
|
|
RoutingBoard board = p_par.board_handling.get_routing_board();
|
|
library.Padstack curr_padstack = board.library.padstacks.get(padstack_name);
|
|
if (curr_padstack == null)
|
|
{
|
|
System.out.println("Wiring.read_via_scope: via padstack not found");
|
|
return false;
|
|
}
|
|
rules.NetClass net_class = board.rules.get_default_net_class();
|
|
Collection<rules.Net> found_nets = get_subnets(net_id, board.rules);
|
|
if (net_id != null && found_nets.isEmpty())
|
|
{
|
|
System.out.print("Wiring.read_via_scope: net with name ");
|
|
System.out.print(net_id.name);
|
|
System.out.println(" not found");
|
|
}
|
|
int[] net_no_arr = new int[found_nets.size()];
|
|
int curr_index = 0;
|
|
for (rules.Net curr_net : found_nets)
|
|
{
|
|
net_no_arr[curr_index] = curr_net.net_number;
|
|
net_class = curr_net.get_class();
|
|
}
|
|
int clearance_class_no = -1;
|
|
if (clearance_class_name != null)
|
|
{
|
|
clearance_class_no = board.rules.clearance_matrix.get_no(clearance_class_name);
|
|
}
|
|
if (clearance_class_no < 0)
|
|
{
|
|
clearance_class_no = net_class.default_item_clearance_classes.get(rules.DefaultItemClearanceClasses.ItemClass.VIA);
|
|
}
|
|
IntPoint board_location = p_par.coordinate_transform.dsn_to_board(location).round();
|
|
if (via_exists(board_location, curr_padstack, net_no_arr, board))
|
|
{
|
|
System.out.print("Multiple via skipped at (");
|
|
System.out.println(board_location.x + ", " + board_location.y + ")");
|
|
}
|
|
else
|
|
{
|
|
boolean attach_allowed = p_par.via_at_smd_allowed && curr_padstack.attach_allowed;
|
|
board.insert_via(curr_padstack, board_location, net_no_arr, clearance_class_no, fixed, attach_allowed);
|
|
}
|
|
return true;
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("Wiring.read_via_scope: IO error scanning file");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static boolean via_exists(IntPoint p_location, library.Padstack p_padstack,
|
|
int[] p_net_no_arr, board.BasicBoard p_board)
|
|
{
|
|
ItemSelectionFilter filter = new ItemSelectionFilter(ItemSelectionFilter.SelectableChoices.VIAS);
|
|
int from_layer = p_padstack.from_layer();
|
|
int to_layer = p_padstack.to_layer();
|
|
Collection<Item> picked_items = p_board.pick_items(p_location, p_padstack.from_layer(), filter);
|
|
for (Item curr_item : picked_items)
|
|
{
|
|
Via curr_via = (Via) curr_item;
|
|
if (curr_via.nets_equal(p_net_no_arr) && curr_via.get_center().equals(p_location)
|
|
&& curr_via.first_layer() == from_layer && curr_via.last_layer() == to_layer)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static board.FixedState calc_fixed(Scanner p_scanner)
|
|
{
|
|
try
|
|
{
|
|
board.FixedState result = board.FixedState.UNFIXED;
|
|
Object next_token = p_scanner.next_token();
|
|
if (next_token == Keyword.SHOVE_FIXED)
|
|
{
|
|
result = board.FixedState.SHOVE_FIXED;
|
|
}
|
|
else if (next_token == Keyword.FIX)
|
|
{
|
|
result = board.FixedState.SYSTEM_FIXED;
|
|
}
|
|
else if (next_token != Keyword.NORMAL)
|
|
{
|
|
result = board.FixedState.USER_FIXED;
|
|
}
|
|
next_token = p_scanner.next_token();
|
|
if (next_token != Keyword.CLOSED_BRACKET)
|
|
{
|
|
System.out.println("Wiring.is_fixed: ) expected");
|
|
return board.FixedState.UNFIXED;
|
|
}
|
|
return result;
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("Wiring.is_fixed: IO error scanning file");
|
|
return board.FixedState.UNFIXED;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads a net_id. The subnet_number of the net_id will be 0, if no subneet_number was found.
|
|
*/
|
|
private static Net.Id read_net_id(Scanner p_scanner)
|
|
{
|
|
try
|
|
{
|
|
int subnet_number = 0;
|
|
p_scanner.yybegin(SpecctraFileScanner.NAME);
|
|
Object next_token = p_scanner.next_token();
|
|
if (!(next_token instanceof String))
|
|
{
|
|
System.out.println("Wiring:read_net_id: String expected");
|
|
return null;
|
|
}
|
|
String net_name = (String) next_token;
|
|
next_token = p_scanner.next_token();
|
|
if (next_token instanceof Integer)
|
|
{
|
|
subnet_number = (Integer) next_token;
|
|
next_token = p_scanner.next_token();
|
|
}
|
|
if (next_token != Keyword.CLOSED_BRACKET)
|
|
{
|
|
System.out.println("Wiring.read_net_id: closing bracket expected");
|
|
}
|
|
return new Net.Id(net_name, subnet_number);
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("DsnFile.read_string_scope: IO error scanning file");
|
|
return null;
|
|
}
|
|
}
|
|
}
|