/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: HighlightEquivalent.java
*
* Copyright (c) 2005, 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.user.ncc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JOptionPane;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.hierarchy.HierarchyEnumerator.NetNameProxy;
import com.sun.electric.database.hierarchy.HierarchyEnumerator.NodableNameProxy;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.topology.Geometric;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.variable.EditWindow_;
import com.sun.electric.database.variable.UserInterface;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.ncc.NccJob;
import com.sun.electric.tool.ncc.basic.CellContext;
import com.sun.electric.tool.ncc.basic.NccUtils;
import com.sun.electric.tool.ncc.netlist.NccNetlist;
import com.sun.electric.tool.ncc.result.NccResult;
import com.sun.electric.tool.ncc.result.NccResults;
import com.sun.electric.tool.ncc.result.equivalence.Equivalence;
import com.sun.electric.tool.user.Highlighter;
import com.sun.electric.util.TextUtils;
/** Called from Tool -> NCC -> Highlight Equivalent */
public class HighlightEquivalent {
private static void prln(String s) {System.out.println(s);}
// private NodaPortInst getPortFromUnshortedNet(Network n) {
// NodaNets noshortNets = new NodaNets(n.getParent(), false);
// Collection<NodaPortInst> ports = noshortNets.getPorts(n);
// for (NodaPortInst pi : ports) return pi;
//
// LayoutLib.error(true, "No ports found on Network?");
// return null;
// }
//
// // GUI netlists don't treat resistors as shorts. Let's find an
// // equivalent shorted-resistor Network. This is tricky. All
// // Networks except globals are guaranteed to be connected to at
// // least one port. Therefore find a port on the old network,
// // short resistors, and try to find the network connected to the
// // same port.
// private Network netWhenResShorted(Network n) {
// // if resistors already shorted then nothing else can be done
// if (n.getNetlist().getShortResistors()) return null;
// prln(" RK Debug: Try shorting resistors");
//
// NodaPortInst port = getPortFromUnshortedNet(n);
// NodaNets shortedNets = new NodaNets(n.getParent(), true);
// Nodable no = shortedNets.getNoda(port.getNodable().getName());
// for (NodaPortInst pi : shortedNets.getPorts(no)) {
// if (pi.getIndex()==port.getIndex() &&
// pi.getPortProto()==port.getPortProto()) {
// return pi.getNet();
// }
// }
// prln(" RK Debug: Shorting resistors fails");
//
// return null;
// }
private void highlightEquivalentNet(Network n, Equivalence e,
CellContext cc) {
prln("Finding equivalent of Network: "+n.describe(false));
NetNameProxy eqProx = e.findEquivalentNetShortingResistors(cc.context, n);
if (eqProx==null) {prln("Can't find an equivalent network."); return;}
// if (eqProx==null) {
// // try extending this net by shorting resistors
// n = netWhenResShorted(n);
// if (n==null) {prln("Can't find an equivalent network."); return;}
// eqProx = e.findEquivalentNet(cc.context, n);
// if (eqProx==null) {prln("Can't find an equivalent network."); return;}
// }
VarContext eqCtxt = eqProx.getContext();
Cell eqCell = eqProx.leafCell();
Highlighter h = HighlightTools.getHighlighter(eqCell, eqCtxt);
HighlightTools.highlightNetNamed(h, eqCell, eqProx.leafName());
}
// Sort Names treating embedded numbers as numbers
private static class NameCompare implements Comparator<String> {
public int compare(String nm1, String nm2) {
return TextUtils.STRING_NUMBER_ORDER.compare(nm1, nm2);
}
}
private Network selectNet(Set<Network> netSet) {
List<Network> nets = new ArrayList<Network>(netSet);
if (nets.size()==1) return nets.get(0);
Map<String,Network> nameToNet = new HashMap<String,Network>();
String[] names = new String[nets.size()];
int i=0;
for (Network n : nets) {
String netNm = n.getName();
nameToNet.put(netNm, n);
names[i++] = netNm;
}
Arrays.sort(names, new NameCompare());
String name = (String)
JOptionPane.showInputDialog(
null, "Select the Network you want to find the match of",
"Select Network:", JOptionPane.PLAIN_MESSAGE, null, names,
names[0]);
if (name==null) {
// user clicked "Cancel"
return null;
}
return nameToNet.get(name);
}
private void highlightEquivOfNet(Set<Network> nets, Equivalence e, CellContext cc) {
Network n = selectNet(nets);
if (n==null) {
// user clicked "Cancel"
return;
}
highlightEquivalentNet(n, e, cc);
}
private List<Nodable> findNodablesFrom(NodeInst ni) {
List<Nodable> nodables = new ArrayList<Nodable>();
Cell c = ni.getParent();
// Search for all Nodables associated with a bussed NodeInst
for (Iterator<Nodable> it=c.getNetlist(NccNetlist.SHORT_RESISTORS).getNodables(); it.hasNext();) {
Nodable no = it.next();
if (no.getNodeInst()==ni) nodables.add(no);
}
return nodables;
}
private Nodable selectNodable(List<Nodable> nodes) {
if (nodes.size()==1) return nodes.get(0);
Map<String,Nodable> nameToNode = new HashMap<String,Nodable>();
String[] names = new String[nodes.size()];
int i=0;
for (Nodable n : nodes) {
String nodeNm = n.getName();
nameToNode.put(nodeNm, n);
names[i++] = nodeNm;
}
Arrays.sort(names, new NameCompare());
String name = (String)
JOptionPane.showInputDialog(
null, "Select the Instance you want to find the match of",
"Select Instance:", JOptionPane.PLAIN_MESSAGE, null, names,
names[0]);
if (name==null) {
// user clicked "Cancel"
return null;
}
return nameToNode.get(name);
}
private void highlightEquivOfNodeInst(NodeInst ni, Equivalence e,
CellContext cc) {
prln("Find the equivalent of NodeInst: "+ni.describe(false));
List<Nodable> nodables = findNodablesFrom(ni);
Job.error(nodables.size()==0, "No Nodable for NodeInst?");
Nodable node = selectNodable(nodables);
if (node==null) {
// user clicked "Cancel"
return;
}
NodableNameProxy eqProx = e.findEquivalentNode(cc.context,node);
if (eqProx==null) {
prln(" No equivalent Node found.");
return;
}
Nodable eqNo = eqProx.getNodable();
NodeInst eqNi;
if (eqNo instanceof NodeInst) eqNi = (NodeInst) eqNo;
else eqNi = eqNo.getNodeInst();
Cell eqCell = eqProx.leafCell();
VarContext eqCtxt = eqProx.getContext();
Highlighter h = HighlightTools.getHighlighter(eqCell, eqCtxt);
h.addElectricObject(eqNi, eqCell);
}
private void highlightEquivOfGeometric(List<Geometric> geoms,
Equivalence e, CellContext cc) {
Geometric g = geoms.iterator().next();
if (!(g instanceof NodeInst)) {
prln("Highlighted object is not a nodeInst: ");
g.getInfo();
return;
}
highlightEquivOfNodeInst((NodeInst)g, e, cc);
}
private void highlight1() {
NccResults results = NccJob.getLastNccResults();
if (results==null) {
prln("No saved NCC results. Please run NCC first.");
return;
}
UserInterface ui = Job.getUserInterface();
EditWindow_ wnd = ui.needCurrentEditWindow_();
if (wnd==null) {
prln("No current Window");
return;
}
CellContext cc = NccUtils.getCellContext(wnd);
NccResult r = results.getResultFromRootCells();
Equivalence e = r.getEquivalence();
List<Geometric> geoms = wnd.getHighlightedEObjs(true, false);
if (geoms.size()>0) {
highlightEquivOfGeometric(geoms, e, cc);
return;
}
Set<Network> nets = wnd.getHighlightedNetworks();
if (nets.size()>0) {
highlightEquivOfNet(nets, e, cc);
return;
}
prln("No arc or node is selected");
}
private HighlightEquivalent() {highlight1();}
// -------------------------- public method -------------------------------
public static void highlight() {new HighlightEquivalent();}
}