/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: PlacementFrame.java
*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
*
* 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.placement;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import com.sun.electric.util.math.Orientation;
/**
* Class to define a framework for Placement algorithms. To make Placement
* algorithms easier to write, all Placement algorithms must extend this class.
* The Placement algorithm then defines two methods:
*
* public String getAlgorithmName() returns the name of the Placement algorithm
*
* void runPlacement(List<PlacementNode> nodesToPlace, List<PlacementNetwork>
* allNetworks, String cellName) runs the placement on the "nodesToPlace",
* calling each PlacementNode's "setPlacement()" and "setOrientation()" methods
* to establish the proper placement.
*
* To avoid the complexities of the Electric database, three shadow-classes are
* defined that describe the necessary information that Placement algorithms
* want:
*
* PlacementNode is an actual node (primitive or cell instance) that is to be
* placed. PlacementPort is the connection site on the PlacementNode. Each
* PlacementNode has a list of zero or more PlacementPort objects, and each
* PlacementPort points to its "parent" PlacementNode. PlacementNetwork
* determines which PlacementPort objects will connect together. Each
* PlacementNetwork has a list of two or more PlacementPort objects that it
* connects, and each PlacementPort has a PlacementNetwork in which it resides.
*/
public abstract class PlacementFrame {
protected int numOfThreads;
protected int runtime;
private ArrayList<PlacementParameter> allParameters = new ArrayList<PlacementParameter>();
/**
* Method to do Placement (overridden by actual Placement algorithms).
*
* @param nodesToPlace
* a list of all nodes that are to be placed.
* @param allNetworks
* a list of all networks that connect the nodes.
* @param cellName
* the name of the cell being placed.
*/
protected abstract void runPlacement(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks, String cellName);
/**
* Method to return the name of the placement algorithm (overridden by
* actual Placement algorithms).
*
* @return the name of the placement algorithm.
*/
public abstract String getAlgorithmName();
/**
* Method to return a list of parameters for this placement algorithm.
*
* @return a list of parameters for this placement algorithm.
*/
public final List<PlacementParameter> getParameters() {
return allParameters;
}
public void setParamterValues(int threads, int runtime) {
this.numOfThreads = threads;
this.runtime = runtime;
}
/**
* Class to define a parameter for a placement algorithm.
*/
public class PlacementParameter {
public static final int TYPEINTEGER = 1;
public static final int TYPESTRING = 2;
public static final int TYPEDOUBLE = 3;
public static final int TYPEBOOLEAN = 4;
final String key;
private final String title;
final Object factoryValue;
private Object cachedValue;
private final int type;
private String[] intMeanings;
public PlacementParameter(String name, String title, int factory) {
key = getAlgorithmName() + "-" + name;
this.title = title;
cachedValue = factoryValue = Integer.valueOf(factory);
type = TYPEINTEGER;
intMeanings = null;
allParameters.add(this);
}
public PlacementParameter(String name, String title, int factory, String[] meanings) {
key = getAlgorithmName() + "-" + name;
this.title = title;
cachedValue = factoryValue = Integer.valueOf(factory);
type = TYPEINTEGER;
intMeanings = meanings;
allParameters.add(this);
}
public PlacementParameter(String name, String title, String factory) {
key = getAlgorithmName() + "-" + name;
this.title = title;
cachedValue = factoryValue = String.valueOf(factory);
type = TYPESTRING;
intMeanings = null;
allParameters.add(this);
}
public PlacementParameter(String name, String title, double factory) {
key = getAlgorithmName() + "-" + name;
this.title = title;
cachedValue = factoryValue = Double.valueOf(factory);
type = TYPEDOUBLE;
intMeanings = null;
allParameters.add(this);
}
public PlacementParameter(String name, String title, boolean factory) {
key = getAlgorithmName() + "-" + name;
this.title = title;
cachedValue = factoryValue = Boolean.valueOf(factory);
type = TYPEBOOLEAN;
intMeanings = null;
allParameters.add(this);
}
public PlacementFrame getOwner() {
return PlacementFrame.this;
}
public String getName() {
return title;
}
public int getType() {
return type;
}
public int getIntValue() {
return ((Integer)cachedValue).intValue();
}
public String[] getIntMeanings() {
return intMeanings;
}
public String getStringValue() {
return (String)cachedValue;
}
public double getDoubleValue() {
return ((Double)cachedValue).doubleValue();
}
public boolean getBooleanValue() {
return ((Boolean)cachedValue).booleanValue();
}
void setValue(Object value) {
assert value.getClass() == factoryValue.getClass();
if (value.equals(factoryValue))
value = factoryValue;
cachedValue = value;
}
}
/**
* Class to define a node that is being placed. This is a shadow class for
* the internal Electric object "NodeInst". There are minor differences
* between PlacementNode and NodeInst, for example, PlacementNode is
* presumed to be centered in the middle, with port offsets based on that
* center, whereas the NodeInst has a cell-center that may not be in the
* middle.
*/
public abstract static class PlacementNode {
private double xPos, yPos;
private Orientation orient;
private Object userObject;
public Object getUserObject() {
return userObject;
}
public void setUserObject(Object obj) {
userObject = obj;
}
/**
* Method to return a list of PlacementPorts on this PlacementNode.
*
* @return a list of PlacementPorts on this PlacementNode.
*/
public abstract List<PlacementPort> getPorts();
/**
* Method to return the width of this PlacementNode.
*
* @return the width of this PlacementNode.
*/
public abstract double getWidth();
/**
* Method to return the height of this PlacementNode.
*
* @return the height of this PlacementNode.
*/
public abstract double getHeight();
/**
* Method to set the location of this PlacementNode. The Placement
* algorithm must call this method to set the final location of the
* PlacementNode.
*
* @param x
* the X-coordinate of the center of this PlacementNode.
* @param y
* the Y-coordinate of the center of this PlacementNode.
*/
public void setPlacement(double x, double y) {
xPos = x;
yPos = y;
}
/**
* Method to set the orientation (rotation and mirroring) of this
* PlacementNode. The Placement algorithm may call this method to set
* the final orientation of the PlacementNode.
*
* @param o
* the Orientation of this PlacementNode.
*/
public void setOrientation(Orientation o) {
orient = o;
for (PlacementPort plPort : getPorts())
plPort.computeRotatedOffset();
}
/**
* Method to return the X-coordinate of the placed location of this
* PlacementNode. This is the location that the Placement algorithm has
* established for this PlacementNode.
*
* @return the X-coordinate of the placed location of this
* PlacementNode.
*/
public double getPlacementX() {
return xPos;
}
/**
* Method to return the Y-coordinate of the placed location of this
* PlacementNode. This is the location that the Placement algorithm has
* established for this PlacementNode.
*
* @return the Y-coordinate of the placed location of this
* PlacementNode.
*/
public double getPlacementY() {
return yPos;
}
/**
* Method to return the Orientation of this PlacementNode. This is the
* Orientation that the Placement algorithm has established for this
* PlacementNode.
*
* @return the Orientation of this PlacementNode.
*/
public Orientation getPlacementOrientation() {
return orient;
}
/**
* Method to return the name of NodeProto of this PlacementNode.
*
* @return the NodeProto of this PlacementNode.
*/
public abstract String getTypeName();
}
/**
* Class to define ports on PlacementNode objects. This is a shadow class
* for the internal Electric object "PortInst".
*/
public static class PlacementPort {
private double offX, offY;
private double rotatedOffX, rotatedOffY;
private PlacementNode plNode;
private PlacementNetwork plNet;
/**
* Constructor to create a PlacementPort.
*
* @param x
* the X offset of this PlacementPort from the center of its
* PlacementNode.
* @param y
* the Y offset of this PlacementPort from the center of its
* PlacementNode.
*/
public PlacementPort(double x, double y) {
offX = x;
offY = y;
}
/**
* Method to set the "parent" PlacementNode on which this PlacementPort
* resides.
*
* @param pn
* the PlacementNode on which this PlacementPort resides.
*/
public void setPlacementNode(PlacementNode pn) {
plNode = pn;
}
/**
* Method to return the PlacementNode on which this PlacementPort
* resides.
*
* @return the PlacementNode on which this PlacementPort resides.
*/
public PlacementNode getPlacementNode() {
return plNode;
}
/**
* Method to return the PlacementNetwork on which this PlacementPort
* resides.
*
* @param pn
* the PlacementNetwork on which this PlacementPort resides.
*/
public void setPlacementNetwork(PlacementNetwork pn) {
plNet = pn;
}
/**
* Method to return the PlacementNetwork on which this PlacementPort
* resides.
*
* @return the PlacementNetwork on which this PlacementPort resides. If
* this PlacementPort does not connect to any other
* PlacementPort, the PlacementNetwork may be null.
*/
public PlacementNetwork getPlacementNetwork() {
return plNet;
}
/**
* Method to return the offset of this PlacementPort's X coordinate from
* the center of its PlacementNode. The offset is valid when no
* Orientation has been applied.
*
* @return the offset of this PlacementPort's X coordinate from the
* center of its PlacementNode.
*/
public double getOffX() {
return offX;
}
/**
* Method to return the offset of this PlacementPort's Y coordinate from
* the center of its PlacementNode. The offset is valid when no
* Orientation has been applied.
*
* @return the offset of this PlacementPort's Y coordinate from the
* center of its PlacementNode.
*/
public double getOffY() {
return offY;
}
/**
* Method to return the offset of this PlacementPort's X coordinate from
* the center of its PlacementNode. The coordinate assumes that the
* PlacementNode has been rotated by its Orientation.
*
* @return the offset of this PlacementPort's X coordinate from the
* center of its PlacementNode.
*/
public double getRotatedOffX() {
return rotatedOffX;
}
/**
* Method to return the offset of this PlacementPort's Y coordinate from
* the center of its PlacementNode. The coordinate assumes that the
* PlacementNode has been rotated by its Orientation.
*
* @return the offset of this PlacementPort's Y coordinate from the
* center of its PlacementNode.
*/
public double getRotatedOffY() {
return rotatedOffY;
}
/**
* Internal method to compute the rotated offset of this PlacementPort
* assuming that the Orientation of its PlacementNode has changed. TODO:
* why is this public? it should not be accessed!
*/
public void computeRotatedOffset() {
Orientation orient = plNode.getPlacementOrientation();
if (orient == Orientation.IDENT) {
rotatedOffX = offX;
rotatedOffY = offY;
return;
}
AffineTransform trans = orient.pureRotate();
Point2D offset = new Point2D.Double(offX, offY);
trans.transform(offset, offset);
rotatedOffX = offset.getX();
rotatedOffY = offset.getY();
}
}
/**
* Class to define networks of PlacementPort objects. This is a shadow class
* for the internal Electric object "Network", but it is simplified for
* Placement.
*/
public static class PlacementNetwork {
private List<PlacementPort> portsOnNet;
/**
* Constructor to create this PlacementNetwork with a list of
* PlacementPort objects that it connects.
*
* @param ports
* a list of PlacementPort objects that it connects.
*/
public PlacementNetwork(List<PlacementPort> ports) {
portsOnNet = ports;
}
/**
* Method to return the list of PlacementPort objects on this
* PlacementNetwork.
*
* @return a list of PlacementPort objects on this PlacementNetwork.
*/
public List<PlacementPort> getPortsOnNet() {
return portsOnNet;
}
}
}