Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: PlacementAdapter.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 com.sun.electric.database.EditingPreferences;
import com.sun.electric.database.ImmutableArcInst;
import com.sun.electric.database.geometry.EPoint;
import com.sun.electric.database.geometry.ERectangle;
import com.sun.electric.database.hierarchy.Cell;
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.Version;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.topology.SteinerTree;
import com.sun.electric.database.topology.SteinerTree.SteinerTreePort;
import com.sun.electric.database.topology.SteinerTree.SteinerTreePortPair;
import com.sun.electric.database.variable.TextDescriptor;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.technology.technologies.Schematics;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.placement.PlacementFrame.PlacementNetwork;
import com.sun.electric.tool.placement.forceDirected1.PlacementForceDirectedTeam5;
import com.sun.electric.tool.placement.forceDirected2.PlacementForceDirectedStaged;
import com.sun.electric.tool.placement.general.BottomUpPartition;
import com.sun.electric.tool.placement.general.BottomUpPlace;
import com.sun.electric.tool.placement.general.Control;
import com.sun.electric.tool.placement.general.FDRowCol;
import com.sun.electric.tool.placement.general.SARowCol;
import com.sun.electric.tool.placement.genetic1.g1.GeneticPlacement;
import com.sun.electric.tool.placement.genetic2.PlacementGenetic;
import com.sun.electric.tool.placement.metrics.AbstractMetric;
import com.sun.electric.tool.placement.metrics.boundingbox.BBMetric;
import com.sun.electric.tool.placement.metrics.mst.MSTMetric;
import com.sun.electric.tool.placement.simulatedAnnealing1.SimulatedAnnealing;
import com.sun.electric.tool.placement.simulatedAnnealing2.PlacementSimulatedAnnealing;
import com.sun.electric.util.ElapseTimer;
import com.sun.electric.util.TextUtils;
import com.sun.electric.util.math.Orientation;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* PlacementExport describes exports in the cell. Placement algorithms do not
* usually need this information: it exists as a way to communicate the
* information internally.
*/
public class PlacementAdapter {
private static final Logger logger = LoggerFactory.getLogger(PlacementAdapter.class);
/**
* 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 static class PlacementNode extends PlacementFrame.PlacementNode {
private final NodeInst originalNode;
private final NodeProto original;
private final String nodeName;
private final int techBits;
private final double width, height;
private final List ports;
private Map addedVariables;
private final boolean terminal;
private Map> equivPorts;
/**
* Method to create a PlacementNode object.
* The original object must be defined by giving either the NodeInst or the NodeProto.
* @param ni the original NodeInst from which this PlacementNode is derived (may be null).
* @param type the original Electric type of this PlacementNode (may be null).
* @param name the name to give the node once placed (may be null).
* @param tBits the technology-specific bits of this PlacementNode
* (typically 0 except for specialized Schematics components).
* @param wid the width of this PlacementNode.
* @param hei the height of this PlacementNode.
* @param pps a list of PlacementPort on the PlacementNode, indicating connection locations.
* @param terminal
*/
public PlacementNode(NodeInst ni, NodeProto type, String name, int tBits, double wid, double hei,
List pps, boolean terminal) {
originalNode = ni;
original = type;
nodeName = name;
techBits = tBits;
width = wid;
height = hei;
ports = new ArrayList(pps);
equivPorts = new HashMap>();
this.terminal = terminal;
}
/**
* Method to indicate that two ports are equivalent on a node,
* and therefore either one can be wired.
* @param p1 the first equivalent PlacementPort.
* @param p2 the second equivalent PlacementPort.
*/
public void addEquivalentPorts(PlacementPort p1, PlacementPort p2)
{
Set list1 = equivPorts.get(p1);
if (list1 == null) equivPorts.put(p1, list1 = new HashSet());
list1.add(p2);
Set list2 = equivPorts.get(p2);
if (list2 == null) equivPorts.put(p2, list2 = new HashSet());
list2.add(p1);
}
public Set getEquivalents(PlacementPort p) { return equivPorts.get(p); }
/**
* Method to add variables to this PlacementNode. Variables are extra
* name/value pairs, for example a transistor width and length.
*
* @param name
* the name of the variable to add.
* @param value
* the value of the variable to add.
*/
public void addVariable(String name, Object value) {
if (addedVariables == null)
addedVariables = new HashMap();
addedVariables.put(name, value);
}
/**
* Method to return the NodeProto of this PlacementNode.
*
* @return the NodeProto of this PlacementNode.
*/
public NodeProto getType() {
if (original != null) return original;
if (originalNode != null) return originalNode.getProto();
return null;
}
/**
* Method to return the original NodeInst of this PlacementNode.
* @return the original NodeInst of this PlacementNode (may be null).
*/
public NodeInst getOriginal() {
return originalNode;
}
/**
* Method to return the name of NodeProto of this PlacementNode.
*
* @return the name NodeProto of this PlacementNode.
*/
public String getTypeName() {
if (original != null) return original.getName();
if (originalNode != null) return originalNode.getProto().getName();
return null;
}
/**
* Method to return a list of PlacementPorts on this PlacementNode.
*
* @return a list of PlacementPorts on this PlacementNode.
*/
public List getPorts() {
return ports;
}
/**
* Method to return the technology-specific information of this
* PlacementNode.
*
* @return the technology-specific information of this PlacementNode
* (typically 0 except for specialized Schematics components).
*/
public int getTechBits() {
return techBits;
}
/**
* Method to return the width of this PlacementNode.
*
* @return the width of this PlacementNode.
*/
@Override
public double getWidth() {
return width;
}
/**
* Method to return the height of this PlacementNode.
*
* @return the height of this PlacementNode.
*/
@Override
public double getHeight() {
return height;
}
/**
* @return the terminal
*/
public boolean isTerminal() {
return terminal;
}
@Override
public String toString() {
if (originalNode != null) return originalNode.describe(false);
String name = original.describe(false);
if (nodeName != null)
name += "[" + nodeName + "]";
if (getTechBits() != 0)
name += "(" + getTechBits() + ")";
return name;
}
}
/**
* Class to define ports on PlacementNode objects. This is a shadow class
* for the internal Electric object "PortInst".
*/
public static class PlacementPort extends PlacementFrame.PlacementPort {
private PortProto proto;
/**
* 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.
* @param pp
* the Electric PortProto of this PlacementPort.
*/
public PlacementPort(double x, double y, PortProto pp) {
super(x, y);
proto = pp;
}
/**
* Method to return the Electric PortProto that this PlacementPort uses.
*
* @return the Electric PortProto that this PlacementPort uses.
*/
public PortProto getPortProto() {
return proto;
}
public String toString() {
return proto.getName();
}
}
/**
* Class to define an Export that will be placed in the circuit.
*/
public static class PlacementExport {
private PlacementPort portToExport;
private String exportName;
private PortCharacteristic characteristic;
/**
* Constructor to create a PlacementExport with the information about an
* Export to be created.
*
* @param port
* the PlacementPort that is being exported.
* @param name
* the name to give the Export.
* @param chr
* the PortCharacteristic (input, output, etc.) to give the
* Export.
*/
public PlacementExport(PlacementPort port, String name, PortCharacteristic chr) {
portToExport = port;
exportName = name;
characteristic = chr;
}
PlacementPort getPort() {
return portToExport;
}
String getName() {
return exportName;
}
PortCharacteristic getCharacteristic() {
return characteristic;
}
}
/**
* Class to define an optimized connection between two PlacementPorts
*/
public static class PlacementConnection extends SteinerTreePortPair
{
private boolean isRail;
public PlacementConnection(SteinerTreePort p1, SteinerTreePort p2, boolean isRail)
{
super(p1, p2);
this.isRail = isRail;
}
public boolean isOnPowerGround() { return isRail; }
}
/**
* Static list of all Placement algorithms. When you create a new algorithm,
* add it to the following list.
*/
public static Control GEN = new Control(); // General control
public static BottomUpPartition BUpa = new BottomUpPartition(); // Bottom-Up Partition
public static BottomUpPlace BUpl = new BottomUpPlace(); // Bottom-Up Placement
public static SimulatedAnnealing SA1 = new SimulatedAnnealing(); // Simulated Annealing (team 2)
public static PlacementSimulatedAnnealing SA2 = new PlacementSimulatedAnnealing(); // Simulated Annealing (team 6)
public static SARowCol SA3 = new SARowCol(); // Simulated Annealing (row/column)
public static GeneticPlacement G1 = new GeneticPlacement(); // Genetic (team 3)
public static PlacementGenetic G2 = new PlacementGenetic(); // Genetic (team 4)
public static PlacementForceDirectedTeam5 FD1 = new PlacementForceDirectedTeam5(); // Force Directed (team 5)
public static PlacementForceDirectedStaged FD2 = new PlacementForceDirectedStaged(); // Force Directed (team 7)
public static FDRowCol FD3 = new FDRowCol(); // Force Directed (row/column)
public static PlacementMinCut MC = new PlacementMinCut(); // Min-Cut
public static PlacementSimple SIMP = new PlacementSimple(); // Simple
public static PlacementRandom RAND = new PlacementRandom(); // Random
/** preserved mapping to placed cell */ private static Map namedPlacedNodes;
/** HPWL from last run */ private static String lastHPWL;
static PlacementFrame[] placementAlgorithms = { GEN, BUpa, BUpl, SA1, SA2, SA3, G1, G2, FD1, FD2, FD3, MC, SIMP, RAND};
/**
* Method to return a list of all Placement algorithms.
* @return a list of all Placement algorithms.
*/
public static PlacementFrame[] getPlacementAlgorithms() {
return placementAlgorithms;
}
/**
* Entry point for other tools that wish to describe a network to be placed.
* Creates a cell with the placed network.
* @param lib the Library in which to create the placed Cell.
* @param cellName the name of the Cell to create.
* @param nodesToPlace a List of PlacementNodes to place in the Cell.
* @param allNetworks a List of PlacementNetworks to connect in the Cell.
* @param exportsToPlace a List of PlacementExports to create in the Cell.
* @param iconToPlace non-null to place an instance of itself (the icon) in the Cell.
* @param ep EditingPreferences with default sizes and text descriptors
* @param prefs placement preferences
* @param quiet
* @param job the Job (for testing abort).
* @return the newly created Cell.
*/
public static Cell doPlacement(PlacementFrame pla, Library lib, String cellName,
List nodesToPlace, List allNetworks, List exportsToPlace,
NodeProto iconToPlace, EditingPreferences ep, Placement.PlacementPreferences prefs, boolean quiet, Job job) {
ElapseTimer timer = ElapseTimer.createInstance().start();
System.out.println("Running placement on cell '" + (lib == Library.getCurrent() ? "" : lib.getName()+":") +
cellName + "' using the '" + pla.getAlgorithmName() + "' algorithm");
// do the real work of placement
if (pla instanceof PlacementFrameElectric) {
((PlacementFrameElectric)pla).setEditingPreferences(ep);
}
for (PlacementFrame.PlacementParameter par : pla.getParameters()) {
par.setValue(prefs.getParameter(par));
}
List nodesToPlaceCopy = new ArrayList(nodesToPlace);
pla.runPlacement(nodesToPlaceCopy, allNetworks, cellName, job);
if (pla.isFailure()) return null;
Map> optimalConnections = new HashMap>();
Cell cell = doGeneratePlacedCell(lib, cellName, nodesToPlace, iconToPlace, allNetworks, exportsToPlace, ep, timer, quiet, optimalConnections);
AbstractMetric bmetric = new BBMetric(nodesToPlaceCopy, allNetworks, optimalConnections);
lastHPWL = bmetric.toString();
if (Job.getDebug() && !quiet && logger.isDebugEnabled()) {
InetAddress addr;
Date now = new Date();
try {
addr = InetAddress.getLocalHost();
String hostname = addr.getHostName();
logger.debug("====================================================");
logger.debug("machine: " + hostname);
logger.debug("date: " + TextUtils.formatDate(now));
logger.debug("Electric's version: " + Version.getVersion());
logger.debug("algorithm: " + pla.getAlgorithmName());
logger.debug("#threads : " + pla.numOfThreads);
logger.debug("#runtime : " + pla.runtime);
logger.debug("cell : " + cellName);
logger.debug("### BBMetric: " + lastHPWL);
AbstractMetric mstMetric = new MSTMetric(nodesToPlaceCopy, allNetworks, optimalConnections);
logger.debug("### MSTMetric: " + mstMetric.toString());
logger.debug("====================================================");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
return cell;
}
public static String getLastHPWL() { return lastHPWL; }
private static Cell doGeneratePlacedCell(Library lib, String cellName, List nodesToPlace,
NodeProto iconToPlace, List allNetworks, List exportsToPlace,
EditingPreferences ep, ElapseTimer timer, boolean quiet, Map> optimalConnections)
{
// create a new cell for the placement results
Cell newCell = Cell.makeInstance(ep, lib, cellName);
// place the nodes in the new cell
Map placedNodes = new HashMap();
namedPlacedNodes = new HashMap();
for (PlacementNode plNode : nodesToPlace) {
double xPos = plNode.getPlacementX();
double yPos = plNode.getPlacementY();
Orientation orient = plNode.getPlacementOrientation();
NodeProto np = plNode.getType();
if (np instanceof Cell) {
Cell placementCell = (Cell) np;
Rectangle2D bounds = placementCell.getBounds();
Point2D centerOffset = new Point2D.Double(bounds.getCenterX(), bounds.getCenterY());
orient.pureRotate().transform(centerOffset, centerOffset);
xPos -= centerOffset.getX();
yPos -= centerOffset.getY();
}
String name = plNode.nodeName;
if (name == null && plNode.originalNode != null && !plNode.originalNode.getNameKey().isTempname())
name = plNode.originalNode.getName();
NodeInst ni = NodeInst.makeInstance(np, ep, new Point2D.Double(xPos, yPos), np.getDefWidth(ep),
np.getDefHeight(ep), newCell, orient, name, plNode.getTechBits());
if (ni == null)
System.out.println("Placement failed to create node");
else {
if (plNode.isTerminal())
ni.setLocked();
if (plNode.originalNode != null && !plNode.originalNode.getNameKey().isTempname())
ni.setTextDescriptor(NodeInst.NODE_NAME, plNode.originalNode.getTextDescriptor(NodeInst.NODE_NAME));
placedNodes.put(plNode, ni);
namedPlacedNodes.put(ni.getName(), ni);
}
if (plNode.addedVariables != null) {
for (String varName : plNode.addedVariables.keySet()) {
Object value = plNode.addedVariables.get(varName);
Variable.Key key = Variable.newKey(varName);
Variable var = ni.newDisplayVar(key, value, ep);
if (key == Schematics.SCHEM_RESISTANCE) {
ni.setTextDescriptor(
key,
var.getTextDescriptor().withOff(0, 0.5)
.withDispPart(TextDescriptor.DispPos.VALUE));
} else if (key == Schematics.ATTR_WIDTH) {
ni.setTextDescriptor(key, var.getTextDescriptor().withOff(0.5, -1).withRelSize(1)
.withDispPart(TextDescriptor.DispPos.VALUE));
} else if (key == Schematics.ATTR_LENGTH) {
ni.setTextDescriptor(key, var.getTextDescriptor().withOff(-0.5, -1).withRelSize(0.5)
.withDispPart(TextDescriptor.DispPos.VALUE));
} else {
ni.setTextDescriptor(key,
var.getTextDescriptor().withDispPart(TextDescriptor.DispPos.VALUE));
}
}
}
}
// place an icon if requested
if (iconToPlace != null) {
ERectangle bounds = newCell.getBounds();
EPoint center = new EPoint(bounds.getMaxX() + iconToPlace.getDefWidth(ep), bounds.getMaxY()
+ iconToPlace.getDefHeight(ep));
NodeInst.makeInstance(iconToPlace, ep, center, iconToPlace.getDefWidth(ep), iconToPlace.getDefHeight(ep),
newCell);
}
// place exports in the new cell
for (PlacementExport plExport : exportsToPlace) {
PlacementPort plPort = plExport.getPort();
String exportName = plExport.getName();
PlacementNode plNode = (PlacementNode) plPort.getPlacementNode();
NodeInst newNI = placedNodes.get(plNode);
if (newNI == null)
continue;
PortInst portToExport = newNI.findPortInstFromProto(plPort.getPortProto());
Export.newInstance(newCell, portToExport, exportName, ep, plExport.getCharacteristic());
}
ImmutableArcInst a = Generic.tech().unrouted_arc.getDefaultInst(ep);
long gridExtend = a.getGridExtendOverMin();
for (PlacementNetwork plNet : allNetworks) {
List connections;
connections = getOptimalConnections(plNet);
optimalConnections.put(plNet, connections);
for(SteinerTreePortPair pc : connections)
{
PlacementFrame.PlacementPort pp1 = (PlacementFrame.PlacementPort)pc.getPort1();
PlacementPort thisPp1 = (PlacementPort)pp1;
PlacementNode plNode1 = (PlacementNode)pp1.getPlacementNode();
NodeInst newNi1 = placedNodes.get(plNode1);
PortInst thisPi1 = newNi1.findPortInstFromProto(thisPp1.getPortProto());
EPoint pt1 = thisPi1.getCenter();
PlacementFrame.PlacementPort pp2 = (PlacementFrame.PlacementPort)pc.getPort2();
PlacementNode plNode2 = (PlacementNode)pp2.getPlacementNode();
PlacementPort thisPp2 = (PlacementPort)pp2;
NodeInst newNi2 = placedNodes.get(plNode2);
PortInst thisPi2 = newNi2.findPortInstFromProto(thisPp2.getPortProto());
EPoint pt2 = thisPi2.getCenter();
TextDescriptor td = ep.getArcTextDescriptor();
ArcInst.newInstanceNoCheck(newCell, Generic.tech().unrouted_arc, null, td, thisPi1, thisPi2,
pt1, pt2, gridExtend, ArcInst.DEFAULTANGLE, a.flags);
}
}
if (timer != null)
{
timer.end();
if (!quiet) System.out.println("\t(took " + timer + ")");
}
return newCell;
}
public static Map getPlacementMap() { return namedPlacedNodes; }
private static class PlacementSteinerTree extends SteinerTree
{
private boolean isRail;
public PlacementSteinerTree(List portList, boolean isRail)
{
super(portList);
this.isRail = isRail;
}
public SteinerTreePortPair makeTreeBranch(SteinerTreePort p1, SteinerTreePort p2)
{
return new PlacementConnection(p1, p2, isRail);
}
}
private static final boolean NEWWAY = false;
/**
* Method to return a list of segments that must be run to create a network.
* Finds the shortest set of segments.
* @param plNet the PlacementNetwork being evaluated.
* @return a List of SteinerTreePortPair objects with port pairs.
*/
public static List getOptimalConnections(PlacementNetwork plNet)
{
List ports = new ArrayList();
for (PlacementFrame.PlacementPort plPort : plNet.getPortsOnNet())
ports.add(plPort);
if (NEWWAY)
{
PlacementSteinerTree st = new PlacementSteinerTree(ports, plNet.isOnRail());
return st.getTreeBranches();
} else
{
// first find the closest two ports
double shortest = Double.MAX_VALUE;
int i1 = -1, i2 = -1;
for(int i=1; i equiv = ((PlacementNode)nI).getEquivalents((PlacementPort)pI);
for(int j=0; j connections = new ArrayList();
if (i1 < 0 || i2 < 0) return connections;
PlacementFrame.PlacementPort e1 = (PlacementFrame.PlacementPort)ports.get(i1);
PlacementFrame.PlacementNode e1n = e1.getPlacementNode();
PlacementFrame.PlacementPort e2 = (PlacementFrame.PlacementPort)ports.get(i2);
PlacementFrame.PlacementNode e2n = e2.getPlacementNode();
// add the shortest connection to the list
boolean isRail = plNet.isOnRail();
PlacementConnection pc = new PlacementConnection(e1, e2, isRail);
connections.add(pc);
ports.remove(Math.max(i1, i2));
ports.remove(Math.min(i1, i2));
Set equiv = ((PlacementNode)e1n).getEquivalents((PlacementPort)e1);
if (equiv != null) for(PlacementPort pp : equiv) ports.remove(pp);
equiv = ((PlacementNode)e2n).getEquivalents((PlacementPort)e2);
if (equiv != null) for(PlacementPort pp : equiv) ports.remove(pp);
// find shortest path through them
while (ports.size() > 0)
{
double e1Dist = Double.MAX_VALUE, e2Dist = Double.MAX_VALUE;
int ei1 = -1, ei2 = -1;
for(int i=0; i e2Dist)
{
// add e2 to second end
PlacementConnection pCon = new PlacementConnection(e2, ports.get(ei2), isRail);
connections.add(pCon);
ports.remove(ei2);
e2 = (PlacementFrame.PlacementPort)pCon.getPort2();
equiv = ((PlacementNode)e2.getPlacementNode()).getEquivalents((PlacementPort)e2);
if (equiv != null) for(PlacementPort pp : equiv) ports.remove(pp);
} else
{
// add e1 to first end
PlacementConnection pCon = new PlacementConnection(ports.get(ei1), e1, isRail);
connections.add(pCon);
ports.remove(ei1);
e1 = (PlacementFrame.PlacementPort)pCon.getPort1();
equiv = ((PlacementNode)e1.getPlacementNode()).getEquivalents((PlacementPort)e1);
if (equiv != null) for(PlacementPort pp : equiv) ports.remove(pp);
}
}
return connections;
}
}
}