/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Routing.java
*
* Copyright (c) 2003 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.routing;
import com.sun.electric.database.CellBackup;
import com.sun.electric.database.CellRevision;
import com.sun.electric.database.CellTree;
import com.sun.electric.database.ImmutableArcInst;
import com.sun.electric.database.ImmutableNodeInst;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.geometry.EPoint;
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.Nodable;
import com.sun.electric.database.hierarchy.View;
import com.sun.electric.database.id.CellId;
import com.sun.electric.database.id.PortProtoId;
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.Name;
import com.sun.electric.database.text.Pref;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.topology.Connection;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.PortInst;
import com.sun.electric.database.variable.EditWindow_;
import com.sun.electric.database.variable.UserInterface;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.PrimitivePort;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.JobException;
import com.sun.electric.tool.Listener;
import com.sun.electric.tool.user.User;
import java.awt.geom.Point2D;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This is the Routing tool.
*/
public class Routing extends Listener
{
/**
* Class to describe recent activity that pertains to routing.
*/
public static class Activity
{
int numCreatedArcs, numCreatedNodes;
ImmutableArcInst [] createdArcs = new ImmutableArcInst[3];
CellId createdArcsParents [] = new CellId[3];
ImmutableNodeInst [] createdNodes = new ImmutableNodeInst[3];
int numDeletedArcs, numDeletedNodes;
ImmutableArcInst deletedArc;
CellId deletedArcParent;
PortProtoId [] deletedPorts = new PortProtoId[2];
Activity()
{
}
}
private Activity current, past = null;
private boolean checkAutoStitch = false;
/** the Routing tool. */ private static Routing tool = new Routing();
/****************************** TOOL INTERFACE ******************************/
/**
* The constructor sets up the Routing tool.
*/
private Routing()
{
super("routing");
}
/**
* Method to initialize the Routing tool.
*/
public void init()
{
setOn();
}
/**
* Method to retrieve the singleton associated with the Routing tool.
* @return the Routing tool.
*/
public static Routing getRoutingTool() { return tool; }
/**
* Handles database changes of a Job.
* @param oldSnapshot database snapshot before Job.
* @param newSnapshot database snapshot after Job and constraint propagation.
* @param undoRedo true if Job was Undo/Redo job.
*/
public void endBatch(Snapshot oldSnapshot, Snapshot newSnapshot, boolean undoRedo)
{
if (undoRedo) return;
if (newSnapshot.tool == tool) return;
current = new Activity();
checkAutoStitch = false;
for (CellId cellId: newSnapshot.getChangedCells(oldSnapshot)) {
CellBackup oldBackup = oldSnapshot.getCell(cellId);
if (oldBackup == null) continue; // Don't route in new cells
CellBackup newBackup = newSnapshot.getCell(cellId);
if (newBackup == null) continue;
if (oldBackup == newBackup) continue;
CellRevision oldRevision = oldBackup.cellRevision;
CellRevision newRevision = newBackup.cellRevision;
ArrayList<ImmutableNodeInst> oldNodes = new ArrayList<ImmutableNodeInst>();
for (ImmutableNodeInst n: oldRevision.nodes) {
while (n.nodeId >= oldNodes.size()) oldNodes.add(null);
oldNodes.set(n.nodeId, n);
}
ArrayList<ImmutableArcInst> oldArcs = new ArrayList<ImmutableArcInst>();
for (ImmutableArcInst a: oldRevision.arcs) {
while (a.arcId >= oldArcs.size()) oldArcs.add(null);
oldArcs.set(a.arcId, a);
}
BitSet newNodes = new BitSet();
for (ImmutableNodeInst d: newRevision.nodes) {
newNodes.set(d.nodeId);
ImmutableNodeInst oldD = d.nodeId < oldNodes.size() ? oldNodes.get(d.nodeId) : null;
if (oldD == null) {
if (current.numCreatedNodes < 3)
current.createdNodes[current.numCreatedNodes++] = d;
} else if (oldD != d) {
checkAutoStitch = true;
}
}
BitSet newArcs = new BitSet();
for (ImmutableArcInst d: newRevision.arcs) {
newArcs.set(d.arcId);
ImmutableArcInst oldD = d.arcId < oldArcs.size( ) ? oldArcs.get(d.arcId) : null;
if (oldD == null) {
if (current.numCreatedArcs < 3) {
current.createdArcsParents[current.numCreatedArcs] = cellId;
current.createdArcs[current.numCreatedArcs++] = d;
}
}
}
for (ImmutableNodeInst nid: oldRevision.nodes) {
if (!newNodes.get(nid.nodeId))
current.numDeletedNodes++;
}
for (ImmutableArcInst aid: oldRevision.arcs) {
if (!newArcs.get(aid.arcId)) {
if (current.numDeletedArcs == 0) {
current.deletedArc = aid;
current.deletedArcParent = cellId;
current.deletedPorts[0] = aid.headPortId;
current.deletedPorts[1] = aid.tailPortId;
}
current.numDeletedArcs++;
}
}
}
if (current.numCreatedArcs > 0 || current.numCreatedNodes > 0 || current.deletedArc != null)
{
past = current;
if (isMimicStitchOn())
{
MimicStitch.mimicStitch(false);
return;
}
}
if (checkAutoStitch && isAutoStitchOn())
{
AutoStitch.autoStitch(false, false);
}
// JFluid results
current = null;
}
/****************************** COMMANDS ******************************/
/**
* Method to mimic the currently selected ArcInst.
*/
public void mimicSelected()
{
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.getCurrentEditWindow_();
if (wnd == null) return;
ArcInst ai = (ArcInst)wnd.getOneElectricObject(ArcInst.class);
if (ai == null) return;
past = new Activity();
past.createdArcsParents[past.numCreatedArcs] = ai.getParent().getId();
past.createdArcs[past.numCreatedArcs++] = ai.getD();
MimicStitch.mimicStitch(true);
}
/**
* Method to convert the current network(s) to an unrouted wire.
*/
public static void unrouteCurrent()
{
// see what is highlighted
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.getCurrentEditWindow_();
if (wnd == null) return;
Cell cell = wnd.getCell();
Set<Network> nets = wnd.getHighlightedNetworks();
if (nets.size() == 0)
{
System.out.println("Must select networks to unroute");
return;
}
new UnrouteJob(cell, nets);
}
/**
* Method to determine the preferred ArcProto to use for routing.
* Examines preferences in the Routing tool and User interface.
* @return the preferred ArcProto to use for routing.
*/
public static ArcProto getPreferredRoutingArcProto()
{
ArcProto preferredArc = null;
String preferredName = getPreferredRoutingArc();
if (preferredName.length() > 0) preferredArc = ArcProto.findArcProto(preferredName);
if (preferredArc == null)
{
// see if there is a default user arc
ArcProto curAp = User.getUserTool().getCurrentArcProto();
if (curAp != null) preferredArc = curAp;
}
return preferredArc;
}
private static class UnrouteJob extends Job
{
private Cell cell;
private Set<Network> nets;
private List<ArcInst> highlightThese;
private UnrouteJob(Cell cell, Set<Network> nets)
{
super("Unroute", Routing.tool, Job.Type.CHANGE, null, null, Job.Priority.USER);
this.cell = cell;
this.nets = nets;
startJob();
}
public boolean doIt() throws JobException
{
// convert requested nets
Netlist netList = cell.getNetlist();
if (netList == null)
throw new JobException("Sorry, a deadlock aborted unrouting (network information unavailable). Please try again");
highlightThese = new ArrayList<ArcInst>();
// make arrays of what to unroute
Map<Network,ArcInst[]> arcMap = null;
if (cell.getView() != View.SCHEMATIC) arcMap = netList.getArcInstsByNetwork();
int total = nets.size();
Network [] netsToUnroute = new Network[total];
ArrayList<UnroutePort[]> netEnds = new ArrayList<UnroutePort[]>();
Set<NodeInst> deleteAllNodes = new HashSet<NodeInst>();
Set<ArcInst> deleteAllArcs = new HashSet<ArcInst>();
int i = 0;
for(Network net : nets)
{
netsToUnroute[i] = net;
Set<ArcInst> arcs = new HashSet<ArcInst>();
Set<NodeInst> nodes = new HashSet<NodeInst>();
List<Connection> netCons = findNetEnds(net, arcMap, arcs, nodes, netList, false);
UnroutePort[] netUnroutePorts = new UnroutePort[netCons.size()];
for (int j = 0; j < netCons.size(); j++) {
netUnroutePorts[j] = new UnroutePort(netCons.get(j));
}
netEnds.add(netUnroutePorts);
for(NodeInst ni : nodes) deleteAllNodes.add(ni);
for(ArcInst ai : arcs) deleteAllArcs.add(ai);
i++;
}
// delete all arcs and nodes that are being unrouted
cell.killArcs(deleteAllArcs);
cell.killNodes(deleteAllNodes);
// do the unrouting
for(int j=0; j<total; j++)
{
if (makeUnroutedNet(netsToUnroute[j], netEnds.get(j), netList, highlightThese)) break;
}
fieldVariableChanged("highlightThese");
return true;
}
public void terminateOK()
{
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.getCurrentEditWindow_();
if (wnd == null) return;
wnd.clearHighlighting();
for(ArcInst ai : highlightThese)
wnd.addElectricObject(ai, ai.getParent());
wnd.finishedHighlighting();
}
private static class UnroutePort {
final PortInst pi;
final EPoint center;
UnroutePort(Connection con) {
pi = con.getPortInst();
center = pi.getCenter();
}
}
private static boolean makeUnroutedNet(Network net, UnroutePort[] netEnds, Netlist netList, List<ArcInst> highlightThese)
{
Cell cell = net.getNetlist().getCell();
ImmutableArcInst a = Generic.tech().unrouted_arc.getDefaultInst(cell.getEditingPreferences());
long gridExtend = a.getGridExtendOverMin();
// now create the new unrouted wires
// double wid = Generic.tech().unrouted_arc.getDefaultLambdaBaseWidth();
int count = netEnds.length;
if (count >= 1000)
{
// too much work to make the solution look pretty: just radiate all connections from a center point
double x = 0, y = 0;
for(int i=0; i<count; i++)
{
x += netEnds[i].center.getX();
y += netEnds[i].center.getY();
}
EPoint center = EPoint.fromLambda(x/count, y/count);
PrimitiveNode centerNp = Generic.tech().unroutedPinNode;
double width = centerNp.getDefWidth();
double height = centerNp.getDefHeight();
NodeInst centerNi = NodeInst.makeInstance(centerNp, center, width, height, net.getParent());
PortInst tail = centerNi.getOnlyPortInst();
for(int i=0; i<count; i++)
{
PortInst head = netEnds[i].pi;
EPoint headP = netEnds[i].center;
ArcInst ai = ArcInst.newInstance(cell, Generic.tech().unrouted_arc, null, null,
head, tail, headP, center, gridExtend, 0, a.flags);
// ArcInst ai = ArcInst.makeInstanceBase(Generic.tech().unrouted_arc, wid, head, tail);
if (ai == null)
{
System.out.println("Could not create unrouted arc");
return true;
}
highlightThese.add(ai);
}
} else
{
// do a poor-man's traveling-salesman solution to make the unrouted nets look good
int [] covered = new int[count];
for(int i=0; i<count; i++) covered[i] = 0;
for(int first=0; ; first++)
{
boolean found = true;
double bestdist = 0;
int besti = 0, bestj = 0;
for(int i=0; i<count; i++)
{
for(int j=i+1; j<count; j++)
{
if (first != 0)
{
if (covered[i] + covered[j] != 1) continue;
}
double dist = netEnds[i].center.distance(netEnds[j].center);
if (!found && dist >= bestdist) continue;
found = false;
bestdist = dist;
besti = i;
bestj = j;
}
}
if (found) break;
covered[besti] = covered[bestj] = 1;
PortInst head = netEnds[besti].pi;
PortInst tail = netEnds[bestj].pi;
EPoint headP = netEnds[besti].center;
EPoint tailP = netEnds[bestj].center;
ArcInst ai = ArcInst.newInstance(cell, Generic.tech().unrouted_arc, null, null,
head, tail, headP, tailP, gridExtend, 0, a.flags);
// ArcInst ai = ArcInst.makeInstanceBase(Generic.tech().unrouted_arc, wid, head, tail);
if (ai == null)
{
System.out.println("Could not create unrouted arc");
return true;
}
highlightThese.add(ai);
}
}
return false;
}
}
/**
* Method to find the endpoints of a network.
* @param net the network to "unroute".
* @param arcMap a shortcut to finding arcs on a network (if not null).
* @param arcsToDelete a HashSet of arcs that should be deleted.
* @param nodesToDelete a HashSet of nodes that should be deleted.
* @param netList the netlist for the current cell.
* @param mustBeUnrouted true to include all items on the network in the list of arcs/nodes to delete.
* False to only include items from the generic technology or pins with no exports.
* @return a List of Connection (PortInst/Point2D pairs) that should be wired together.
*/
public static List<Connection> findNetEnds(Network net, Map<Network,ArcInst[]> arcMap, Set<ArcInst> arcsToDelete, Set<NodeInst> nodesToDelete,
Netlist netList, boolean mustBeUnrouted)
{
// initialize
List<Connection> endList = new ArrayList<Connection>();
Map<NodeInst,List<Connection>> endListByNode = new HashMap<NodeInst,List<Connection>>();
// look at every arc and see if it is part of the network
ArcInst[] arcsOnNet = null;
if (arcMap != null) arcsOnNet = arcMap.get(net); else
{
List<ArcInst> arcList = new ArrayList<ArcInst>();
for(Iterator<ArcInst> aIt = net.getArcs(); aIt.hasNext(); ) arcList.add(aIt.next());
arcsOnNet = arcList.toArray(new ArcInst[]{});
}
for(ArcInst ai : arcsOnNet)
{
if (mustBeUnrouted && ai.getProto() != Generic.tech().unrouted_arc) continue;
arcsToDelete.add(ai);
// see if an end of the arc is a network "end"
for(int i=0; i<2; i++)
{
Connection thisCon = ai.getConnection(i);
PortInst pi = thisCon.getPortInst();
NodeInst ni = pi.getNodeInst();
// see if this arc end is a "termination point" (on cell, exported, or not further connected)
boolean term = true;
if (!ni.hasExports() && !ni.isCellInstance())
{
PrimitiveNode.Function fun = ni.getFunction();
if (ni.getNumConnections() != 1 && (fun == PrimitiveNode.Function.PIN ||
fun == PrimitiveNode.Function.CONTACT || fun == PrimitiveNode.Function.CONNECT)) term = false; else
{
// see if this primitive connects to other unconnected nets
for(Iterator<Connection> cIt = ni.getConnections(); cIt.hasNext(); )
{
Connection con = cIt.next();
ArcInst conAi = con.getArc();
if (mustBeUnrouted && conAi.getProto() != Generic.tech().unrouted_arc) continue;
if (conAi != ai && netList.getNetwork(conAi, 0) == net) { term = false; break; }
}
}
}
// if a termination point, consider it for the list of net ends
if (term)
{
// see if it is already in the list, connection-wise
boolean found = false;
Netlist nl = null;
List<Connection> consOnNode = endListByNode.get(ni);
if (consOnNode != null)
{
for(Connection lCon : consOnNode)
{
PortInst otherPI = lCon.getPortInst();
if (otherPI == pi) { found = true; break; }
// connecting to another port on a node: ignore if they are connected internally
if (ni.isCellInstance())
{
if (nl == null) nl = ((Cell)ni.getProto()).getNetlist();
if (nl == null) continue;
Network subNet = nl.getNetwork((Export)pi.getPortProto(), 0);
Network otherSubNet = nl.getNetwork((Export)otherPI.getPortProto(), 0);
if (subNet == otherSubNet) { found = true; break; }
} else
{
PrimitivePort subPP = (PrimitivePort)pi.getPortProto();
PrimitivePort otherSubPP = (PrimitivePort)otherPI.getPortProto();
if (subPP.getTopology() == otherSubPP.getTopology()) { found = true; break; }
}
}
}
if (!found)
{
endList.add(thisCon);
List<Connection> consByNode = endListByNode.get(ni);
if (consByNode == null) endListByNode.put(ni, consByNode = new ArrayList<Connection>());
consByNode.add(thisCon);
}
} else
{
// not a network end: mark the node for removal
boolean deleteNode = !mustBeUnrouted;
if (ni.getProto().getFunction().isPin())
deleteNode = true;
if (deleteNode) nodesToDelete.add(ni);
}
}
}
return endList;
}
/**
* Method to return the most recent routing activity.
*/
public Activity getLastActivity() { return past; }
/****************************** SUN ROUTER INTERFACE ******************************/
private static boolean sunRouterChecked = false;
private static Class<?> sunRouterClass = null;
private static Method sunRouterMethod;
/**
* Method to tell whether the Sun Router is available.
* This is a proprietary tool from Sun Microsystems.
* This method dynamically figures out whether the router is present by using reflection.
* @return true if the Sun Router is available.
*/
public static boolean hasSunRouter()
{
if (!sunRouterChecked)
{
sunRouterChecked = true;
// find the Sun Router class
try
{
sunRouterClass = Class.forName("com.sun.electric.plugins.sunRouter.SunRouter");
} catch (ClassNotFoundException e)
{
sunRouterClass = null;
return false;
}
// find the necessary method on the router class
try
{
sunRouterMethod = sunRouterClass.getMethod("routeCell", new Class[] {Cell.class});
} catch (NoSuchMethodException e)
{
sunRouterClass = null;
return false;
}
}
// if already initialized, return
if (sunRouterClass == null) return false;
return true;
}
/**
* Method to invoke the Sun Router via reflection.
*/
public static void sunRouteCurrentCell()
{
if (!hasSunRouter()) return;
UserInterface ui = Job.getUserInterface();
Cell curCell = ui.needCurrentCell();
if (curCell == null) return;
try
{
sunRouterMethod.invoke(sunRouterClass, new Object[] {curCell});
} catch (Exception e)
{
System.out.println("Unable to run the Sun Router module");
e.printStackTrace(System.out);
}
}
/****************************** COPY / PASTE ROUTING TOPOLOGY ******************************/
private static Cell copiedTopologyCell;
/**
* Method called when the "Copy Routing Topology" command is issued.
* It remembers the topology in the current cell.
*/
public static void copyRoutingTopology()
{
UserInterface ui = Job.getUserInterface();
Cell np = ui.needCurrentCell();
if (np == null) return;
copiedTopologyCell = np;
System.out.println("Cell " + np.describe(true) + " will have its connectivity remembered");
}
/**
* Method called when the "Paste Routing Topology" command is issued.
* It applies the topology of the "copied" cell to the current cell.
*/
public static void pasteRoutingTopology()
{
if (copiedTopologyCell == null)
{
System.out.println("Must copy topology before pasting it");
return;
}
// first validate the source cell
if (!copiedTopologyCell.isLinked())
{
System.out.println("Copied cell is no longer valid");
return;
}
// get the destination cell
UserInterface ui = Job.getUserInterface();
Cell toCell = ui.needCurrentCell();
if (toCell == null) return;
// make sure copy goes to a different cell
if (copiedTopologyCell == toCell)
{
System.out.println("Topology must be copied to a different cell");
return;
}
// do the copy
new CopyRoutingTopology(copiedTopologyCell, toCell);
}
/**
* Class to delete a cell in a new thread.
*/
private static class CopyRoutingTopology extends Job
{
private Cell fromCell, toCell;
protected CopyRoutingTopology(Cell fromCell, Cell toCell)
{
super("Copy Routing Topology", Routing.tool, Job.Type.CHANGE, null, null, Job.Priority.USER);
this.fromCell = fromCell;
this.toCell = toCell;
startJob();
}
public boolean doIt() throws JobException
{
return copyTopology(fromCell, toCell);
}
}
private static class NodeMatch
{
NodeInst ni;
String name;
NodeInst otherNi;
NodeMatch(NodeInst ni, String name)
{
this.ni = ni;
this.name = name;
}
void findEquivalentByName(Cell other)
{
// match by name
String thisName = ni.getName();
for(Iterator<NodeInst> it = other.getNodes(); it.hasNext(); )
{
NodeInst oNi = it.next();
if (oNi.getName().equals(thisName))
{
otherNi = oNi;
return;
}
}
// match by export
if (!ni.isCellInstance() && ni.hasExports())
{
for(Iterator<Export> it = ni.getExports(); it.hasNext(); )
{
Export e = it.next();
String eName = e.getName();
for(Iterator<Export> oIt = other.getExports(); oIt.hasNext(); )
{
Export oE = oIt.next();
if (eName.equalsIgnoreCase(oE.getName()))
{
otherNi = oE.getOriginalPort().getNodeInst();
return;
}
}
}
}
}
}
/**
* Method to copy the routing topology from one cell to another.
* @param fromCell the source of the routing topology.
* @param toCell the destination cell for the routing topology.
* @return true if successful.
*/
public static boolean copyTopology(Cell fromCell, Cell toCell)
{
// make a list of all networks
System.out.println("Copying topology of " + fromCell + " to " + toCell);
Netlist nl = fromCell.getNetlist();
Map<Network,ArcInst[]> arcMap = null;
if (fromCell.getView() != View.SCHEMATIC) arcMap = nl.getArcInstsByNetwork();
// first make a list of all nodes in the "from" cell
Map<NodeInst,List<NodeMatch>> nodeMap = new HashMap<NodeInst,List<NodeMatch>>();
List<NodeMatch> unmatched = new ArrayList<NodeMatch>();
for(Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext(); )
{
NodeInst ni = it.next();
if (ni.getProto() == Generic.tech().cellCenterNode ||
ni.getProto() == Generic.tech().essentialBoundsNode) continue;
// ignore connecting primitives with no exports
if (!ni.isCellInstance() &&!ni.hasExports())
{
PrimitiveNode.Function fun = ni.getFunction();
if (fun == PrimitiveNode.Function.UNKNOWN || fun.isPin() ||
fun.isContact() || fun == PrimitiveNode.Function.CONNECT ||
fun == PrimitiveNode.Function.NODE) continue;
}
// make a list of all equivalent nodes that match this one
if (ni.isIconOfParent()) continue;
List<NodeMatch> matches = new ArrayList<NodeMatch>();
for(Iterator<Nodable> noIt = nl.getNodables(); noIt.hasNext(); )
{
Nodable no = noIt.next();
if (no.getNodeInst() == ni)
{
NodeMatch nm = new NodeMatch(ni, no.getName());
nm.findEquivalentByName(toCell);
if (nm.otherNi == null) unmatched.add(nm);
matches.add(nm);
}
}
nodeMap.put(ni, matches);
}
// resolve unmatched nodes
if (unmatched.size() > 0)
{
// make a list of unmatched nodes in the "to" cell
Set<NodeInst> availableToNodes = new HashSet<NodeInst>();
for(Iterator<NodeInst> it = toCell.getNodes(); it.hasNext(); )
availableToNodes.add(it.next());
for(Iterator<NodeInst> it = fromCell.getNodes(); it.hasNext(); )
{
List<NodeMatch> associated = nodeMap.get(it.next());
if (associated == null) continue;
for(NodeMatch nm : associated)
{
if (nm.otherNi != null)
availableToNodes.remove(nm.otherNi);
}
}
for(int i=0; i<unmatched.size(); i++)
{
NodeMatch nm = unmatched.get(i);
NodeProto fromNp = nm.ni.getProto();
// make a list of these nodes in the "from" cell
List<NodeMatch> fromNm = new ArrayList<NodeMatch>();
for(NodeMatch nmTest : unmatched)
{
if (nmTest.ni.getProto() == fromNp) fromNm.add(nmTest);
}
// make a list of these nodes in the "to" cell
List<NodeInst> toNi = new ArrayList<NodeInst>();
for(NodeInst ni : availableToNodes)
{
if (ni.isCellInstance())
{
if (fromNp instanceof Cell)
{
if (((Cell)fromNp).getCellGroup() == ((Cell)ni.getProto()).getCellGroup()) toNi.add(ni);
}
} else
{
if (fromNp instanceof PrimitiveNode)
{
if (nm.ni.getFunction() == ni.getFunction()) toNi.add(ni);
}
}
}
// if lists are not the same length, give a warning
if (fromNm.size() != toNi.size())
{
if (fromNp instanceof Cell)
System.out.println("Error: there are " + fromNm.size() +
" instances of " + fromNp.describe(false) + " in source and " + toNi.size() + " in destination");
continue;
}
// sort the rest by position and force matches based on that
if (fromNm.size() == 0) continue;
Collections.sort(fromNm, new NameMatchSpatially());
Collections.sort(toNi, new InstancesSpatially());
for(int j=0; j<fromNm.size(); j++)
{
NodeMatch nmAssoc = fromNm.get(j);
NodeInst niAssoc = toNi.get(j);
nmAssoc.otherNi = niAssoc;
unmatched.remove(nmAssoc);
availableToNodes.remove(niAssoc);
}
}
}
// now construct the unrouted arcs in the "to" cell
int wiresMade = 0;
for(Iterator<Network> it = nl.getNetworks(); it.hasNext(); )
{
Network net = it.next();
Set<PortInst> endSet = new HashSet<PortInst>();
// deal with export matches
for(Iterator<Export> eIt = net.getExports(); eIt.hasNext(); )
{
Export e = eIt.next();
int eWidth = nl.getBusWidth(e);
for(int i=0; i<eWidth; i++)
{
if (net != nl.getNetwork(e, i)) continue;
String eName = e.getNameKey().subname(i).toString();
for(Iterator<Export> oEIt = toCell.getExports(); oEIt.hasNext(); )
{
Export oE = oEIt.next();
if (oE.getName().equalsIgnoreCase(eName))
endSet.add(oE.getOriginalPort());
}
}
}
// find all PortInsts on this network
ArcInst[] arcsOnNet = null;
if (arcMap != null) arcsOnNet = arcMap.get(net); else
{
List<ArcInst> arcList = new ArrayList<ArcInst>();
for(Iterator<ArcInst> aIt = net.getArcs(); aIt.hasNext(); ) arcList.add(aIt.next());
arcsOnNet = arcList.toArray(new ArcInst[]{});
}
for(ArcInst ai : arcsOnNet)
{
int busWidth = nl.getBusWidth(ai);
for(int b=0; b<busWidth; b++)
{
Network busNet = nl.getNetwork(ai, b);
if (busNet != net) continue;
// wire "b" of arc "ai" is on the network: include both ends
for(int e=0; e<2; e++)
{
PortInst pi = ai.getPortInst(e);
NodeInst ni = pi.getNodeInst();
List<NodeMatch> possibleNodes = nodeMap.get(ni);
if (possibleNodes == null) continue;
if (possibleNodes.size() > 1)
{
PortProto p = pi.getPortProto();
int portWidth = p.getNameKey().busWidth();
if (busWidth == portWidth)
{
// each wire of the bus connects to the same port on the different arrayed nodes
Name portName = p.getNameKey().subname(b);
for(NodeMatch nm : possibleNodes)
{
if (nm.otherNi == null) continue;
PortProto pp = nm.otherNi.getProto().findPortProto(portName);
PortInst piDest = nm.otherNi.findPortInstFromProto(pp);
if (piDest != null) endSet.add(piDest);
}
} else
{
// bus is has different signal for each arrayed node
int nodeIndex = b / portWidth;
int portIndex = b % portWidth;
NodeMatch nm = possibleNodes.get(nodeIndex);
if (nm.otherNi != null)
{
Name portName = p.getNameKey().subname(portIndex);
PortProto pp = nm.otherNi.getProto().findPortProto(portName);
PortInst piDest = nm.otherNi.findPortInstFromProto(pp);
if (piDest != null) endSet.add(piDest);
}
}
} else
{
PortProto p = pi.getPortProto();
int nodeIndex = 0;
int portIndex = b;
NodeMatch nm = possibleNodes.get(nodeIndex);
if (nm.otherNi != null)
{
Name portName = p.getNameKey().subname(portIndex);
PortProto pp = nm.otherNi.getProto().findPortProto(portName);
PortInst piDest = nm.otherNi.findPortInstFromProto(pp);
if (piDest == null)
{
if (nm.otherNi.getNumPortInsts() == 1) piDest = nm.otherNi.getOnlyPortInst();
}
if (piDest != null) endSet.add(piDest);
}
}
}
}
}
// sort the connections
List<PortInst> sortedPorts = new ArrayList<PortInst>();
for(PortInst pi : endSet) sortedPorts.add(pi);
Collections.sort(sortedPorts, new PortsByName());
// create the connections
PortInst lastPi = null;
for(PortInst pi : sortedPorts)
{
if (lastPi != null)
{
Poly lPoly = lastPi.getPoly();
Poly poly = pi.getPoly();
Point2D lPt = new Point2D.Double(lPoly.getCenterX(), lPoly.getCenterY());
Point2D pt = new Point2D.Double(poly.getCenterX(), poly.getCenterY());
ArcInst newAi = ArcInst.makeInstance(Generic.tech().unrouted_arc, lastPi, pi, lPt, pt, null);
if (newAi == null) break;
wiresMade++;
}
lastPi = pi;
}
}
if (wiresMade == 0) System.out.println("No topology was copied"); else
System.out.println("Created " + wiresMade + " arcs to copy the topology");
return true;
}
private static class PortsByName implements Comparator<PortInst>
{
public int compare(PortInst p1, PortInst p2)
{
NodeInst n1 = p1.getNodeInst();
NodeInst n2 = p2.getNodeInst();
return n1.getName().compareToIgnoreCase(n2.getName());
}
}
private static class InstancesSpatially implements Comparator<NodeInst>
{
public int compare(NodeInst n1, NodeInst n2)
{
double x1 = n1.getAnchorCenterX();
double y1 = n1.getAnchorCenterY();
double x2 = n2.getAnchorCenterX();
double y2 = n2.getAnchorCenterY();
if (y1 == y2)
{
if (x1 == x2) return 0;
if (x1 > x2) return 1;
return -1;
}
if (y1 == y2) return 0;
if (y1 > y2) return 1;
return -1;
}
}
private static class NameMatchSpatially implements Comparator<NodeMatch>
{
public int compare(NodeMatch nm1, NodeMatch nm2)
{
NodeInst n1 = nm1.ni;
NodeInst n2 = nm2.ni;
double x1 = n1.getAnchorCenterX();
double y1 = n1.getAnchorCenterY();
double x2 = n2.getAnchorCenterX();
double y2 = n2.getAnchorCenterY();
if (y1 == y2)
{
if (x1 == x2) return 0;
if (x1 > x2) return 1;
return -1;
}
if (y1 == y2) return 0;
if (y1 > y2) return 1;
return -1;
}
}
/****************************** GENERAL ROUTING OPTIONS ******************************/
private static Pref cachePreferredRoutingArc = Pref.makeStringPref("PreferredRoutingArc", Routing.tool.prefs, "");
/**
* Method to return the name of the arc that should be used as a default by the stitching routers.
* The default is "".
* @return the name of the arc that should be used as a default by the stitching routers.
*/
public static String getPreferredRoutingArc() { return cachePreferredRoutingArc.getString(); }
/**
* Method to set the name of the arc that should be used as a default by the stitching routers.
* @param arcName the name of the arc that should be used as a default by the stitching routers.
*/
public static void setPreferredRoutingArc(String arcName) { cachePreferredRoutingArc.setString(arcName); }
/**
* Method to return the name of the arc that should be used as a factory default by the stitching routers.
* @return the name of the arc that should be used as a factory default by the stitching routers.
*/
public static String getFactoryPreferredRoutingArc() { return cachePreferredRoutingArc.getStringFactoryValue(); }
/****************************** AUTO-STITCHING OPTIONS ******************************/
private static Pref cacheAutoStitchOn = Pref.makeBooleanPref("AutoStitchOn", Routing.tool.prefs, false);
/**
* Method to tell whether Auto-stitching should be done.
* The default is "false".
* @return true if Auto-stitching should be done.
*/
public static boolean isAutoStitchOn() { return cacheAutoStitchOn.getBoolean(); }
/**
* Method to set whether Auto-stitching should be done.
* @param on true if Auto-stitching should be done.
*/
public static void setAutoStitchOn(boolean on) { cacheAutoStitchOn.setBoolean(on); }
/**
* Method to tell whether Auto-stitching should be done, by default.
* @return true if Auto-stitching should be done, by default.
*/
public static boolean isFactoryAutoStitchOn() { return cacheAutoStitchOn.getBooleanFactoryValue(); }
private static Pref cacheAutoStitchCreateExports = Pref.makeBooleanPref("AutoStitchCreateExports", Routing.tool.prefs, false);
/**
* Method to tell whether Auto-stitching should create exports if necessary.
* The default is "false".
* @return true if Auto-stitching should create exports if necessary.
*/
public static boolean isAutoStitchCreateExports() { return cacheAutoStitchCreateExports.getBoolean(); }
/**
* Method to set whether Auto-stitching should create exports if necessary.
* @param on true if Auto-stitching should create exports if necessary.
*/
public static void setAutoStitchCreateExports(boolean on) { cacheAutoStitchCreateExports.setBoolean(on); }
/**
* Method to tell whether Auto-stitching should create exports if necessary, by default.
* @return true if Auto-stitching should create exports if necessary, by default.
*/
public static boolean isFactoryAutoStitchCreateExports() { return cacheAutoStitchCreateExports.getBooleanFactoryValue(); }
/****************************** MIMIC-STITCHING OPTIONS ******************************/
private static Pref cacheMimicStitchOn = Pref.makeBooleanPref("MimicStitchOn", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching should be done.
* The default is "false".
* @return true if Mimic-stitching should be done.
*/
public static boolean isMimicStitchOn() { return cacheMimicStitchOn.getBoolean(); }
/**
* Method to set whether Mimic-stitching should be done.
* @param on true if Mimic-stitching should be done.
*/
public static void setMimicStitchOn(boolean on) { cacheMimicStitchOn.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching should be done, by default.
* @return true if Mimic-stitching should be done, by default.
*/
public static boolean isFactoryMimicStitchOn() { return cacheMimicStitchOn.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchInteractive = Pref.makeBooleanPref("MimicStitchInteractive", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching runs interactively.
* During interactive Mimic stitching, each new set of arcs is shown to the user for confirmation.
* The default is "false".
* @return true if Mimic-stitching runs interactively.
*/
public static boolean isMimicStitchInteractive() { return cacheMimicStitchInteractive.getBoolean(); }
/**
* Method to set whether Mimic-stitching runs interactively.
* During interactive Mimic stitching, each new set of arcs is shown to the user for confirmation.
* @param on true if Mimic-stitching runs interactively.
*/
public static void setMimicStitchInteractive(boolean on) { cacheMimicStitchInteractive.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching runs interactively, by default.
* During interactive Mimic stitching, each new set of arcs is shown to the user for confirmation.
* @return true if Mimic-stitching runs interactively, by default.
*/
public static boolean isFactoryMimicStitchInteractive() { return cacheMimicStitchInteractive.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchPinsKept = Pref.makeBooleanPref("MimicStitchPinsKept", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching keeps pins even if it has no arc connections.
* The default is "false".
* @return true if Mimic-stitching runs interactively.
*/
public static boolean isMimicStitchPinsKept() { return cacheMimicStitchPinsKept.getBoolean(); }
/**
* Method to set whether Mimic-stitching keeps pins even if it has no arc connections.
* @param on true if Mimic-stitching runs interactively.
*/
public static void setMimicStitchPinsKept(boolean on) { cacheMimicStitchPinsKept.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching keeps pins even if it has no arc connections, by default.
* @return true if Mimic-stitching runs interactively, by default.
*/
public static boolean isFactoryMimicStitchPinsKept() { return cacheMimicStitchPinsKept.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchMatchPorts = Pref.makeBooleanPref("MimicStitchMatchPorts", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching only works between matching ports.
* The default is "false".
* @return true if Mimic-stitching only works between matching ports.
*/
public static boolean isMimicStitchMatchPorts() { return cacheMimicStitchMatchPorts.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works between matching ports.
* @param on true if Mimic-stitching only works between matching ports.
*/
public static void setMimicStitchMatchPorts(boolean on) { cacheMimicStitchMatchPorts.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works between matching ports, by default.
* @return true if Mimic-stitching only works between matching ports, by default.
*/
public static boolean isFactoryMimicStitchMatchPorts() { return cacheMimicStitchMatchPorts.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchMatchPortWidth = Pref.makeBooleanPref("MimicStitchMatchPortWidth", Routing.tool.prefs, true);
/**
* Method to tell whether Mimic-stitching only works between ports of the same width.
* This applies only in the case of busses.
* The default is "true".
* @return true if Mimic-stitching only works between matching ports.
*/
public static boolean isMimicStitchMatchPortWidth() { return cacheMimicStitchMatchPortWidth.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works between ports of the same width.
* This applies only in the case of busses.
* @param on true if Mimic-stitching only works between ports of the same width.
*/
public static void setMimicStitchMatchPortWidth(boolean on) { cacheMimicStitchMatchPortWidth.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works between ports of the same width, by default.
* This applies only in the case of busses.
* @return true if Mimic-stitching only works between matching ports, by default.
*/
public static boolean isFactoryMimicStitchMatchPortWidth() { return cacheMimicStitchMatchPortWidth.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchMatchNumArcs = Pref.makeBooleanPref("MimicStitchMatchNumArcs", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching only works when the number of existing arcs matches.
* The default is "false".
* @return true if Mimic-stitching only works when the number of existing arcs matches.
*/
public static boolean isMimicStitchMatchNumArcs() { return cacheMimicStitchMatchNumArcs.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works when the number of existing arcs matches.
* @param on true if Mimic-stitching only works when the number of existing arcs matches.
*/
public static void setMimicStitchMatchNumArcs(boolean on) { cacheMimicStitchMatchNumArcs.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works when the number of existing arcs matches, by default.
* @return true if Mimic-stitching only works when the number of existing arcs matches, by default.
*/
public static boolean isFactoryMimicStitchMatchNumArcs() { return cacheMimicStitchMatchNumArcs.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchMatchNodeSize = Pref.makeBooleanPref("MimicStitchMatchNodeSize", Routing.tool.prefs, false);
/**
* Method to tell whether Mimic-stitching only works when the node sizes are the same.
* The default is "false".
* @return true if Mimic-stitching only works when the node sizes are the same.
*/
public static boolean isMimicStitchMatchNodeSize() { return cacheMimicStitchMatchNodeSize.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works when the node sizes are the same.
* @param on true if Mimic-stitching only works when the node sizes are the same.
*/
public static void setMimicStitchMatchNodeSize(boolean on) { cacheMimicStitchMatchNodeSize.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works when the node sizes are the same, by default.
* @return true if Mimic-stitching only works when the node sizes are the same, by default.
*/
public static boolean isFactoryMimicStitchMatchNodeSize() { return cacheMimicStitchMatchNodeSize.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchMatchNodeType = Pref.makeBooleanPref("MimicStitchMatchNodeType", Routing.tool.prefs, true);
/**
* Method to tell whether Mimic-stitching only works when the nodes have the same type.
* The default is "true".
* @return true if Mimic-stitching only works when the nodes have the same type.
*/
public static boolean isMimicStitchMatchNodeType() { return cacheMimicStitchMatchNodeType.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works when the nodes have the same type.
* @param on true if Mimic-stitching only works when the nodes have the same type.
*/
public static void setMimicStitchMatchNodeType(boolean on) { cacheMimicStitchMatchNodeType.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works when the nodes have the same type, by default.
* @return true if Mimic-stitching only works when the nodes have the same type, by default.
*/
public static boolean isFactoryMimicStitchMatchNodeType() { return cacheMimicStitchMatchNodeType.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchNoOtherArcsSameDir = Pref.makeBooleanPref("MimicStitchNoOtherArcsSameDir", Routing.tool.prefs, true);
/**
* Method to tell whether Mimic-stitching only works when there are no other arcs running in the same direction.
* The default is "true".
* @return true if Mimic-stitching only works when there are no other arcs running in the same direction.
*/
public static boolean isMimicStitchNoOtherArcsSameDir() { return cacheMimicStitchNoOtherArcsSameDir.getBoolean(); }
/**
* Method to set whether Mimic-stitching only works when there are no other arcs running in the same direction.
* @param on true if Mimic-stitching only works when there are no other arcs running in the same direction.
*/
public static void setMimicStitchNoOtherArcsSameDir(boolean on) { cacheMimicStitchNoOtherArcsSameDir.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching only works when there are no other arcs running in the same direction, by default.
* @return true if Mimic-stitching only works when there are no other arcs running in the same direction, by default.
*/
public static boolean isFactoryMimicStitchNoOtherArcsSameDir() { return cacheMimicStitchNoOtherArcsSameDir.getBooleanFactoryValue(); }
private static Pref cacheMimicStitchOnlyNewTopology = Pref.makeBooleanPref("MimicStitchOnlyNewTopology", Routing.tool.prefs, true);
/**
* Method to tell whether Mimic-stitching creates arcs only where not already connected.
* If a connection is already made elsewhere, the new one is not made.
* The default is "true".
* @return true if Mimic-stitching creates arcs only where not already connected.
*/
public static boolean isMimicStitchOnlyNewTopology() { return cacheMimicStitchOnlyNewTopology.getBoolean(); }
/**
* Method to set whether Mimic-stitching creates arcs only where not already connected.
* If a connection is already made elsewhere, the new one is not made.
* @param on true if Mimic-stitching creates arcs only where not already connected.
*/
public static void setMimicStitchOnlyNewTopology(boolean on) { cacheMimicStitchOnlyNewTopology.setBoolean(on); }
/**
* Method to tell whether Mimic-stitching creates arcs only where not already connected, by default.
* If a connection is already made elsewhere, the new one is not made.
* @return true if Mimic-stitching creates arcs only where not already connected, by default.
*/
public static boolean isFactoryMimicStitchOnlyNewTopology() { return cacheMimicStitchOnlyNewTopology.getBooleanFactoryValue(); }
/****************************** SEA-OF-GATES ROUTER OPTIONS ******************************/
/** Pref map for arc preventing by sea-of-gates router. */ private static Map<ArcProto,Pref> defaultSOGPreventPrefs = new HashMap<ArcProto,Pref>();
/** Pref map for arc favoring by sea-of-gates router. */ private static Map<ArcProto,Pref> defaultSOGFavorPrefs = new HashMap<ArcProto,Pref>();
private static Pref getArcProtoBitPref(ArcProto ap, String what, Map<ArcProto,Pref> map)
{
Pref pref = map.get(ap);
if (pref == null)
{
pref = Pref.makeBooleanPref("Default" + what + "For" + ap.getName() + "IN" + ap.getTechnology().getTechName(),
User.getUserTool().prefs, false);
map.put(ap, pref);
}
return pref;
}
/**
* Method to set the "sea-of-gates can use" bit for this ArcProto.
* @param prevent true if sea-of-gates routing should avoid this ArcProto.
*/
public static void setSeaOfGatesPrevent(ArcProto ap, boolean prevent) { getArcProtoBitPref(ap, "SeaOfGatesPrevent", defaultSOGPreventPrefs).setBoolean(prevent); }
/**
* Method to tell if the "sea-of-gates" router can use this ArcProto.
* @return true if sea-of-gates routing should avoid this ArcProto.
*/
public static boolean isSeaOfGatesPrevent(ArcProto ap) { return getArcProtoBitPref(ap, "SeaOfGatesPrevent", defaultSOGPreventPrefs).getBoolean(); }
/**
* Method to set the "sea-of-gates favor" bit for this ArcProto.
* @param favor true if sea-of-gates routing should favor this ArcProto.
*/
public static void setSeaOfGatesFavor(ArcProto ap, boolean favor) { getArcProtoBitPref(ap, "SeaOfGatesFavor", defaultSOGFavorPrefs).setBoolean(favor); }
/**
* Method to tell if the "sea-of-gates" router can use this ArcProto, by default.
* @return true if sea-of-gates routing should avoid this ArcProto, by default.
*/
public static boolean isFactorySeaOfGatesPrevent(ArcProto ap) { return getArcProtoBitPref(ap, "SeaOfGatesPrevent", defaultSOGPreventPrefs).getBooleanFactoryValue(); }
/**
* Method to tell if the "sea-of-gates" router should favor this ArcProto.
* @return true if sea-of-gates routing should favor this ArcProto.
*/
public static boolean isSeaOfGatesFavor(ArcProto ap) { return getArcProtoBitPref(ap, "SeaOfGatesFavor", defaultSOGFavorPrefs).getBoolean(); }
/**
* Method to tell if the "sea-of-gates" router should favor this ArcProto, by default.
* @return true if sea-of-gates routing should favor this ArcProto, by default.
*/
public static boolean isFactorySeaOfGatesFavor(ArcProto ap) { return getArcProtoBitPref(ap, "SeaOfGatesFavor", defaultSOGFavorPrefs).getBooleanFactoryValue(); }
private static Pref cacheSOGMaxWidth = Pref.makeDoublePref("SeaOfGatesMaxWidth", Routing.getRoutingTool().prefs, 10);
/**
* Method to get the "sea-of-gates" maximum arc width.
* Since the SOG router places arcs that are as wide as the widest arc on the net,
* this may be too large (especially near pads). This value limits the width.
* @return the maximum arc width in sea-of-gates routing.
*/
public static double getSeaOfGatesMaxWidth() { return cacheSOGMaxWidth.getDouble(); }
/**
* Method to set the "sea-of-gates" maximum arc width.
* Since the SOG router places arcs that are as wide as the widest arc on the net,
* this may be too large (especially near pads). This value limits the width.
* @param w the maximum arc width in sea-of-gates routing.
*/
public static void setSeaOfGatesMaxWidth(double w) { cacheSOGMaxWidth.setDouble(w); }
/**
* Method to get the "sea-of-gates" maximum arc width, by default.
* Since the SOG router places arcs that are as wide as the widest arc on the net,
* this may be too large (especially near pads). This value limits the width.
* @return the maximum arc width in sea-of-gates routing, by default.
*/
public static double getFactorySeaOfGatesMaxWidth() { return cacheSOGMaxWidth.getDoubleFactoryValue(); }
private static Pref cacheSOGComplexityLimit = Pref.makeIntPref("SeaOfGatesComplexityLimit", Routing.getRoutingTool().prefs, 200000);
/**
* Method to get the "sea-of-gates" complexity limit.
* This is the maximum number of steps allowed when searching for a routing path.
* @return the "sea-of-gates" complexity limit.
*/
public static int getSeaOfGatesComplexityLimit() { return cacheSOGComplexityLimit.getInt(); }
/**
* Method to set the "sea-of-gates" complexity limit.
* This is the maximum number of steps allowed when searching for a routing path.
* @param c the "sea-of-gates" complexity limit.
*/
public static void setSeaOfGatesComplexityLimit(int c) { cacheSOGComplexityLimit.setInt(c); }
/**
* Method to get the "sea-of-gates" complexity limit, by default.
* This is the maximum number of steps allowed when searching for a routing path.
* @return the "sea-of-gates" complexity limit, by default.
*/
public static int getFactorySeaOfGatesComplexityLimit() { return cacheSOGComplexityLimit.getIntFactoryValue(); }
private static Pref cacheSOGUseParallelFromToRoutes = Pref.makeBooleanPref("SeaOfGatesUseParallelFromToRoutes", Routing.getRoutingTool().prefs, true);
/**
* Method to tell whether the "sea-of-gates" router does from/to analysis in parallel.
* Normally, a path is found by looking both from one end to the other, and then from the other end back to the first.
* The best result of these two searches is used as the route.
* When true, both paths are run in parallel on separate processors if there are multiple processors (default is true).
* @return true if the "sea-of-gates" router does from/to analysis in parallel.
*/
public static boolean isSeaOfGatesUseParallelFromToRoutes() { return cacheSOGUseParallelFromToRoutes.getBoolean(); }
/**
* Method to set whether the "sea-of-gates" router does from/to analysis in parallel.
* Normally, a path is found by looking both from one end to the other, and then from the other end back to the first.
* The best result of these two searches is used as the route.
* When true, both paths are run in parallel on separate processors if there are multiple processors (default is true).
* @param p true if the "sea-of-gates" router does from/to analysis in parallel.
*/
public static void setSeaOfGatesUseParallelFromToRoutes(boolean p) { cacheSOGUseParallelFromToRoutes.setBoolean(p); }
/**
* Method to tell whether the "sea-of-gates" router does from/to analysis in parallel, by default.
* Normally, a path is found by looking both from one end to the other, and then from the other end back to the first.
* The best result of these two searches is used as the route.
* When true, both paths are run in parallel on separate processors if there are multiple processors.
* @return true if the "sea-of-gates" router does from/to analysis in parallel, by default.
*/
public static boolean isFactorySeaOfGatesUseParallelFromToRoutes() { return cacheSOGUseParallelFromToRoutes.getBooleanFactoryValue(); }
private static Pref cacheSOGUseParallelRoutes = Pref.makeBooleanPref("SeaOfGatesUseParallelRoutes", Routing.getRoutingTool().prefs, false);
/**
* Method to tell whether the "sea-of-gates" router finds routes in parallel.
* When true, multiple routes are searched using parallel threads, if there are multiple processors (default is false).
* @return true if the "sea-of-gates" router finds routes in parallel.
*/
public static boolean isSeaOfGatesUseParallelRoutes() { return cacheSOGUseParallelRoutes.getBoolean(); }
/**
* Method to set whether the "sea-of-gates" router finds routes in parallel.
* When true, multiple routes are searched using parallel threads, if there are multiple processors (default is false).
* @param p true if the "sea-of-gates" router finds routes in parallel.
*/
public static void setSeaOfGatesUseParallelRoutes(boolean p) { cacheSOGUseParallelRoutes.setBoolean(p); }
/**
* Method to tell whether the "sea-of-gates" router finds routes in parallel, by default.
* When true, multiple routes are searched using parallel threads, if there are multiple processors.
* @return true if the "sea-of-gates" router finds routes in parallel, by default.
*/
public static boolean isFactorySeaOfGatesUseParallelRoutes() { return cacheSOGUseParallelRoutes.getBooleanFactoryValue(); }
/****************************** SUN ROUTER OPTIONS ******************************/
private static Pref cacheSLRVerboseLevel = Pref.makeIntPref("SunRouterVerboseLevel", Routing.getRoutingTool().prefs, 2);
/** verbose level can be 0: silent, 1: quiet, 2: normal 3: verbose */
public static int getSunRouterVerboseLevel() { return cacheSLRVerboseLevel.getInt(); }
public static void setSunRouterVerboseLevel(int v) { cacheSLRVerboseLevel.setInt(v); }
public static int getFactorySunRouterVerboseLevel() { return cacheSLRVerboseLevel.getIntFactoryValue(); }
private static Pref cacheSLRCostLimit = Pref.makeDoublePref("SunRouterCostLimit", Routing.getRoutingTool().prefs, 10);
public static double getSunRouterCostLimit() { return cacheSLRCostLimit.getDouble(); }
public static void setSunRouterCostLimit(double r) { cacheSLRCostLimit.setDouble(r); }
public static double getFactorySunRouterCostLimit() { return cacheSLRCostLimit.getDoubleFactoryValue(); }
private static Pref cacheSLRCutlineDeviation = Pref.makeDoublePref("SunRouterCutlineDeviation", Routing.getRoutingTool().prefs, 0.1);
public static double getSunRouterCutlineDeviation() { return cacheSLRCutlineDeviation.getDouble(); }
public static void setSunRouterCutlineDeviation(double r) { cacheSLRCutlineDeviation.setDouble(r); }
public static double getFactorySunRouterCutlineDeviation() { return cacheSLRCutlineDeviation.getDoubleFactoryValue(); }
private static Pref cacheSLRDelta = Pref.makeDoublePref("SunRouterDelta", Routing.getRoutingTool().prefs, 1);
public static double getSunRouterDelta() { return cacheSLRDelta.getDouble(); }
public static void setSunRouterDelta(double r) { cacheSLRDelta.setDouble(r); }
public static double getFactorySunRouterDelta() { return cacheSLRDelta.getDoubleFactoryValue(); }
private static Pref cacheSLRXBitSize = Pref.makeIntPref("SunRouterXBitSize", Routing.getRoutingTool().prefs, 20);
public static int getSunRouterXBitSize() { return cacheSLRXBitSize.getInt(); }
public static void setSunRouterXBitSize(int r) { cacheSLRXBitSize.setInt(r); }
public static int getFactorySunRouterXBitSize() { return cacheSLRXBitSize.getIntFactoryValue(); }
private static Pref cacheSLRYBitSize = Pref.makeIntPref("SunRouterYBitSize", Routing.getRoutingTool().prefs, 20);
public static int getSunRouterYBitSize() { return cacheSLRYBitSize.getInt(); }
public static void setSunRouterYBitSize(int r) { cacheSLRYBitSize.setInt(r); }
public static int getFactorySunRouterYBitSize() { return cacheSLRYBitSize.getIntFactoryValue(); }
private static Pref cacheSLRXTileSize = Pref.makeIntPref("SunRouterXTileSize", Routing.getRoutingTool().prefs, 40);
public static int getSunRouterXTileSize() { return cacheSLRXTileSize.getInt(); }
public static void setSunRouterXTileSize(int r) { cacheSLRXTileSize.setInt(r); }
public static int getFactorySunRouterXTileSize() { return cacheSLRXTileSize.getIntFactoryValue(); }
private static Pref cacheSLRYTileSize = Pref.makeIntPref("SunRouterYTileSize", Routing.getRoutingTool().prefs, 40);
public static int getSunRouterYTileSize() { return cacheSLRYTileSize.getInt(); }
public static void setSunRouterYTileSize(int r) { cacheSLRYTileSize.setInt(r); }
public static int getFactorySunRouterYTileSize() { return cacheSLRYTileSize.getIntFactoryValue(); }
private static Pref cacheSLRLayerAssgnCapF = Pref.makeDoublePref("SunRouterLayerAssgnCapF", Routing.getRoutingTool().prefs, 0.9);
public static double getSunRouterLayerAssgnCapF() { return cacheSLRLayerAssgnCapF.getDouble(); }
public static void setSunRouterLayerAssgnCapF(double r) { cacheSLRLayerAssgnCapF.setDouble(r); }
public static double getFactorySunRouterLayerAssgnCapF() { return cacheSLRLayerAssgnCapF.getDoubleFactoryValue(); }
private static Pref cacheSLRLengthLongNet = Pref.makeDoublePref("SunRouterLengthLongNet", Routing.getRoutingTool().prefs, 0);
public static double getSunRouterLengthLongNet() { return cacheSLRLengthLongNet.getDouble(); }
public static void setSunRouterLengthLongNet(double r) { cacheSLRLengthLongNet.setDouble(r); }
public static double getFactorySunRouterLengthLongNet() { return cacheSLRLengthLongNet.getDoubleFactoryValue(); }
private static Pref cacheSLRLengthMedNet = Pref.makeDoublePref("SunRouterLengthMedNet", Routing.getRoutingTool().prefs, 0);
public static double getSunRouterLengthMedNet() { return cacheSLRLengthMedNet.getDouble(); }
public static void setSunRouterLengthMedNet(double r) { cacheSLRLengthMedNet.setDouble(r); }
public static double getFactorySunRouterLengthMedNet() { return cacheSLRLengthMedNet.getDoubleFactoryValue(); }
private static Pref cacheSLRTilesPerPinLongNet = Pref.makeDoublePref("SunRouterTilesPerPinLongNet", Routing.getRoutingTool().prefs, 5);
public static double getSunRouterTilesPerPinLongNet() { return cacheSLRTilesPerPinLongNet.getDouble(); }
public static void setSunRouterTilesPerPinLongNet(double r) { cacheSLRTilesPerPinLongNet.setDouble(r); }
public static double getFactorySunRouterTilesPerPinLongNet() { return cacheSLRTilesPerPinLongNet.getDoubleFactoryValue(); }
private static Pref cacheSLRTilesPerPinMedNet = Pref.makeDoublePref("SunRouterTilesPerPinMedNet", Routing.getRoutingTool().prefs, 3);
public static double getSunRouterTilesPerPinMedNet() { return cacheSLRTilesPerPinMedNet.getDouble(); }
public static void setSunRouterTilesPerPinMedNet(double r) { cacheSLRTilesPerPinMedNet.setDouble(r); }
public static double getFactorySunRouterTilesPerPinMedNet() { return cacheSLRTilesPerPinMedNet.getDoubleFactoryValue(); }
private static Pref cacheSLROneTileFactor = Pref.makeDoublePref("SunRouterOneTileFactor", Routing.getRoutingTool().prefs, 2.65);
public static double getSunRouterOneTileFactor() { return cacheSLROneTileFactor.getDouble(); }
public static void setSunRouterOneTileFactor(double r) { cacheSLROneTileFactor.setDouble(r); }
public static double getFactorySunRouterOneTileFactor() { return cacheSLROneTileFactor.getDoubleFactoryValue(); }
private static Pref cacheSLROverloadLimit = Pref.makeIntPref("SunRouterOverloadLimit", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterOverloadLimit() { return cacheSLROverloadLimit.getInt(); }
public static void setSunRouterOverloadLimit(int r) { cacheSLROverloadLimit.setInt(r); }
public static int getFactorySunRouterOverloadLimit() { return cacheSLROverloadLimit.getIntFactoryValue(); }
private static Pref cacheSLRPinFactor = Pref.makeIntPref("SunRouterPinFactor", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterPinFactor() { return cacheSLRPinFactor.getInt(); }
public static void setSunRouterPinFactor(int r) { cacheSLRPinFactor.setInt(r); }
public static int getFactorySunRouterPinFactor() { return cacheSLRPinFactor.getIntFactoryValue(); }
private static Pref cacheSLRUPinDensityF = Pref.makeDoublePref("SunRouterUPinDensityF", Routing.getRoutingTool().prefs, 100);
public static double getSunRouterUPinDensityF() { return cacheSLRUPinDensityF.getDouble(); }
public static void setSunRouterUPinDensityF(double r) { cacheSLRUPinDensityF.setDouble(r); }
public static double getFactorySunRouterUPinDensityF() { return cacheSLRUPinDensityF.getDoubleFactoryValue(); }
private static Pref cacheSLRWindow = Pref.makeIntPref("SunRouterWindow", Routing.getRoutingTool().prefs, 30);
public static int getSunRouterWindow() { return cacheSLRWindow.getInt(); }
public static void setSunRouterWindow(int r) { cacheSLRWindow.setInt(r); }
public static int getFactorySunRouterWindow() { return cacheSLRWindow.getIntFactoryValue(); }
private static Pref cacheWireOffset = Pref.makeIntPref("SunRouterWireOffset", Routing.getRoutingTool().prefs, 0);
public static int getSunRouterWireOffset() { return cacheWireOffset.getInt(); }
public static void setSunRouterWireOffset(int r) { cacheWireOffset.setInt(r); }
public static int getFactorySunRouterWireOffset() { return cacheWireOffset.getIntFactoryValue(); }
private static Pref cacheWireModulo = Pref.makeIntPref("SunRouterWireModulo", Routing.getRoutingTool().prefs, -1);
public static int getSunRouterWireModulo() { return cacheWireModulo.getInt(); }
public static void setSunRouterWireModulo(int r) { cacheWireModulo.setInt(r); }
public static int getFactorySunRouterWireModulo() { return cacheWireModulo.getIntFactoryValue(); }
private static Pref cacheWireBlockageFactor = Pref.makeDoublePref("SunRouterWireBlockageFactor", Routing.getRoutingTool().prefs, 0);
public static double getSunRouterWireBlockageFactor() { return cacheWireBlockageFactor.getDouble(); }
public static void setSunRouterWireBlockageFactor(double r) { cacheWireBlockageFactor.setDouble(r); }
public static double getFactorySunRouterWireBlockageFactor() { return cacheWireBlockageFactor.getDoubleFactoryValue(); }
private static Pref cacheRipUpMaximum = Pref.makeIntPref("SunRouterRipUpMaximum", Routing.getRoutingTool().prefs, 3);
public static int getSunRouterRipUpMaximum() { return cacheRipUpMaximum.getInt(); }
public static void setSunRouterRipUpMaximum(int r) { cacheRipUpMaximum.setInt(r); }
public static int getFactorySunRouterRipUpMaximum() { return cacheRipUpMaximum.getIntFactoryValue(); }
private static Pref cacheRipUpPenalty = Pref.makeIntPref("SunRouterRipUpPenalty", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterRipUpPenalty() { return cacheRipUpPenalty.getInt(); }
public static void setSunRouterRipUpPenalty(int r) { cacheRipUpPenalty.setInt(r); }
public static int getFactorySunRouterRipUpPenalty() { return cacheRipUpPenalty.getIntFactoryValue(); }
private static Pref cacheRipUpExpansion = Pref.makeIntPref("SunRouterRipUpExpansion", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterRipUpExpansion() { return cacheRipUpExpansion.getInt(); }
public static void setSunRouterRipUpExpansion(int r) { cacheRipUpExpansion.setInt(r); }
public static int getFactorySunRouterRipUpExpansion() { return cacheRipUpExpansion.getIntFactoryValue(); }
private static Pref cacheZRipUpExpansion = Pref.makeIntPref("SunRouterZRipUpExpansion", Routing.getRoutingTool().prefs, 2);
public static int getSunRouterZRipUpExpansion() { return cacheZRipUpExpansion.getInt(); }
public static void setSunRouterZRipUpExpansion(int r) { cacheZRipUpExpansion.setInt(r); }
public static int getFactorySunRouterZRipUpExpansion() { return cacheZRipUpExpansion.getIntFactoryValue(); }
private static Pref cacheRipUpSearches = Pref.makeIntPref("SunRouterRipUpSearches", Routing.getRoutingTool().prefs, 1);
public static int getSunRouterRipUpSearches() { return cacheRipUpSearches.getInt(); }
public static void setSunRouterRipUpSearches(int r) { cacheRipUpSearches.setInt(r); }
public static int getFactorySunRouterRipUpSearches() { return cacheRipUpSearches.getIntFactoryValue(); }
private static Pref cacheGlobalPathExpansion = Pref.makeIntPref("SunRouterGlobalPathExpansion", Routing.getRoutingTool().prefs, 5);
public static int getSunRouterGlobalPathExpansion() { return cacheGlobalPathExpansion.getInt(); }
public static void setSunRouterGlobalPathExpansion(int r) { cacheGlobalPathExpansion.setInt(r); }
public static int getFactorySunRouterGlobalPathExpansion() { return cacheGlobalPathExpansion.getIntFactoryValue(); }
private static Pref cacheSourceAccessExpansion = Pref.makeIntPref("SunRouterSourceAccessExpansion", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterSourceAccessExpansion() { return cacheSourceAccessExpansion.getInt(); }
public static void setSunRouterSourceAccessExpansion(int r) { cacheSourceAccessExpansion.setInt(r); }
public static int getFactorySunRouterSourceAccessExpansion() { return cacheSourceAccessExpansion.getIntFactoryValue(); }
private static Pref cacheSinkAccessExpansion = Pref.makeIntPref("SunRouterSinkAccessExpansion", Routing.getRoutingTool().prefs, 10);
public static int getSunRouterSinkAccessExpansion() { return cacheSinkAccessExpansion.getInt(); }
public static void setSunRouterSinkAccessExpansion(int r) { cacheSinkAccessExpansion.setInt(r); }
public static int getFactorySunRouterSinkAccessExpansion() { return cacheSinkAccessExpansion.getIntFactoryValue(); }
private static Pref cacheDenseViaAreaSize = Pref.makeIntPref("SunRouterDenseViaAreaSize", Routing.getRoutingTool().prefs, 60);
public static int getSunRouterDenseViaAreaSize() { return cacheDenseViaAreaSize.getInt(); }
public static void setSunRouterDenseViaAreaSize(int r) { cacheDenseViaAreaSize.setInt(r); }
public static int getFactorySunRouterDenseViaAreaSize() { return cacheDenseViaAreaSize.getIntFactoryValue(); }
private static Pref cacheRetryExpandRouting = Pref.makeIntPref("SunRouterRetryExpandRouting", Routing.getRoutingTool().prefs, 50);
public static int getSunRouterRetryExpandRouting() { return cacheRetryExpandRouting.getInt(); }
public static void setSunRouterRetryExpandRouting(int r) { cacheRetryExpandRouting.setInt(r); }
public static int getFactorySunRouterRetryExpandRouting() { return cacheRetryExpandRouting.getIntFactoryValue(); }
private static Pref cacheRetryDenseViaAreaSize = Pref.makeIntPref("SunRouterRetryDenseViaAreaSize", Routing.getRoutingTool().prefs, 100);
public static int getSunRouterRetryDenseViaAreaSize() { return cacheRetryDenseViaAreaSize.getInt(); }
public static void setSunRouterRetryDenseViaAreaSize(int r) { cacheRetryDenseViaAreaSize.setInt(r); }
public static int getFactorySunRouterRetryDenseViaAreaSize() { return cacheRetryDenseViaAreaSize.getIntFactoryValue(); }
private static Pref cachePathSearchControl = Pref.makeIntPref("SunRouterPathSearchControl", Routing.getRoutingTool().prefs, 10000);
public static int getSunRouterPathSearchControl() { return cachePathSearchControl.getInt(); }
public static void setSunRouterPathSearchControl(int r) { cachePathSearchControl.setInt(r); }
public static int getFactorySunRouterPathSearchControl() { return cachePathSearchControl.getIntFactoryValue(); }
private static Pref cacheSparseViaModulo = Pref.makeIntPref("SunRouterSparseViaModulo", Routing.getRoutingTool().prefs, 31);
public static int getSunRouterSparseViaModulo() { return cacheSparseViaModulo.getInt(); }
public static void setSunRouterSparseViaModulo(int r) { cacheSparseViaModulo.setInt(r); }
public static int getFactorySunRouterSparseViaModulo() { return cacheSparseViaModulo.getIntFactoryValue(); }
private static Pref cacheLowPathSearchCost = Pref.makeIntPref("SunRouterLowPathSearchCost", Routing.getRoutingTool().prefs, 5);
public static int getSunRouterLowPathSearchCost() { return cacheLowPathSearchCost.getInt(); }
public static void setSunRouterLowPathSearchCost(int r) { cacheLowPathSearchCost.setInt(r); }
public static int getFactorySunRouterLowPathSearchCost() { return cacheLowPathSearchCost.getIntFactoryValue(); }
private static Pref cacheMediumPathSearchCost = Pref.makeIntPref("SunRouterMediumPathSearchCost", Routing.getRoutingTool().prefs, 20);
public static int getSunRouterMediumPathSearchCost() { return cacheMediumPathSearchCost.getInt(); }
public static void setSunRouterMediumPathSearchCost(int r) { cacheMediumPathSearchCost.setInt(r); }
public static int getFactorySunRouterMediumPathSearchCost() { return cacheMediumPathSearchCost.getIntFactoryValue(); }
private static Pref cacheHighPathSearchCost = Pref.makeIntPref("SunRouterHighPathSearchCost", Routing.getRoutingTool().prefs, 100);
public static int getSunRouterHighPathSearchCost() { return cacheHighPathSearchCost.getInt(); }
public static void setSunRouterHighPathSearchCost(int r) { cacheHighPathSearchCost.setInt(r); }
public static int getFactorySunRouterHighPathSearchCost() { return cacheHighPathSearchCost.getIntFactoryValue(); }
private static Pref cacheTakenPathSearchCost = Pref.makeIntPref("SunRouterTakenPathSearchCost", Routing.getRoutingTool().prefs, 10000);
public static int getSunRouterTakenPathSearchCost() { return cacheTakenPathSearchCost.getInt(); }
public static void setSunRouterTakenPathSearchCost(int r) { cacheTakenPathSearchCost.setInt(r); }
public static int getFactorySunRouterTakenPathSearchCost() { return cacheTakenPathSearchCost.getIntFactoryValue(); }
}