Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Quick.java
*
* Copyright (c) 2004, 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.drc;
import com.sun.electric.technology.*;
import com.sun.electric.tool.Consumer;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.user.ErrorLogger;
import com.sun.electric.util.math.DBMath;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.HierarchyEnumerator;
import com.sun.electric.database.hierarchy.Nodable;
import com.sun.electric.database.geometry.*;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.database.topology.NodeInst;
import com.sun.electric.database.topology.ArcInst;
import com.sun.electric.database.network.Network;
import com.sun.electric.database.prototype.NodeProto;
import com.sun.electric.util.math.FixpTransform;
import com.sun.electric.util.math.MutableInteger;
import java.util.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Area;
/**
* User: gg151869
* Date: Dec 11, 2007
*/
public class MTDRCAreaTool extends MTDRCTool
{
// /** Miscellanous data for DRC */ private DRC.ReportInfo reportInfo;
public MTDRCAreaTool(DRC.DRCPreferences dp, Cell c, Consumer consumer)
{
super("Design-Rule Area Check " + c, dp, c, consumer);
}
@Override
boolean checkArea() {return true;}
static int checkMinArea(Layer theLayer, Cell topC, DRC.ReportInfo rI, DRCRules areaRules,
CellLayersContainer cellLayersC, Job job, String msg)
{
DRCTemplate minAreaRule = areaRules.getMinValue(theLayer, DRCTemplate.DRCRuleType.MINAREA);
DRCTemplate enclosedAreaRule = areaRules.getMinValue(theLayer, DRCTemplate.DRCRuleType.MINENCLOSEDAREA);
DRCTemplate spaceRule = areaRules.getSpacingRule(theLayer, null, theLayer, null, true, -1, -1.0, -1.0); // UCONSPA, CONSPA or SPACING
if (minAreaRule == null && enclosedAreaRule == null && spaceRule == null)
return 0;
if (msg != null)
{
System.out.println("Min Area DRC for " + msg + " in thread " + Thread.currentThread().getName());
}
HierarchyEnumerator.Visitor quickArea = new LayerAreaEnumerator(theLayer, minAreaRule, enclosedAreaRule,
spaceRule, topC, rI, GeometryHandler.GHMode.ALGO_SWEEP,
cellLayersC, job);
HierarchyEnumerator.enumerateCell(topC, VarContext.globalContext, quickArea);
return rI.errorLogger.getNumErrors() + rI.errorLogger.getNumWarnings();
}
@Override
public MTDRCResult runTaskInternal(Layer theLayer)
{
ErrorLogger errorLogger = DRC.getDRCErrorLogger(true, ", Layer " + theLayer.getName());
String msg = "Cell " + topCell.getName() + " , layer " + theLayer.getName();
DRC.ReportInfo reportInfo = new DRC.ReportInfo(errorLogger, topCell.getTechnology(), dp, false);
Date lastAreaGoodDate = DRC.getLastDRCDateBasedOnBits(topCell, false, -1, !reportInfo.inMemory);
if (DRC.isCellDRCDateGood(topCell, lastAreaGoodDate))
System.out.println("The cell seems to be MinArea OK. Should I run the code?");
int totalNumErrors = checkMinArea(theLayer, topCell, reportInfo, rules, cellLayersCon, this, msg);
HashSet goodAreaDRCDate = new HashSet();
HashSet cleanAreaDRCDate = new HashSet();
timer.end();
int errorCount = errorLogger.getNumErrors();
int warnCount = errorLogger.getNumWarnings();
System.out.println(errorCount + " errors and " + warnCount + " warnings found in " + msg
+ " (took " + timer + " in thread " + Thread.currentThread().getName() + ")");
System.out.println("Accumulative time " + globalStartTime.currentTimeString());
if (totalNumErrors == 0)
{
goodAreaDRCDate.add(topCell);
}
else
{
cleanAreaDRCDate.add(topCell);
errorLogger.termLogging(true);
}
return new MTDRCResult(errorCount, warnCount, !checkAbort(), new HashSet(), new HashSet(),
goodAreaDRCDate, cleanAreaDRCDate, null);
}
/**************************************************************************************************************
* LayerAreaEnumerator class
**************************************************************************************************************/
public static class GeometryHandlerLayerBucket
{
GeometryHandler local;
boolean merged = false;
GeometryHandlerLayerBucket(GeometryHandler.GHMode mode)
{
local = GeometryHandler.createGeometryHandler(mode, 1);
}
void addElementLocal(Poly poly, Layer layer)
{
local.add(layer, poly);
}
void mergeGeometry(Cell cell, Map cellsMap)
{
if (!merged)
{
merged = true;
for (Iterator it = cell.getNodes(); it.hasNext();)
{
NodeInst ni = it.next();
if (!ni.isCellInstance()) continue; // only cell instances
FixpTransform trans = ni.transformOut();
Cell protoCell = (Cell) ni.getProto();
GeometryHandlerLayerBucket bucket = cellsMap.get(protoCell);
if (bucket != null) // it is null when the layer was not found in the subcell
local.addAll(bucket.local, trans);
}
local.postProcess(true);
} else
{
assert (false); // It should not happen
}
}
}
/**************************************************************************************************************
* LayerAreaEnumerator class
**************************************************************************************************************/
/**
* Class that uses local GeometryHandler to calculate the area per cell
*/
private static class LayerAreaEnumerator extends HierarchyEnumerator.Visitor
{
private Layer theLayer;
private Job job;
private Map cellsMap;
private Layer.Function.Set thisLayerFunction;
private GeometryHandler.GHMode mode;
private Collection nodesList; // NodeProto that contains this layer
private Collection arcsList; // ArcProto that contains this layer
private CellLayersContainer cellLayersCon;
private DRCTemplate minAreaRule, enclosedAreaRule, spacingRule, minAreaEnclosedRule;
// private ErrorLogger errorLogger;
private Cell topCell;
private DRC.ReportInfo reportInfo;
LayerAreaEnumerator(Layer layer, DRCTemplate minAreaR, DRCTemplate enclosedAreaR, DRCTemplate spaceR,
Cell topC, DRC.ReportInfo rI,
GeometryHandler.GHMode m, CellLayersContainer cellLayersC, Job j)
{
// This is required so the poly arcs will be properly merged with the transistor polys
// even though non-electrical layers are retrieved
this.minAreaRule = minAreaR;
this.enclosedAreaRule = enclosedAreaR;
this.spacingRule = spaceR;
this.topCell = topC;
this.reportInfo = rI;
this.theLayer = layer;
this.thisLayerFunction = Layer.getMultiLayersSet(theLayer);
this.mode = m;
cellsMap = new HashMap();
nodesList = new ArrayList();
this.cellLayersCon = cellLayersC;
this.job = j;
// Store the min value betwen min area and min enclosure to speed up the process
minAreaEnclosedRule = minAreaRule;
if (enclosedAreaRule != null &&
(minAreaRule == null || enclosedAreaRule.getValue(0) < minAreaRule.getValue(0)))
minAreaEnclosedRule = enclosedAreaRule;
// determine list of PrimitiveNodes that have this particular layer
for (PrimitiveNode node : topCell.getTechnology().getNodesCollection())
{
for (Technology.NodeLayer nLayer : node.getNodeLayers())
{
if (thisLayerFunction.contains(nLayer.getLayer().getFunction(), theLayer.getFunctionExtras()))
{
nodesList.add(node);
break; // found
}
}
}
arcsList = new ArrayList();
for (ArcProto ap : topCell.getTechnology().getArcsCollection())
{
for (int i = 0; i < ap.getNumArcLayers(); i++)
{
if (ap.getLayer(i) == theLayer)
{
arcsList.add(ap);
break; // found
}
}
}
}
public boolean enterCell(HierarchyEnumerator.CellInfo info)
{
// Checking if the job was aborted by the user
if (job.checkAbort()) return false;
Cell cell = info.getCell();
Set set = cellLayersCon.getLayersSet(cell);
// The cell doesn't contain the layer
if (set != null && !set.contains(theLayer))
{
return false;
}
GeometryHandlerLayerBucket bucket = cellsMap.get(cell);
if (bucket == null)
{
bucket = new GeometryHandlerLayerBucket(mode);
cellsMap.put(cell, bucket);
}
else
{
assert(bucket.merged);
return false; // done with this cell
}
for(Iterator it = info.getCell().getArcs(); it.hasNext(); )
{
ArcInst ai = it.next();
Network aNet = info.getNetlist().getNetwork(ai, 0);
// aNet is null if ArcProto is Artwork
if (aNet == null)
continue;
ArcProto ap = ai.getProto();
boolean notFound = !arcsList.contains(ap);
if (notFound)
continue; // primitive doesn't contain this layer
Technology tech = ap.getTechnology();
Poly[] arcInstPolyList = tech.getShapeOfArc(ai, thisLayerFunction);
int tot = arcInstPolyList.length;
for(int i=0; i areas = m.getAreas(layer);
MutableInteger errorFound = new MutableInteger(0);
// It could be multi-threaded per area
for (Area area : areas)
{
List list = PolyBase.getLoopsFromArea(area, layer);
boolean minPass = true;
for (PolyBase p : list)
{
double a = p.getArea();
minPass = (minAreaEnclosedRule == null) ? true : a >= minAreaEnclosedRule.getValue(0);
if (!minPass) break; // go for full checking
if (spacingRule != null)
{
Rectangle2D bnd = p.getBounds2D();
minPass = bnd.getWidth() >= spacingRule.getValue(0);
if (minPass)
minPass = bnd.getHeight() >= spacingRule.getValue(1);
}
if (!minPass) break; // go for full checking
}
// Must run the real checking
if (!minPass)
{
for (PolyBase.PolyBaseTree obj : PolyBase.getTreesFromLoops(list))
{
traversePolyTree(layer, obj, 0, cell, errorFound);
}
}
}
return errorFound.intValue();
}
// private int checkMinAreaLayerWithTree(GeometryHandler merge, Cell cell, Layer layer)
// {
// // Layer doesn't have min area
// if (minAreaRule == null && enclosedAreaRule == null && spacingRule == null) return 0;
//
// Collection trees = merge.getTreeObjects(layer);
// GenMath.MutableInteger errorFound = new GenMath.MutableInteger(0);
//
// for (PolyBase.PolyBaseTree obj : trees)
// {
// traversePolyTree(layer, obj, 0, cell, errorFound);
// }
// return errorFound.intValue();
// }
private void traversePolyTree(Layer layer, PolyBase.PolyBaseTree obj, int level,
Cell cell, MutableInteger count)
{
for (PolyBase.PolyBaseTree son : obj.getSons())
{
traversePolyTree(layer, son, level+1, cell, count);
}
boolean minAreaCheck = level%2 == 0;
boolean checkMin = false, checkNotch = false;
DRC.DRCErrorType errorType = DRC.DRCErrorType.MINAREAERROR;
double minVal = 0;
String ruleName = "";
if (minAreaCheck)
{
if (minAreaRule == null) return; // no rule
minVal = minAreaRule.getValue(0);
ruleName = minAreaRule.ruleName;
checkMin = true;
}
else
{
// odd level checks enclose area and holes (spacing rule)
errorType = DRC.DRCErrorType.ENCLOSEDAREAERROR;
if (enclosedAreaRule != null)
{
minVal = enclosedAreaRule.getValue(0);
ruleName = enclosedAreaRule.ruleName;
checkMin = true;
}
checkNotch = (spacingRule != null);
}
PolyBase poly = obj.getPoly();
if (checkMin)
{
double area = poly.getArea();
// isGreaterThan doesn't consider equals condition therefore negate condition is used
if (!DBMath.isGreaterThan(minVal, area)) return; // larger than the min value
count.increment();
DRC.createDRCErrorLogger(reportInfo,
errorType, null, cell, minVal, area, ruleName,
poly, null, layer, null, null, null);
}
if (checkNotch)
{
// Notches are calculated using the bounding box of the polygon -> this is an approximation
Rectangle2D bnd = poly.getBounds2D();
if (bnd.getWidth() < spacingRule.getValue(0))
{
count.increment();
DRC.createDRCErrorLogger(reportInfo,
DRC.DRCErrorType.NOTCHERROR, "(X axis)", cell, spacingRule.getValue(0), bnd.getWidth(),
spacingRule.ruleName, poly, null, layer, null, null, layer);
}
if (bnd.getHeight() < spacingRule.getValue(1))
{
count.increment();
DRC.createDRCErrorLogger(reportInfo,
DRC.DRCErrorType.NOTCHERROR, "(Y axis)", cell, spacingRule.getValue(1), bnd.getHeight(),
spacingRule.ruleName, poly, null, layer, null, null, layer);
}
}
}
}
}