/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: EDIFEquiv.java
*
* Copyright (c) 2005 Sun Microsystems and Static Free Software
*
* Electric(tm) 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.
*
* Electric(tm) 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.io.output;
import com.sun.electric.database.geometry.Orientation;
import com.sun.electric.database.geometry.GenMath.MutableInteger;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.Library;
import com.sun.electric.database.prototype.NodeProto;
import com.sun.electric.database.prototype.PortCharacteristic;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.TextUtils;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.Technology;
import com.sun.electric.technology.technologies.Schematics;
import com.sun.electric.tool.io.FileType;
import com.sun.electric.tool.io.IOTool;
import com.sun.electric.tool.io.input.EDIF;
import com.sun.electric.tool.io.input.EDIF.EDIFPreferences;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Reads in a configuration file that specifies the equivalent Electric nodes for Nodes
* found in (or to be written to) the EDIF file. This allows mapping of Electric primitives
* and Cells to primitives and cells in the target Tool which will read in the EDIF, or vice versa.
* Most importantly, it specifies equivalences between ports on the two nodes which may be in
* different locations. Differing sizes of nodes does not matter.
* <P>
* This is currently only being used with Cadence Virtuoso Composer.
*/
public class EDIFEquiv {
private HashMap<Object,NodeEquivalence> equivsByNodeProto; // key: Electric hash (getElectricKey()), value: NodeEquivalence
private HashMap<Object,NodeEquivalence> equivsByExternal; // key: External hash (getExternalKey()), value: NodeEquivalence
private HashMap<String,VariableEquivalence> exportByVariable; // key: External hash (electric varname), value: VariableEquivalence
private HashMap<String,VariableEquivalence> exportFromVariable; // key: External hash (external varname), value: VariableEquivalence
private HashMap<String,FigureGroupEquivalence> exportByFigureGroup; // key: External hash (electric figureGroupName), value: FigureGroupEquivalence
private HashMap<String,FigureGroupEquivalence> exportFromFigureGroup; // key: External hash (external figureGroupName), value: FigureGroupEquivalence
private HashMap<String,GlobalEquivalence> exportByGlobal; // key: External hash (electric figureGroupName), value: GlobalEquivalence
private HashMap<String,GlobalEquivalence> exportFromGlobal; // key: External hash (external figureGroupName), value: GlobalEquivalence
/**
* Get the node equivalence for the NodeInst. This must be a NodeInst, not a
* NodeProto, because different transistor primitives share the same Primitive
* prototype.
* @param ni the NodeInst to look up
* @return null if none found
*/
public NodeEquivalence getNodeEquivalence(NodeInst ni) {
NodeProto np = ni.getProto();
PrimitiveNode.Function func = np.getFunction();
PortCharacteristic exportType = null;
if (!ni.isCellInstance()) {
func = ni.getFunction();
// func = pn.getTechnology().getPrimitiveFunction(pn, ni.getTechSpecific());
// if this is an off page node and one of it's ports is exported, find out type
if (np == Schematics.tech().offpageNode) {
for (Iterator<PortProto> it = ni.getParent().getPorts(); it.hasNext(); ) {
Export e = (Export)it.next();
if (e.getOriginalPort().getNodeInst() == ni) {
exportType = e.getCharacteristic();
break;
}
}
}
}
return equivsByNodeProto.get(getElectricKey(np, func, exportType));
}
/**
* Method to get the VariableEquivalence that maps Electric variable names to external names.
* @param varName the Electric variable name.
* @return the VariableEquivalence that tells how to do the mapping (null if none).
*/
public VariableEquivalence getElectricVariableEquivalence(String varName)
{
VariableEquivalence ve = exportByVariable.get(varName);
return ve;
}
/**
* Method to get the VariableEquivalence that maps external variable names to Electric names.
* @param varName the external variable name.
* @return the VariableEquivalence that tells how to do the mapping (null if none).
*/
public VariableEquivalence getExternalVariableEquivalence(String varName)
{
VariableEquivalence ve = exportFromVariable.get(varName);
return ve;
}
/**
* Method to get the FigureGroupEquivalence that maps Electric figuregroup names to external names.
* @param fgName the Electric figuregroup name.
* @return the FigureGroupEquivalence that tells how to do the mapping (null if none).
*/
public FigureGroupEquivalence getElectricFigureGroupEquivalence(String fgName)
{
FigureGroupEquivalence fge = exportByFigureGroup.get(fgName);
return fge;
}
/**
* Method to get the FigureGroupEquivalence that maps external figuregroup names to Electric names.
* @param fgName the external figuregroup name.
* @return the FigureGroupEquivalence that tells how to do the mapping (null if none).
*/
public FigureGroupEquivalence getExternalFigureGroupEquivalence(String fgName)
{
FigureGroupEquivalence fge = exportFromFigureGroup.get(fgName);
return fge;
}
/**
* Method to get the GlobalEquivalence that maps Electric global names to external names.
* @param gName the Electric global name.
* @return the GlobalEquivalence that tells how to do the mapping (null if none).
*/
public GlobalEquivalence getElectricGlobalEquivalence(String gName)
{
GlobalEquivalence ge = exportByGlobal.get(gName);
return ge;
}
/**
* Method to get the GlobalEquivalence that maps external global names to Electric names.
* @param gName the external global name.
* @return the GlobalEquivalence that tells how to do the mapping (null if none).
*/
public GlobalEquivalence getExternalGlobalEquivalence(String gName)
{
GlobalEquivalence ge = exportFromGlobal.get(gName);
return ge;
}
/**
* Get the node equivalence for the external reference.
* @param extLib
* @param extCell
* @param extView
* @return null if none found
*/
public NodeEquivalence getNodeEquivalence(String extLib, String extCell, String extView) {
Object key = getExternalKey(extLib, extCell, extView);
return equivsByExternal.get(key);
}
/**
* Get a list of NodeEquivalences
* @return a list of NodeEquivalence objects
*/
public List<NodeEquivalence> getNodeEquivs() {
return new ArrayList<NodeEquivalence>(equivsByExternal.values());
}
/**
* Translate a port location on an Electric node to a the equivalent port
* location on the equivalent external node instance.
* @param connPoint the electric connection point
* @param pi the port inst
* @return the connection point on the equivalent external node instance
*/
public Point2D translatePortConnection(Point2D connPoint, PortInst pi) {
NodeInst ni = pi.getNodeInst();
NodeEquivalence equiv = getNodeEquivalence(ni);
if (equiv == null) return connPoint;
PortEquivalence pe = equiv.getPortEquivElec(pi.getPortProto().getName());
if (pe == null) return connPoint;
AffineTransform af2 = ni.getOrient().concatenate(Orientation.fromAngle(-equiv.rotation*10)).pureRotate();
return pe.translateElecToExt(connPoint, af2);
}
/**
* Translate a port location on an external node instance to the equivalent
* port location on the equivalent Electric node instance
* @param connPoint the connection point on the external node instance
* @param externalLib the external node's library
* @param externalCell the external node
* @param externalView the external node's view
* @param externalPort the external node's port in question
* @return the connection point on the equivalent electric node instance
*/
public Point2D translatePortConnection(Point2D connPoint, String externalLib, String externalCell,
String externalView, String externalPort, String orientation) {
NodeEquivalence equiv = getNodeEquivalence(externalLib, externalCell, externalView);
if (equiv == null) return connPoint;
PortEquivalence pe = equiv.getPortEquivExt(externalPort);
if (pe == null) return connPoint;
int angle = 0;
boolean mirroredAboutXAxis = false;
boolean mirroredAboutYAxis = false;
if (orientation.indexOf("R90") != -1) angle = 900;
if (orientation.indexOf("R180") != -1) angle = 1800;
if (orientation.indexOf("R270") != -1) angle = 2700;
if (orientation.indexOf("MX") != -1) mirroredAboutXAxis = true;
if (orientation.indexOf("MY") != -1) mirroredAboutYAxis = true;
Orientation orient = Orientation.fromJava(angle, mirroredAboutYAxis, mirroredAboutXAxis);
orient = orient.concatenate(Orientation.fromAngle(equiv.rotation*10));
AffineTransform af2 = orient.pureRotate();
Point2D ret = pe.translateExtToElec(connPoint, af2);
if (equiv.xOffset != 0 || equiv.yOffset != 0)
ret = new Point2D.Double(ret.getX()+equiv.xOffset, ret.getY()+equiv.yOffset);
return ret;
}
// hash map key
private Object getElectricKey(NodeProto np, PrimitiveNode.Function func, PortCharacteristic portType) {
if (func == null) func = PrimitiveNode.Function.UNKNOWN;
if (portType == null) portType = PortCharacteristic.UNKNOWN;
return np.getName() + " " + func.toString() + " " + portType.getName();
}
// hash map key
private Object getExternalKey(String externalLib, String externalCell, String externalView) {
return externalLib + " " + externalCell + " " + externalView;
}
// size of elecPorts and extPorts lists must be equal
private void addNodeEquiv(NodeProto np, PrimitiveNode.Function func, PortCharacteristic exportType, int rot,
String extLib, String extCell, String extView, List<Port> elecPorts, List<Port> extPorts) {
List<PortEquivalence> portEquivs = new ArrayList<PortEquivalence>();
if (elecPorts.size() != extPorts.size()) {
System.out.println("Error, port lists differ in size!");
return;
}
for (int i=0; i<elecPorts.size(); i++) {
PortEquivalence pe = new PortEquivalence(elecPorts.get(i), extPorts.get(i));
portEquivs.add(pe);
}
NodeEquivalence equiv = new NodeEquivalence(np, func, exportType, extLib, extCell, extView, rot, portEquivs);
equivsByExternal.put(getExternalKey(extLib, extCell, extView), equiv);
equivsByNodeProto.put(getElectricKey(np, func, exportType), equiv);
}
/**
* Create a new EDIF equivalence object. This contains equivalence information between
* Electric cells/prims and Exteranal EDIF cells/prims. The equivalence information is
* read from a configuration file. The file has the format:
* <pre>
* C Lib Cell View rotation { porta(x,y), ... } ExternalLib ExternalCell ExternalView { porta(x,y), ... }
* P Tech NodeName Function rotation { porta(x,y), ... } ExternalLib ExternalCell ExternalView { porta(x,y), ... }
* F FigureGroup ExternalFigureGroup
* V VariableName ExternalVariableName [appendToElectricOutput]
* # comment
* </pre>
* 'C' is for Cell, and 'P' is for Primitive. The left hand size specifies the Electric cell/node,
* while the right hand side specifies the External tool's cell/node. The list of ports must be the
* same in length, and specify the x,y coordinate of the port. This coordinate is on the prototype of
* the node, or also when the node is default size at 0,0. Note that Electric port locations should
* be locations after the node has been rotated, if rot is not 0. Rotation should be in tenth-degrees.
*
* For 'F', an association between internal FigureGroup names and external names is declared.
* For 'V', an association between internal Variable names and external names is declared. You
* can also specify a string to be append to all matching Variable values.
*/
public EDIFEquiv(String configurationFile) {
equivsByNodeProto = new HashMap<Object,NodeEquivalence>();
equivsByExternal = new HashMap<Object,NodeEquivalence>();
exportByVariable = new HashMap<String,VariableEquivalence>();
exportFromVariable = new HashMap<String,VariableEquivalence>();
exportByFigureGroup = new HashMap<String,FigureGroupEquivalence>();
exportFromFigureGroup = new HashMap<String,FigureGroupEquivalence>();
exportByGlobal = new HashMap<String,GlobalEquivalence>();
exportFromGlobal = new HashMap<String,GlobalEquivalence>();
String file = configurationFile;
if (file.length() == 0)
{
System.out.println("No EDIF configuration information being used");
return;
}
File fd = new File(file);
if (!fd.exists()) {
System.out.println("Error: EDIF configuration file not found: "+fd.getAbsolutePath());
return;
}
System.out.println("Using EDIF configuration file: "+fd.getAbsolutePath());
try {
FileReader reader = new FileReader(fd);
BufferedReader bufReader = new BufferedReader(reader);
String line = "";
int lineno = 1;
while ((line = bufReader.readLine()) != null) {
readLine(line, lineno);
lineno++;
}
} catch (IOException e) {
System.out.println("Error reading EDIF config file ("+fd.getAbsolutePath()+"): "+e.getMessage());
return;
}
}
private static final Pattern portsPat = Pattern.compile("(.+?)\\{(.+?)\\}(.+?)\\{(.+?)\\}");
/**
* Read one line of the configuration file. See Constructor for file format.
* @param line
* @param lineno
* @return false on error
*/
private boolean readLine(String line, int lineno) {
line = line.trim();
if (line.equals("")) return true;
if (line.startsWith("#")) return true;
// special case for Variable equivalences
if (line.startsWith("V"))
{
String [] parts = line.split("\\s+");
String append = "";
double scale = TextUtils.atof(parts[3]);
if (parts.length == 5) append = parts[4];
VariableEquivalence ve = new VariableEquivalence(parts[1], parts[2], scale, append);
exportByVariable.put(parts[1], ve);
exportFromVariable.put(parts[2], ve);
return true;
}
// special case for FigureGroup equivalences
if (line.startsWith("F"))
{
String [] parts = line.split("\\s+");
FigureGroupEquivalence fge = new FigureGroupEquivalence(parts[1], parts[2]);
exportByFigureGroup.put(parts[1], fge);
exportFromFigureGroup.put(parts[2], fge);
return true;
}
// special case for Global equivalences
if (line.startsWith("G"))
{
String [] parts = line.split("\\s+");
GlobalEquivalence ge = new GlobalEquivalence(parts[1], parts[2]);
exportByGlobal.put(parts[1], ge);
exportFromGlobal.put(parts[2], ge);
return true;
}
// grab port parts
Matcher mat = portsPat.matcher(line);
if (!mat.find()) {
System.out.println("Wrong number of curly brackets for ports on line "+lineno);
return false;
}
String elec = mat.group(1).trim();
String elec_ports = mat.group(2).trim();
String ext = mat.group(3).trim();
String ext_ports = mat.group(4).trim();
String [] parts;
// internal definition
NodeProto np = null;
PrimitiveNode.Function func = null;
PortCharacteristic portType = null;
int rot = 0;
parts = elec.split("\\s+");
if (parts.length < 1) {
System.out.println("No Electric arguments on line "+lineno);
return false;
}
boolean keyE = parts[0].equalsIgnoreCase("E") ? true : false;
boolean keyP = parts[0].equalsIgnoreCase("P") ? true : false;
boolean keyC = parts[0].equalsIgnoreCase("C") ? true : false;
if (keyP && parts.length != 5) {
System.out.println("Wrong number of arguments for Electric Primitive, expected 'P tech node func rot' on line "+lineno);
return false;
}
if (keyE && parts.length != 6) {
System.out.println("Wrong number of arguments for Electric Primitive, expected 'E tech node func rot porttype' on line "+lineno);
return false;
}
if (keyC && parts.length != 5) {
System.out.println("Wrong number of arguments for Electric cell, expected 'C lib cell view rot' on line "+lineno);
return false;
}
if (keyP || keyE) {
// primitive node
np = null;
Technology tech = Technology.findTechnology(parts[1]);
if (tech == null)
{
System.out.println("Could not find Technology " + parts[1] + " on line " + lineno);
return false;
}
np = tech.findNodeProto(parts[2]);
if (np == null)
{
System.out.println("Could not find " + parts[2] + " in technology " +
parts[1] + " on line " + lineno);
return false;
}
for (PrimitiveNode.Function function : PrimitiveNode.Function.getFunctions())
{
if (parts[3].equals(function.getName()) || parts[3].equals(function.getShortName()) ||
parts[3].equals(function.getConstantName()))
{
func = function;
break;
}
}
if (func == null)
{
System.out.println("Could not find Function " + parts[3] + " on line " + lineno);
return false;
}
try {
rot = Integer.parseInt(parts[4]);
} catch (NumberFormatException e) {
System.out.println("Rotation " + parts[4] + " is not an integer on line " + lineno);
}
if (keyE) {
// get port type
portType = PortCharacteristic.findCharacteristic(parts[5]);
if (portType == null) {
System.out.println("Unable to find Export type " + parts[5] + " on line " + lineno);
return false;
}
}
} else if (keyC)
{
// cell
Library lib = Library.findLibrary(parts[1]);
if (lib == null)
{
System.out.println("Could not find Library " + parts[1] + " on line " + lineno);
return false;
}
np = lib.findNodeProto(parts[2]+"{"+parts[3]+"}");
if (np == null)
{
System.out.println("Could not find Cell " + parts[2] + ", view " + parts[3] + " in library " + parts[1] +
" on line " + lineno);
return false;
}
func = PrimitiveNode.Function.UNKNOWN;
try {
rot = Integer.parseInt(parts[4]);
} catch (NumberFormatException e) {
System.out.println("Rotation " + parts[4] + " is not an integer on line " + lineno);
}
} else {
System.out.println("Unrecognized key " + parts[0] + ", expected 'P', 'C', or 'E' on line " + lineno);
return false;
}
// external definition
String extlib, extname, extview;
parts = ext.split("\\s+");
if (parts.length != 3) {
System.out.println("Wrong number of arguments for external lib, expected 'lib name view' on line "+lineno);
return false;
}
extlib = parts[0];
extname = parts[1];
extview = parts[2];
// port equivalences
List<Port> elecPorts = parsePortsList(elec_ports, lineno);
List<Port> extPorts = parsePortsList(ext_ports, lineno);
if (elecPorts.size() != extPorts.size()) {
System.out.println("Port lists are not the same size on line "+lineno);
return false;
}
addNodeEquiv(np, func, portType, rot, extlib, extname, extview, elecPorts, extPorts);
return true;
}
/**
* String should be of the format (ignore spaces):
* a(x,y), b(x,y), ... z(x,y)
* @param portsList
* @return a list of Port objects
*/
private List<Port> parsePortsList(String portsList, int lineno) {
// split by commas not contained in ()
boolean opened = false;
List<Port> ports = new ArrayList<Port>();
int i = 0, last = 0;
for (i=0; i<portsList.length(); i++) {
char c = portsList.charAt(i);
if (c == '(') {
if (opened == true) {
System.out.println("Unmatched open parenthesis in ports list on line "+lineno);
return ports;
}
opened = true;
continue;
}
if (c == ')') {
if (opened == false) {
System.out.println("Unmatched close parenthesis in ports list on line "+lineno);
return ports;
}
opened = false;
continue;
}
if (c == ',') {
if (opened == true) // ignore commands in coords (x,y)
continue;
String portDef = portsList.substring(last, i);
last = i+1;
Port port = parsePort(portDef, lineno);
if (port != null) ports.add(port);
}
}
// last one does not have trailing comma
if (last < i) {
String portDef = portsList.substring(last, i);
Port port = parsePort(portDef, lineno);
if (port != null) ports.add(port);
}
return ports;
}
/**
* String should be of the format (ignore spaces):
* a(x,y)
* @param port
* @return a Port object
*/
private Port parsePort(String port, int lineno) {
boolean ignorePort = false;
if (port.trim().equals("NA")) return new Port("NA", new Point2D.Double(0,0), true);
String [] fields = port.split("[(),]");
if (fields.length != 3) {
System.out.println("Expected port format portname(x,y), but got "+port+" on line "+lineno);
return null;
}
double x = 0, y = 0;
try {
x = Double.parseDouble(fields[1]);
y = Double.parseDouble(fields[2]);
} catch (NumberFormatException e) {
System.out.println("Could not convert port coordinate to number: "+port+", on line "+lineno);
return null;
}
String name = fields[0].trim();
if (name.equals("NA")) ignorePort = true;
if (name.equals("\\NA")) name = "NA";
return new Port(fields[0].trim(), new Point2D.Double(x, y), ignorePort);
}
public void print() {
for (NodeEquivalence ne : equivsByNodeProto.values()) {
System.out.println(ne.toString());
}
}
// ==================================================================================
// Equivalence Classes
public static class NodeEquivalence {
public final NodeProto np;
public final PrimitiveNode.Function function;
public final PortCharacteristic exortedType;
public final String externalLib;
public final String externalCell;
public final String externalView;
public final List<PortEquivalence> portEquivs;
public final int rotation; // in degrees, rotate the electric prim by this value to match the cadence prim
public final double xOffset, yOffset;
private NodeEquivalence(NodeProto np, PrimitiveNode.Function func, PortCharacteristic exportedType,
String externalLib, String externalCell, String externalView, int rotation, List<PortEquivalence> portEquivs) {
this.np = np;
this.function = func;
this.exortedType = exportedType;
this.externalLib = externalLib;
this.externalCell = externalCell;
this.externalView = externalView;
this.rotation = rotation;
this.portEquivs = portEquivs;
// figure out offset
double bestXOff = 0, bestYOff = 0;
if (rotation == 0)
{
Map<Double,MutableInteger> xMap = new HashMap<Double,MutableInteger>();
Map<Double,MutableInteger> yMap = new HashMap<Double,MutableInteger>();
for(EDIFEquiv.PortEquivalence pe : portEquivs)
{
Double diffX = new Double(pe.getElecPort().loc.getX() - pe.getExtPort().loc.getX());
MutableInteger xCount = xMap.get(diffX);
if (xCount == null) xMap.put(diffX, xCount = new MutableInteger(0));
xCount.increment();
Double diffY = new Double(pe.getElecPort().loc.getY() - pe.getExtPort().loc.getY());
MutableInteger yCount = yMap.get(diffY);
if (yCount == null) yMap.put(diffY, yCount = new MutableInteger(0));
yCount.increment();
}
int bestXInc = 0;
for(Double diffX : xMap.keySet())
{
MutableInteger xCount = xMap.get(diffX);
if (xCount.intValue() > bestXInc)
{
bestXInc = xCount.intValue();
bestXOff = diffX.doubleValue();
}
}
int bestYInc = 0;
for(Double diffY : yMap.keySet())
{
MutableInteger yCount = yMap.get(diffY);
if (yCount.intValue() > bestYInc)
{
bestYInc = yCount.intValue();
bestYOff = diffY.doubleValue();
}
}
}
xOffset = bestXOff;
yOffset = bestYOff;
}
/**
* Get the PortEquivalence object for the Electric port name.
* @param elecPortName
* @return null if no such port
*/
public PortEquivalence getPortEquivElec(String elecPortName) {
for (PortEquivalence pe : portEquivs) {
if (pe.getElecPort().name.equals(elecPortName))
return pe;
}
return null;
}
/**
* Get the PortEquivalence object for the external node's port name.
* @param extPortName
* @return null if no such port
*/
public PortEquivalence getPortEquivExt(String extPortName) {
for (PortEquivalence pe : portEquivs) {
if (pe.getExtPort().name.equals(extPortName))
return pe;
}
return null;
}
/**
* Get a list of the external ports of this equivalence class
* @return a list of EDIFEquiv.Port objects
*/
public List<Port> getExtPorts() {
List<Port> extPorts = new ArrayList<Port>();
for (PortEquivalence pe : portEquivs) {
extPorts.add(pe.getExtPort());
}
return extPorts;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("NodeEquivalence Elec: "+np.describe(false)+", func: "+function+"\n");
buf.append(" Ext: "+externalLib+" "+externalCell+" "+externalView+"\n");
for (PortEquivalence pe : portEquivs) {
buf.append(pe.toString()+"\n");
}
return buf.toString();
}
}
public static class PortEquivalence {
private final Port elecPort;
private final Port extPort;
private PortEquivalence(Port elecPort, Port extPort) {
this.elecPort = elecPort;
this.extPort = extPort;
}
public Port getElecPort() { return elecPort; }
public Port getExtPort() { return extPort; }
/**
* Translate the location of the electric port to the external port
* @param point the location of the port in Electric.
* @return the location of the port in EDIF.
*/
public Point2D translateElecToExt(Point2D point, AffineTransform niPureRotation) {
Point2D elecPoint = new Point2D.Double(elecPort.loc.getX(), elecPort.loc.getY());
Point2D extPoint = new Point2D.Double(extPort.loc.getX(), extPort.loc.getY());
if (niPureRotation != null) {
elecPoint = niPureRotation.transform(elecPort.loc, elecPoint);
extPoint = niPureRotation.transform(extPort.loc, extPoint);
}
return new Point2D.Double(point.getX()-(elecPoint.getX()-extPoint.getX()),
point.getY()-(elecPoint.getY()-extPoint.getY()));
}
/**
* Translate the location of the external port to the electric port
* @param point the location of the port in EDIF.
* @return the location of the port in Electric.
*/
public Point2D translateExtToElec(Point2D point, AffineTransform niPureRotation) {
Point2D elecPoint = new Point2D.Double(elecPort.loc.getX(), elecPort.loc.getY());
Point2D extPoint = new Point2D.Double(extPort.loc.getX(), extPort.loc.getY());
if (niPureRotation != null) {
elecPoint = niPureRotation.transform(elecPort.loc, elecPoint);
extPoint = niPureRotation.transform(extPort.loc, extPoint);
}
return new Point2D.Double(point.getX()-(elecPoint.getX()-extPoint.getX()),
point.getY()-(elecPoint.getY()-extPoint.getY()));
}
public String toString() {
return "PortEquiv Elec{ "+elecPort+" } - Ext{ "+extPort+" }";
}
}
public static class VariableEquivalence {
public final String elecVarName;
public final String externVarName;
public final double scale;
public final String appendElecOutput;
private VariableEquivalence(String elecVarName, String externVarName, double scale, String appendElecOutput) {
this.elecVarName = elecVarName;
this.externVarName = externVarName;
this.scale = scale;
this.appendElecOutput = appendElecOutput;
}
}
public static class FigureGroupEquivalence {
public final String elecFGName;
public final String externFGName;
private FigureGroupEquivalence(String elecFGName, String externFGName) {
this.elecFGName = elecFGName;
this.externFGName = externFGName;
}
}
public static class GlobalEquivalence {
public final String elecGName;
public final String externGName;
private GlobalEquivalence(String elecGName, String externGName) {
this.elecGName = elecGName;
this.externGName = externGName;
}
}
public static class Port {
public final String name;
public final Point2D loc;
public final boolean ignorePort;
private Port(String name, Point2D loc, boolean ignorePort) {
this.name = name;
this.loc = loc;
this.ignorePort = ignorePort;
}
public String toString() {
return name+"("+loc.getX()+","+loc.getY()+")"+(ignorePort?"[ignored]":"");
}
}
/** Unit Test */
public static void mainTest() {
EDIFEquiv eq = new EDIFEquiv(IOTool.getEDIFConfigurationFile());
eq.print();
}
}