/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: StratCheckSizes.java
*
* Copyright (c) 2003, 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.
*/
/** StratFrontier finds all non-matched EquivRecords */
package com.sun.electric.tool.ncc.strategy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import com.sun.electric.tool.ncc.NccGlobals;
import com.sun.electric.tool.ncc.NccOptions;
import com.sun.electric.tool.ncc.basic.NccUtils;
import com.sun.electric.tool.ncc.lists.LeafList;
import com.sun.electric.tool.ncc.netlist.Mos;
import com.sun.electric.tool.ncc.netlist.NetObject;
import com.sun.electric.tool.ncc.netlist.Part;
import com.sun.electric.tool.ncc.netlist.Resistor;
import com.sun.electric.tool.ncc.netlist.Subcircuit;
import com.sun.electric.tool.ncc.result.SizeMismatch.LengthMismatch;
import com.sun.electric.tool.ncc.result.SizeMismatch.Mismatch;
import com.sun.electric.tool.ncc.result.SizeMismatch.WidthMismatch;
import com.sun.electric.tool.ncc.trees.Circuit;
import com.sun.electric.tool.ncc.trees.EquivRecord;
/** Check that corresponding transistors in the schematic and layout
* have the same channel widths and lengths.
*/
public class StratCheckSizes extends Strategy {
// ------------------------------ private data -----------------------------
private NccOptions options;
private double minWidth, maxWidth, minLength, maxLength;
private Part minWidPart, maxWidPart, minLenPart, maxLenPart;
private List<Mismatch> mismatches = new ArrayList<Mismatch>();
private int cktNdx, minWidNdx, maxWidNdx, minLenNdx, maxLenNdx;
private StratCheckSizes(NccGlobals globals) {
super(globals);
options = globals.getOptions();
}
private void checkWidthMismatch() {
if (!NccUtils.sizesMatch(maxWidth, minWidth, options)) {
mismatches.add(new WidthMismatch(minWidth, minWidPart, minWidNdx,
maxWidth, maxWidPart, maxWidNdx));
}
}
private void checkLengthMismatch() {
if (!NccUtils.sizesMatch(maxLength, minLength, options)) {
mismatches.add(new LengthMismatch(minLength, minLenPart, minLenNdx,
maxLength, maxLenPart, maxLenNdx));
}
}
private static class MismatchComparator implements Comparator<Mismatch> {
public int compare(Mismatch m1, Mismatch m2) {
double diff = m1.relErr() - m2.relErr();
if (diff==0) return 0;
return diff<0 ? 1 : -1;
}
}
private void summary() {
if (mismatches.size()==0) return; // no news is good news
Collections.sort(mismatches, new MismatchComparator());
System.out.println(" There are "+mismatches.size()+" size mismatches.");
for (Mismatch m : mismatches)
System.out.print(m.toString());
globals.getNccGuiInfo().setSizeMismatches(mismatches);
}
private boolean matches() {return mismatches.size()==0;}
private double getWidth(Part p) {
return (p instanceof Mos) ? ((Mos)p).getWidth()
: ((Resistor)p).getWidth();
}
private double getLength(Part p) {
return (p instanceof Mos) ? ((Mos)p).getLength()
: ((Resistor)p).getLength();
}
public LeafList doFor(EquivRecord j) {
if(j.isLeaf()) {
if (j.isMatched()) {
minWidth = minLength = Double.MAX_VALUE;
maxWidth = maxLength = Double.MIN_VALUE;
cktNdx = 0;
super.doFor(j);
checkWidthMismatch();
checkLengthMismatch();
}
} else {
super.doFor(j);
}
return new LeafList();
}
public HashMap<Integer,List<NetObject>> doFor(Circuit c){
HashMap<Integer,List<NetObject>> result = super.doFor(c);
cktNdx++;
return result;
}
public Integer doFor(NetObject n) {
Part p = (Part) n;
if (p instanceof Subcircuit) {
minWidth = maxWidth = minLength = maxLength = 1;
} else {
globals.error(!(p instanceof Mos) &&
!(p instanceof Resistor), "part with no width & length");
double w = getWidth(p);
if (w<minWidth) {minWidth=w; minWidPart=p; minWidNdx=cktNdx;}
if (w>maxWidth) {maxWidth=w; maxWidPart=p; maxWidNdx=cktNdx;}
double l = getLength(p);
if (l<minLength) {minLength=l; minLenPart=p; minLenNdx=cktNdx;}
if (l>maxLength) {maxLength=l; maxLenPart=p; maxLenNdx=cktNdx;}
}
return CODE_NO_CHANGE;
}
// ------------------- intended interface ------------------------
public static boolean doYourJob(NccGlobals globals) {
NccOptions options = globals.getOptions();
if (!options.checkSizes) return true;
EquivRecord parts = globals.getParts();
if (parts==null) return true;
StratCheckSizes jsf = new StratCheckSizes(globals);
jsf.doFor(parts);
jsf.summary();
return jsf.matches();
}
}