/* * 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. * * SessionFile.java * * Created on 29. Oktober 2004, 08:01 */ package designformats.specctra; import java.util.Collection; import java.util.Iterator; import geometry.planar.FloatPoint; import geometry.planar.Point; import board.BasicBoard; import board.PolylineTrace; import board.Via; import board.ConductionArea; import datastructures.IndentFileWriter; import datastructures.IdentifierType; /** * Methods to handle a Specctra session file. * * @author alfons */ public class SessionFile { /** * Creates a Specctra session file to update the host system from the RoutingBooard */ public static boolean write( BasicBoard p_board, java.io.OutputStream p_output_stream, String p_design_name) { if (p_output_stream == null) { return false; } IndentFileWriter output_file = null; try { output_file = new IndentFileWriter(p_output_stream); } catch (Exception e) { System.out.println("unable to create session file"); return false; } String session_name = p_design_name.replace(".dsn", ".ses"); try { String [] reserved_chars = {"(", ")", " ", "-"}; IdentifierType identifier_type = new IdentifierType(reserved_chars, p_board.communication.specctra_parser_info.string_quote); write_session_scope(p_board, identifier_type, output_file, session_name, p_design_name); } catch (java.io.IOException e) { System.out.println("unable to write session file"); return false; } try { output_file.close(); } catch (java.io.IOException e) { System.out.println("unable to close session file"); return false; } return true; } private static void write_session_scope(BasicBoard p_board, IdentifierType p_identifier_type, IndentFileWriter p_file, String p_session_name, String p_design_name) throws java.io.IOException { double scale_factor = p_board.communication.coordinate_transform.dsn_to_board(1)/p_board.communication.resolution; CoordinateTransform coordinate_transform = new CoordinateTransform(scale_factor, 0, 0); p_file.start_scope(); p_file.write("session "); p_identifier_type.write(p_session_name, p_file); p_file.new_line(); p_file.write("(base_design "); p_identifier_type.write(p_design_name, p_file); p_file.write(")"); write_placement(p_board, p_identifier_type, coordinate_transform, p_file); write_was_is(p_board, p_identifier_type, p_file); write_routes(p_board, p_identifier_type, coordinate_transform, p_file); p_file.end_scope(); } public static void write_placement(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("placement"); Resolution.write_scope(p_file, p_board.communication); for (int i = 1; i <= p_board.library.packages.count(); ++i) { write_components(p_board, p_identifier_type, p_coordinate_transform, p_file, p_board.library.packages.get(i)); } p_file.end_scope(); } /** * Writes all components with the package p_package to the session file. */ public static void write_components(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file, library.Package p_package) throws java.io.IOException { Collection<board.Item> board_items = p_board.get_items(); boolean component_found = false; for (int i = 1; i <= p_board.components.count(); ++i) { board.Component curr_component = p_board.components.get(i); if (curr_component.get_package() == p_package) { // check, if not all items of the component are deleted boolean undeleted_item_found = false; Iterator<board.Item> it = board_items.iterator(); while (it.hasNext()) { board.Item curr_item = it.next(); if (curr_item.get_component_no() == curr_component.no) { undeleted_item_found = true; break; } } if (undeleted_item_found) { if (!component_found) { // write the scope header p_file.start_scope(); p_file.write("component "); p_identifier_type.write(p_package.name, p_file); component_found = true; } write_component(p_board, p_identifier_type, p_coordinate_transform, p_file, curr_component); } } } if (component_found) { p_file.end_scope(); } } public static void write_component(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file, board.Component p_component) throws java.io.IOException { p_file.new_line(); p_file.write("(place "); p_identifier_type.write(p_component.name, p_file); double[] location = p_coordinate_transform.board_to_dsn(p_component.get_location().to_float()); Integer x_coor = (int) Math.round(location[0]); Integer y_coor = (int) Math.round(location[1]); p_file.write(" "); p_file.write(x_coor.toString()); p_file.write(" "); p_file.write(y_coor.toString()); if (p_component.placed_on_front()) { p_file.write(" front "); } else { p_file.write(" back "); } int rotation = (int) Math.round(p_component.get_rotation_in_degree()); p_file.write((new Integer(rotation).toString())); if (p_component.position_fixed) { p_file.new_line(); p_file.write(" (lock_type position)"); } p_file.write(")"); } public static void write_was_is(BasicBoard p_board, IdentifierType p_identifier_type, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("was_is"); Collection<board.Pin> board_pins = p_board.get_pins(); for (board.Pin curr_pin : board_pins) { board.Pin swapped_with = curr_pin.get_changed_to(); if (curr_pin.get_changed_to() != curr_pin) { p_file.new_line(); p_file.write("(pins "); board.Component curr_cmp = p_board.components.get(curr_pin.get_component_no()); if (curr_cmp != null) { p_identifier_type.write(curr_cmp.name, p_file); p_file.write("-"); library.Package.Pin package_pin = curr_cmp.get_package().get_pin(curr_pin.get_index_in_package()); p_identifier_type.write(package_pin.name, p_file); } else { System.out.println("SessionFile.write_was_is: component not found"); } p_file.write(" "); board.Component swap_cmp = p_board.components.get(swapped_with.get_component_no()); if (swap_cmp != null) { p_identifier_type.write(swap_cmp.name, p_file); p_file.write("-"); library.Package.Pin package_pin = swap_cmp.get_package().get_pin(swapped_with.get_index_in_package()); p_identifier_type.write(package_pin.name, p_file); } else { System.out.println("SessionFile.write_was_is: component not found"); } p_file.write(")"); } } p_file.end_scope(); } private static void write_routes(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("routes "); Resolution.write_scope(p_file, p_board.communication); Parser.write_scope(p_file,p_board.communication.specctra_parser_info, p_identifier_type, true); write_library(p_board, p_identifier_type, p_coordinate_transform, p_file); write_network(p_board, p_identifier_type, p_coordinate_transform, p_file); p_file.end_scope(); } private static void write_library(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("library_out "); for (int i = 0; i < p_board.library.via_padstack_count(); ++i) { write_padstack(p_board.library.get_via_padstack(i), p_board, p_identifier_type, p_coordinate_transform, p_file); } p_file.end_scope(); } private static void write_padstack(library.Padstack p_padstack, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { // search the layer range of the padstack int first_layer_no = 0; while (first_layer_no < p_board.get_layer_count()) { if (p_padstack.get_shape(first_layer_no) != null) { break; } ++first_layer_no; } int last_layer_no = p_board.get_layer_count() - 1; while (last_layer_no >= 0 ) { if (p_padstack.get_shape(last_layer_no) != null) { break; } --last_layer_no; } if (first_layer_no >= p_board.get_layer_count() || last_layer_no < 0) { System.out.println("SessionFile.write_padstack: padstack shape not found"); return; } p_file.start_scope(); p_file.write("padstack "); p_identifier_type.write(p_padstack.name, p_file); for (int i = first_layer_no; i <= last_layer_no; ++i) { geometry.planar.Shape curr_board_shape = p_padstack.get_shape(i); if (curr_board_shape == null) { continue; } board.Layer board_layer = p_board.layer_structure.arr[i]; Layer curr_layer = new Layer(board_layer.name, i, board_layer.is_signal); Shape curr_shape = p_coordinate_transform.board_to_dsn_rel(curr_board_shape, curr_layer); p_file.start_scope(); p_file.write("shape"); curr_shape.write_scope_int(p_file, p_identifier_type); p_file.end_scope(); } if (!p_padstack.attach_allowed) { p_file.new_line(); p_file.write("(attach off)"); } p_file.end_scope(); } private static void write_network(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("network_out "); for (int i = 1; i <= p_board.rules.nets.max_net_no(); ++i) { write_net(i, p_board, p_identifier_type, p_coordinate_transform, p_file); } p_file.end_scope(); } private static void write_net(int p_net_no, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { Collection<board.Item> net_items = p_board.get_connectable_items(p_net_no); boolean header_written = false; Iterator<board.Item> it = net_items.iterator(); while (it.hasNext()) { board.Item curr_item = it.next(); if (curr_item.get_fixed_state() == board.FixedState.SYSTEM_FIXED) { continue; } boolean is_wire = curr_item instanceof PolylineTrace; boolean is_via = curr_item instanceof Via; boolean is_conduction_area = curr_item instanceof ConductionArea && p_board.layer_structure.arr [curr_item.first_layer()].is_signal; if (!header_written && (is_wire || is_via || is_conduction_area)) { p_file.start_scope(); p_file.write("net "); rules.Net curr_net = p_board.rules.nets.get(p_net_no); if (curr_net == null) { System.out.println("SessionFile.write_net: net not found"); } else { p_identifier_type.write(curr_net.name, p_file); } header_written = true; } if (is_wire) { write_wire((PolylineTrace)curr_item, p_board, p_identifier_type, p_coordinate_transform, p_file); } else if (is_via) { write_via((Via) curr_item, p_board, p_identifier_type, p_coordinate_transform, p_file); } else if (is_conduction_area) { write_conduction_area( (ConductionArea) curr_item, p_board, p_identifier_type, p_coordinate_transform, p_file); } } if (header_written) { p_file.end_scope(); } } private static void write_wire(PolylineTrace p_wire, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { int layer_no = p_wire.get_layer(); board.Layer board_layer = p_board.layer_structure.arr[layer_no]; int wire_width = (int) Math.round(p_coordinate_transform.board_to_dsn(2 * p_wire.get_half_width())); p_file.start_scope(); p_file.write("wire"); Point[] corner_arr = p_wire.polyline().corner_arr(); int [] coors = new int [2 * corner_arr.length]; int corner_index = 0; int [] prev_coors = null; for (int i = 0; i < corner_arr.length; ++i) { double[] curr_float_coors = p_coordinate_transform.board_to_dsn(corner_arr[i].to_float()); int [] curr_coors = new int[2]; curr_coors[0] = (int) Math.round(curr_float_coors[0]); curr_coors[1] = (int) Math.round(curr_float_coors[1]); if (i == 0 || ( curr_coors[0] != prev_coors[0] || curr_coors[1] != prev_coors[1])) { coors[corner_index] = curr_coors[0]; ++corner_index; coors[corner_index] = curr_coors[1]; ++corner_index; prev_coors = curr_coors; } } if (corner_index < coors.length) { int [] adjusted_coors = new int[corner_index]; for (int i = 0; i < adjusted_coors.length; ++i) { adjusted_coors[i] = coors[i]; } coors = adjusted_coors; } write_path(board_layer.name, wire_width, coors, p_identifier_type, p_file); write_fixed_state(p_file, p_wire.get_fixed_state()); p_file.end_scope(); } private static void write_via(Via p_via, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { library.Padstack via_padstack = p_via.get_padstack(); FloatPoint via_location = p_via.get_center().to_float(); p_file.start_scope(); p_file.write("via "); p_identifier_type.write(via_padstack.name, p_file); p_file.write(" "); double[] location = p_coordinate_transform.board_to_dsn(via_location); Integer x_coor = (int) Math.round(location[0]); p_file.write(x_coor.toString()); p_file.write(" "); Integer y_coor = (int) Math.round(location[1]); p_file.write(y_coor.toString()); write_fixed_state(p_file, p_via.get_fixed_state()); p_file.end_scope(); } static private void write_fixed_state(IndentFileWriter p_file, board.FixedState p_fixed_state) throws java.io.IOException { if (p_fixed_state.ordinal() <= board.FixedState.SHOVE_FIXED.ordinal()) { return; } p_file.new_line(); p_file.write("(type "); if (p_fixed_state == board.FixedState.SYSTEM_FIXED) { p_file.write("fix)"); } else { p_file.write("protect)"); } } private static void write_path(String p_layer_name, int p_width, int[] p_coors, IdentifierType p_identifier_type, IndentFileWriter p_file) throws java.io.IOException { p_file.start_scope(); p_file.write("path "); p_identifier_type.write(p_layer_name, p_file); p_file.write(" "); p_file.write((new Integer(p_width)).toString()); int corner_count = p_coors.length/ 2; for (int i = 0; i < corner_count; ++i) { p_file.new_line(); p_file.write(new Integer(p_coors[2 * i]).toString()); p_file.write(" "); p_file.write(new Integer(p_coors[2 * i + 1]).toString()); } p_file.end_scope(); } private static void write_conduction_area( ConductionArea p_conduction_area, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException { int net_count = p_conduction_area.net_count(); if (net_count <= 0 || net_count > 1) { System.out.println("SessionFile.write_conduction_area: unexpected net count"); return; } geometry.planar.Area curr_area = p_conduction_area.get_area(); int layer_no = p_conduction_area.get_layer(); board.Layer board_layer = p_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_file.start_scope(); p_file.write("wire "); Shape dsn_shape = p_coordinate_transform.board_to_dsn(boundary_shape, conduction_layer); if (dsn_shape != null) { dsn_shape.write_scope_int(p_file, p_identifier_type); } for (int i = 0; i < holes.length; ++i) { Shape dsn_hole = p_coordinate_transform.board_to_dsn(holes[i], conduction_layer); dsn_hole.write_hole_scope(p_file, p_identifier_type); } p_file.end_scope(); } }