![JAR search and dependency download from the Maven repository](/logo.png)
com.sun.electric.tool.placement.Placement Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Placement.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.ImmutableExport;
import com.sun.electric.database.geometry.Poly;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Export;
import com.sun.electric.database.hierarchy.View;
import com.sun.electric.database.network.Netlist;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.prototype.NodeProto;
import com.sun.electric.database.prototype.PortProto;
import com.sun.electric.database.text.PrefPackage;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.UserInterface;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.JobException;
import com.sun.electric.tool.Tool;
import com.sun.electric.tool.placement.PlacementAdapter.PlacementExport;
import com.sun.electric.tool.placement.PlacementAdapter.PlacementNode;
import com.sun.electric.tool.placement.PlacementAdapter.PlacementPort;
import com.sun.electric.tool.placement.PlacementFrame.PlacementNetwork;
import com.sun.electric.tool.user.User;
import com.sun.electric.tool.user.ui.WindowFrame;
import com.sun.electric.util.CollectionFactory;
import com.sun.electric.util.math.Orientation;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.prefs.Preferences;
/**
* Class to place cells for better routing.
*/
public class Placement extends Tool
{
/** the Placement tool. */ private static Placement tool = new Placement();
/**
* The constructor sets up the Placement tool.
*/
private Placement()
{
super("placement");
}
/**
* Method to initialize the Placement tool.
*/
public void init() {}
/**
* Method to retrieve the singleton associated with the Placement tool.
* @return the Placement tool.
*/
public static Placement getPlacementTool() { return tool; }
/**
* Method to run placement on the current cell in a new Job.
*/
public static void placeCurrentCell()
{
// get cell information
UserInterface ui = Job.getUserInterface();
Cell cell = ui.needCurrentCell();
if (cell == null) return;
PlacementPreferences pp = new PlacementPreferences(false);
new PlaceJob(cell, pp);
}
/**
* Method to run floor planning and placement on the current cell in a new Job.
*/
public static void floorplanCurrentCell()
{
// get cell information
UserInterface ui = Job.getUserInterface();
Cell cell = ui.needCurrentCell();
if (cell == null) return;
PlacementPreferences pp = new PlacementPreferences(false);
pp.placementAlgorithm = PlacementAdapter.GEN.getAlgorithmName();
new PlaceJob(cell, pp);
}
/**
* Class to do placement in a Job.
*/
private static class PlaceJob extends Job
{
private Cell cell;
private PlacementPreferences prefs;
private Cell newCell;
private PlaceJob(Cell cell, PlacementPreferences prefs)
{
super("Place cells", User.getUserTool(), Job.Type.CHANGE, null, null, Job.Priority.USER);
this.cell = cell;
this.prefs = prefs;
startJob();
}
public boolean doIt() throws JobException
{
newCell = placeCellNoJob(cell, getEditingPreferences(), prefs, false, this);
PlacementFrame pla = getCurrentPlacementAlgorithm(prefs);
Cell redispCell = pla.getRedispCell();
if (redispCell != null) newCell = redispCell;
fieldVariableChanged("newCell");
return true;
}
public void terminateOK()
{
if (newCell != null)
{
WindowFrame wf = WindowFrame.getCurrentWindowFrame();
if (User.isShowCellsInNewWindow()) wf = null;
if (wf == null) wf = WindowFrame.createEditWindow(newCell);
wf.setCellWindow(newCell, null);
}
}
}
/**
* Entry point to do Placement of a Cell and create a new, placed Cell.
* Gathers the requirements for Placement into a collection of shadow
* objects (PlacementNode, PlacementPort, PlacementNetwork, and
* PlacementExport). Then invokes the alternate version of "doPlacement()"
* that works from shadow objects.
* @param cell the Cell to place. Objects in that Cell will be reorganized in and placed in a new Cell.
* @param ep EditingPreferences
* @param prefs placement preferences
* @param quiet true to suppress messages.
* @param job the Job (for detecting abort).
* @return the new Cell with the placement results.
*/
public static Cell placeCellNoJob(Cell cell, EditingPreferences ep, PlacementPreferences prefs, boolean quiet, Job job)
{
if (!quiet)
{
Job.getUserInterface().startProgressDialog("Placing cell " + cell.describe(false), null);
Job.getUserInterface().setProgressNote("Acquiring netlist...");
}
System.out.println();
PlacementFrame pla = getCurrentPlacementAlgorithm(prefs);
// get network information for the Cell
Netlist netList = cell.getNetlist();
if (netList == null) {
System.out.println("Sorry, a deadlock aborted routing (network information unavailable). Please try again");
return null;
}
// convert nodes in the Cell into PlacementNode objects
NodeProto iconToPlace = null;
List nodesToPlace = CollectionFactory.createArrayList();
Map> convertedNodes = CollectionFactory.createHashMap();
List exportsToPlace = CollectionFactory.createArrayList();
int total = cell.getNumNodes();
if (!quiet)
{
Job.getUserInterface().setProgressNote("Converting " + total + " nodes");
Job.getUserInterface().setProgressValue(0);
}
int soFar = 0;
for (Iterator it = cell.getNodes(); it.hasNext();)
{
soFar++;
if (!quiet && (soFar%100) == 0) Job.getUserInterface().setProgressValue(soFar * 100 / total);
NodeInst ni = it.next();
if (ni.isIconOfParent()) {
iconToPlace = ni.getProto();
continue;
}
boolean validNode = ni.isCellInstance();
if (!validNode) {
if (ni.getProto().getTechnology() != Generic.tech()) {
PrimitiveNode.Function fun = ni.getFunction();
if (fun != PrimitiveNode.Function.CONNECT && fun != PrimitiveNode.Function.CONTACT && !fun.isPin())
validNode = true;
}
if (ni.hasExports())
validNode = true;
}
if (validNode) {
// make a list of PlacementPorts on this NodeInst
NodeProto np = ni.getProto();
List pl = new ArrayList();
Map placedPorts = new HashMap();
if (ni.isCellInstance()) {
Cell instCell = (Cell)np;
for (Iterator eIt = instCell.getExports(); eIt.hasNext();) {
Export e = eIt.next();
Poly poly = e.getPoly();
double pX = poly.getCenterX(), pY = poly.getCenterY();
// the next two lines were added by SMR to make it right
pX -= instCell.getBounds().getCenterX();
pY -= instCell.getBounds().getCenterY();
PlacementPort plPort = new PlacementPort(pX, pY, e);
pl.add(plPort);
placedPorts.put(e, plPort);
}
} else {
NodeInst niDummy = NodeInst.makeDummyInstance(np, ep);
for (Iterator pIt = niDummy.getPortInsts(); pIt.hasNext();) {
PortInst pi = pIt.next();
Poly poly = pi.getPoly();
double offX = poly.getCenterX() - niDummy.getTrueCenterX();
double offY = poly.getCenterY() - niDummy.getTrueCenterY();
PlacementPort plPort = new PlacementPort(offX, offY, pi.getPortProto());
pl.add(plPort);
placedPorts.put(pi.getPortProto(), plPort);
}
}
// add to the list of PlacementExports
for (Iterator eIt = ni.getExports(); eIt.hasNext();) {
Export e = eIt.next();
PlacementPort plPort = placedPorts.get(e.getOriginalPort().getPortProto());
PlacementExport plExport = new PlacementExport(plPort, e.getName(), e.getCharacteristic());
exportsToPlace.add(plExport);
}
// make the PlacementNode for this NodeInst
PlacementNode plNode = new PlacementNode(ni, null, null, ni.getTechSpecific(), np.getDefWidth(ep),
np.getDefHeight(ep), pl, ni.isLocked());
nodesToPlace.add(plNode);
for (PlacementFrame.PlacementPort plPort : pl)
plPort.setPlacementNode(plNode);
// mark equivalent ports
for(int i=1; i portInstsByNetwork = null;
if (cell.getView() != View.SCHEMATIC)
portInstsByNetwork = netList.getPortInstsByNetwork();
List allNetworks = new ArrayList();
total = netList.getNumNetworks();
if (!quiet)
{
Job.getUserInterface().setProgressNote("Converting " + total + " nets");
Job.getUserInterface().setProgressValue(0);
}
soFar = 0;
for (Iterator it = netList.getNetworks(); it.hasNext();)
{
soFar++;
if (!quiet && (soFar%100) == 0) Job.getUserInterface().setProgressValue(soFar * 100 / total);
Network net = it.next();
List portsOnNet = new ArrayList();
PortInst[] portInsts = null;
if (portInstsByNetwork != null)
portInsts = portInstsByNetwork.get(net);
else {
List portList = new ArrayList();
for (Iterator pIt = net.getPorts(); pIt.hasNext();)
portList.add(pIt.next());
portInsts = portList.toArray(new PortInst[] {});
}
for (int i = 0; i < portInsts.length; i++) {
PortInst pi = portInsts[i];
NodeInst ni = pi.getNodeInst();
PortProto pp = pi.getPortProto();
Map convertedPorts = convertedNodes.get(ni);
if (convertedPorts == null)
continue;
PlacementPort plPort = convertedPorts.get(pp);
if (plPort != null)
portsOnNet.add(plPort);
}
if (portsOnNet.size() > 1) {
boolean isRail = ImmutableExport.isNamedPower(net.getName()) || ImmutableExport.isNamedGround(net.getName());
PlacementNetwork plNet = new PlacementNetwork(portsOnNet, isRail);
for (PlacementFrame.PlacementPort plPort : portsOnNet)
plPort.setPlacementNetwork(plNet);
allNetworks.add(plNet);
}
}
// do the placement from the shadow objects
if (!quiet)
Job.getUserInterface().stopProgressDialog();
pla.setOriginalCell(cell);
pla.setFailure(false);
Cell newCell = PlacementAdapter.doPlacement(pla, cell.getLibrary(), cell.noLibDescribe(), nodesToPlace,
allNetworks, exportsToPlace, iconToPlace, ep, prefs, quiet, job);
return newCell;
}
public static class PlacementPreferences extends PrefPackage implements Serializable
{
private static final String PLACEMENT_NODE = "tool/placement";
/** The name of the Placement algorithm to use. The default is "Min-Cut". */
@StringPref(node = PLACEMENT_NODE, key = "AlgorithmName", factory = "Min-Cut")
public String placementAlgorithm;
private Object[][] values;
public PlacementPreferences(boolean factory)
{
super(factory);
Preferences prefs = (factory ? getFactoryPrefRoot() : getPrefRoot()).node(PLACEMENT_NODE);
values = new Object[PlacementAdapter.placementAlgorithms.length][];
for (int i = 0; i < values.length; i++) {
PlacementFrame pf = PlacementAdapter.placementAlgorithms[i];
values[i] = new Object[pf.getParameters().size()];
for (int j = 0; j < pf.getParameters().size(); j++) {
PlacementFrame.PlacementParameter par = pf.getParameters().get(j);
String key = pf.getAlgorithmName() + "-" + par.key;
Object value;
switch (par.getType()) {
case PlacementFrame.PlacementParameter.TYPEINTEGER:
value = Integer.valueOf(prefs.getInt(key, ((Integer)par.factoryValue).intValue()));
break;
case PlacementFrame.PlacementParameter.TYPESTRING:
value = String.valueOf(prefs.get(key, (String)par.factoryValue));
break;
case PlacementFrame.PlacementParameter.TYPEDOUBLE:
value = Double.valueOf(prefs.getDouble(key, ((Double)par.factoryValue).doubleValue()));
break;
case PlacementFrame.PlacementParameter.TYPEBOOLEAN:
value = Boolean.valueOf(prefs.getBoolean(key, ((Boolean)par.factoryValue).booleanValue()));
break;
default:
throw new AssertionError();
}
if (value.equals(par.factoryValue)) {
value = par.factoryValue;
}
values[i][j] = value;
}
}
}
/**
* Store annotated option fields of the subclass into the speciefied Preferences subtree.
* @param prefRoot the root of the Preferences subtree.
* @param removeDefaults remove from the Preferences subtree options which have factory default value.
*/
@Override
protected void putPrefs(Preferences prefRoot, boolean removeDefaults) {
super.putPrefs(prefRoot, removeDefaults);
Preferences prefs = prefRoot.node(PLACEMENT_NODE);
assert values.length == PlacementAdapter.placementAlgorithms.length;
for (int i = 0; i < values.length; i++) {
PlacementFrame pf = PlacementAdapter.placementAlgorithms[i];
assert values[i].length == pf.getParameters().size();
for (int j = 0; j < pf.getParameters().size(); j++) {
PlacementFrame.PlacementParameter par = pf.getParameters().get(j);
String key = pf.getAlgorithmName() + "-" + par.key;
Object v = values[i][j];
if (removeDefaults && v.equals(par.factoryValue)) {
prefs.remove(key);
} else {
switch (par.getType()) {
case PlacementFrame.PlacementParameter.TYPEINTEGER:
prefs.putInt(key, ((Integer)v).intValue());
break;
case PlacementFrame.PlacementParameter.TYPESTRING:
prefs.put(key, (String)v);
break;
case PlacementFrame.PlacementParameter.TYPEDOUBLE:
prefs.putDouble(key, ((Double)v).doubleValue());
break;
case PlacementFrame.PlacementParameter.TYPEBOOLEAN:
prefs.putBoolean(key, ((Boolean)v).booleanValue());
break;
default:
throw new AssertionError();
}
}
}
}
}
public Object getParameter(PlacementFrame.PlacementParameter par) {
int i = indexOfFrame(par);
PlacementFrame pf = PlacementAdapter.placementAlgorithms[i];
int j = indexOfParameter(pf, par.key);
return values[i][j];
}
public void setParameter(PlacementFrame.PlacementParameter par, Object value) {
int i = indexOfFrame(par);
PlacementFrame pf = PlacementAdapter.placementAlgorithms[i];
int j = indexOfParameter(pf, par.key);
Object oldValue = values[i][j];
if (oldValue.equals(value)) {
return;
}
assert value.getClass() == par.factoryValue.getClass();
if (value.equals(par.factoryValue))
value = par.factoryValue;
values[i][j] = value;
}
private int indexOfFrame(PlacementFrame.PlacementParameter par) {
PlacementFrame rf = par.getOwner();
for (int i = 0; i < PlacementAdapter.placementAlgorithms.length; i++) {
if (rf.getClass() == PlacementAdapter.placementAlgorithms[i].getClass()) return i;
}
return -1;
}
private static int indexOfParameter(PlacementFrame pf, String parameterKey) {
for (int j = 0; j < pf.getParameters().size(); j++) {
if (parameterKey.equals(pf.getParameters().get(j).key))
return j;
}
return -1;
}
}
/**
* Method to return the current Placement algorithm.
* This is a requested subclass of PlacementFrame.
* @return the current Placement algorithm.
*/
public static PlacementFrame getCurrentPlacementAlgorithm(PlacementPreferences prefs)
{
String algName = prefs.placementAlgorithm;
for(PlacementFrame pfObj : PlacementAdapter.getPlacementAlgorithms())
{
if (algName.equals(pfObj.getAlgorithmName())) return pfObj;
}
return PlacementAdapter.getPlacementAlgorithms()[0];
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy