322 lines
12 KiB
Java
322 lines
12 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.
|
|
*
|
|
* RulesFile.java
|
|
*
|
|
* Created on 18. Juli 2005, 07:07
|
|
*
|
|
*/
|
|
|
|
package designformats.specctra;
|
|
|
|
import datastructures.IndentFileWriter;
|
|
|
|
import board.BasicBoard;
|
|
|
|
/**
|
|
* File for saving the board rules, so that they can be restored after the Board
|
|
* is creates anew from the host system.
|
|
*
|
|
* @author Alfons Wirtz
|
|
*/
|
|
public class RulesFile
|
|
{
|
|
|
|
public static void write(interactive.BoardHandling p_board_handling, java.io.OutputStream p_output_stream, String p_design_name)
|
|
{
|
|
IndentFileWriter output_file = new IndentFileWriter(p_output_stream);
|
|
BasicBoard routing_board = p_board_handling.get_routing_board();
|
|
WriteScopeParameter write_scope_parameter =
|
|
new WriteScopeParameter(routing_board, p_board_handling.settings.autoroute_settings,
|
|
output_file, routing_board.communication.specctra_parser_info.string_quote,
|
|
routing_board.communication.coordinate_transform, false);
|
|
try
|
|
{
|
|
write_rules(write_scope_parameter, p_design_name);
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("unable to write rules to file");
|
|
}
|
|
try
|
|
{
|
|
output_file.close();
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("unable to close rules file");
|
|
}
|
|
}
|
|
|
|
public static boolean read(java.io.InputStream p_input_stream, String p_design_name,
|
|
interactive.BoardHandling p_board_handling)
|
|
{
|
|
BasicBoard routing_board = p_board_handling.get_routing_board();
|
|
Scanner scanner = new SpecctraFileScanner(p_input_stream);
|
|
try
|
|
{
|
|
Object curr_token = scanner.next_token();
|
|
if (curr_token != Keyword.OPEN_BRACKET)
|
|
{
|
|
System.out.println("RulesFile.read: open bracket expected");
|
|
return false;
|
|
}
|
|
curr_token = scanner.next_token();
|
|
if (curr_token != Keyword.RULES)
|
|
{
|
|
System.out.println("RulesFile.read: keyword rules expected");
|
|
return false;
|
|
}
|
|
curr_token = scanner.next_token();
|
|
if (curr_token != Keyword.PCB_SCOPE)
|
|
{
|
|
System.out.println("RulesFile.read: keyword pcb expected");
|
|
return false;
|
|
}
|
|
scanner.yybegin(SpecctraFileScanner.NAME);
|
|
curr_token = scanner.next_token();
|
|
if (!(curr_token instanceof String) || !((String) curr_token).equals(p_design_name))
|
|
{
|
|
System.out.println("RulesFile.read: design_name not matching");
|
|
return false;
|
|
}
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("RulesFile.read: IO error scanning file");
|
|
return false;
|
|
}
|
|
LayerStructure layer_structure = new LayerStructure(routing_board.layer_structure);
|
|
CoordinateTransform coordinate_transform = routing_board.communication.coordinate_transform;
|
|
Object next_token = null;
|
|
for (;;)
|
|
{
|
|
Object prev_token = next_token;
|
|
try
|
|
{
|
|
next_token = scanner.next_token();
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("RulesFile.read: IO error scanning file");
|
|
return false;
|
|
}
|
|
if (next_token == null)
|
|
{
|
|
System.out.println("Structure.read_scope: unexpected end of file");
|
|
return false;
|
|
}
|
|
if (next_token == Keyword.CLOSED_BRACKET)
|
|
{
|
|
// end of scope
|
|
break;
|
|
}
|
|
boolean read_ok = true;
|
|
if (prev_token == Keyword.OPEN_BRACKET)
|
|
{
|
|
if (next_token == Keyword.RULE)
|
|
{
|
|
add_rules(Rule.read_scope(scanner), routing_board, null);
|
|
}
|
|
else if (next_token == Keyword.LAYER)
|
|
{
|
|
add_layer_rules(scanner, routing_board);
|
|
}
|
|
else if (next_token == Keyword.PADSTACK)
|
|
{
|
|
Library.read_padstack_scope(scanner, layer_structure, coordinate_transform, routing_board.library.padstacks);
|
|
}
|
|
else if (next_token == Keyword.VIA)
|
|
{
|
|
read_via_info(scanner, routing_board);
|
|
}
|
|
else if (next_token == Keyword.VIA_RULE)
|
|
{
|
|
read_via_rule(scanner, routing_board);
|
|
}
|
|
else if (next_token == Keyword.CLASS)
|
|
{
|
|
read_net_class(scanner, layer_structure, routing_board);
|
|
}
|
|
else if (next_token == Keyword.SNAP_ANGLE)
|
|
{
|
|
|
|
board.AngleRestriction snap_angle = Structure.read_snap_angle(scanner);
|
|
if (snap_angle != null)
|
|
{
|
|
routing_board.rules.set_trace_angle_restriction(snap_angle);
|
|
}
|
|
}
|
|
else if (next_token == Keyword.AUTOROUTE_SETTINGS)
|
|
{
|
|
interactive.AutorouteSettings autoroute_settings
|
|
= AutorouteSettings.read_scope(scanner, layer_structure);
|
|
if (autoroute_settings != null)
|
|
{
|
|
p_board_handling.settings.autoroute_settings = autoroute_settings;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ScopeKeyword.skip_scope(scanner);
|
|
}
|
|
}
|
|
if (!read_ok)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static void write_rules( WriteScopeParameter p_par, String p_design_name) throws java.io.IOException
|
|
{
|
|
p_par.file.start_scope();
|
|
p_par.file.write("rules PCB ");
|
|
p_par.file.write(p_design_name);
|
|
Structure.write_snap_angle(p_par.file, p_par.board.rules.get_trace_angle_restriction());
|
|
AutorouteSettings.write_scope(p_par.file, p_par.autoroute_settings,
|
|
p_par.board.layer_structure, p_par.identifier_type);
|
|
// write the default rule using 0 as default layer.
|
|
Rule.write_default_rule(p_par, 0);
|
|
// write the via padstacks
|
|
for (int i = 1; i <= p_par.board.library.padstacks.count(); ++i)
|
|
{
|
|
library.Padstack curr_padstack = p_par.board.library.padstacks.get(i);
|
|
if (p_par.board.library.get_via_padstack(curr_padstack.name )!= null)
|
|
{
|
|
Library.write_padstack_scope(p_par, curr_padstack);
|
|
}
|
|
}
|
|
Network.write_via_infos(p_par.board.rules, p_par.file, p_par.identifier_type);
|
|
Network.write_via_rules(p_par.board.rules, p_par.file, p_par.identifier_type);
|
|
Network.write_net_classes(p_par);
|
|
p_par.file.end_scope();
|
|
}
|
|
|
|
private static void add_rules(java.util.Collection<Rule> p_rules, BasicBoard p_board, String p_layer_name)
|
|
{
|
|
int layer_no = -1;
|
|
if (p_layer_name != null)
|
|
{
|
|
layer_no = p_board.layer_structure.get_no(p_layer_name);
|
|
if (layer_no < 0)
|
|
{
|
|
System.out.println("RulesFile.add_rules: layer not found");
|
|
}
|
|
}
|
|
CoordinateTransform coordinate_transform = p_board.communication.coordinate_transform;
|
|
String string_quote = p_board.communication.specctra_parser_info.string_quote;
|
|
for (Rule curr_rule : p_rules)
|
|
{
|
|
if (curr_rule instanceof Rule.WidthRule)
|
|
{
|
|
double wire_width = ((Rule.WidthRule)curr_rule).value;
|
|
int trace_halfwidth = (int) Math.round(coordinate_transform.dsn_to_board(wire_width) / 2);
|
|
if (layer_no < 0)
|
|
{
|
|
p_board.rules.set_default_trace_half_widths(trace_halfwidth);
|
|
}
|
|
else
|
|
{
|
|
p_board.rules.set_default_trace_half_width(layer_no, trace_halfwidth);
|
|
}
|
|
}
|
|
else if (curr_rule instanceof Rule.ClearanceRule)
|
|
{
|
|
Structure.set_clearance_rule(( Rule.ClearanceRule)curr_rule, layer_no, coordinate_transform, p_board.rules, string_quote);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static boolean add_layer_rules(Scanner p_scanner, BasicBoard p_board)
|
|
{
|
|
try
|
|
{
|
|
Object next_token = p_scanner.next_token();
|
|
if (!(next_token instanceof String))
|
|
{
|
|
System.out.println("RulesFile.add_layer_rules: String expected");
|
|
return false;
|
|
}
|
|
String layer_string = (String) next_token;
|
|
next_token = p_scanner.next_token();
|
|
while (next_token != Keyword.CLOSED_BRACKET)
|
|
{
|
|
if (next_token != Keyword.OPEN_BRACKET)
|
|
{
|
|
System.out.println("RulesFile.add_layer_rules: ( expected");
|
|
return false;
|
|
}
|
|
next_token = p_scanner.next_token();
|
|
if (next_token == Keyword.RULE)
|
|
{
|
|
java.util.Collection<Rule> curr_rules = Rule.read_scope(p_scanner);
|
|
add_rules(curr_rules, p_board, layer_string);
|
|
}
|
|
else
|
|
{
|
|
ScopeKeyword.skip_scope(p_scanner);
|
|
}
|
|
next_token = p_scanner.next_token();
|
|
}
|
|
return true;
|
|
}
|
|
catch (java.io.IOException e)
|
|
{
|
|
System.out.println("RulesFile.add_layer_rules: IO error scanning file");
|
|
return false;
|
|
}
|
|
}
|
|
private static boolean read_via_info(Scanner p_scanner, BasicBoard p_board)
|
|
{
|
|
rules.ViaInfo curr_via_info = Network.read_via_info(p_scanner, p_board);
|
|
if (curr_via_info == null)
|
|
{
|
|
return false;
|
|
}
|
|
rules.ViaInfo existing_via = p_board.rules.via_infos.get(curr_via_info.get_name());
|
|
if (existing_via != null)
|
|
{
|
|
// replace existing via info
|
|
p_board.rules.via_infos.remove(existing_via);
|
|
}
|
|
p_board.rules.via_infos.add(curr_via_info);
|
|
return true;
|
|
}
|
|
|
|
private static boolean read_via_rule(Scanner p_scanner, BasicBoard p_board)
|
|
{
|
|
java.util.Collection<String> via_rule = Network.read_via_rule(p_scanner, p_board);
|
|
if (via_rule == null)
|
|
{
|
|
return false;
|
|
}
|
|
Network.add_via_rule(via_rule, p_board);
|
|
return true;
|
|
}
|
|
|
|
private static boolean read_net_class(Scanner p_scanner, LayerStructure p_layer_structure, BasicBoard p_board)
|
|
{
|
|
NetClass curr_class = NetClass.read_scope(p_scanner);
|
|
if (curr_class == null)
|
|
{
|
|
return false;
|
|
}
|
|
Network.insert_net_class(curr_class, p_layer_structure, p_board, p_board.communication.coordinate_transform, false);
|
|
return true;
|
|
}
|
|
}
|