/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Quick.java * * Copyright (c) 2004 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.drc; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.HierarchyEnumerator; import com.sun.electric.database.variable.VarContext; import com.sun.electric.database.variable.Variable; import com.sun.electric.database.text.TextUtils; import com.sun.electric.database.topology.Geometric; import com.sun.electric.tool.Consumer; import com.sun.electric.tool.Job; import com.sun.electric.tool.MultiTaskJob; import com.sun.electric.technology.*; import java.util.*; /** * User: gg151869 * Date: Dec 12, 2007 */ public abstract class MTDRCTool extends MultiTaskJob<Layer, MTDRCTool.MTDRCResult, MTDRCTool.MTDRCResult> //public abstract class MTDRCTool extends MultiTaskJob<Layer, MTDRCTool.MTDRCResult, MTDRCTool.MTDRCResult> { protected DRC.DRCPreferences dp; protected Cell topCell; protected long globalStartTime; protected CellLayersContainer cellLayersCon = new CellLayersContainer(); protected final boolean printLog = Job.getDebug(); protected DRCRules rules; protected MTDRCTool(String jobName, DRC.DRCPreferences dp, Cell c, Consumer<MTDRCResult> consumer) { super(jobName, DRC.getDRCTool(), consumer); this.dp = dp; this.topCell= c; // Rules set must be local to avoid concurrency issues with other tasks this.rules = topCell.getTechnology().getFactoryDesignRules(); } @Override public void prepareTasks() { Technology tech = topCell.getTechnology(); cellLayersCon = new CellLayersContainer(); CheckCellLayerEnumerator layerCellCheck = new CheckCellLayerEnumerator(cellLayersCon); HierarchyEnumerator.enumerateCell(topCell, VarContext.globalContext, layerCellCheck); Collection<String> layers = cellLayersCon.getLayersSet(topCell); globalStartTime = System.currentTimeMillis(); for (String layerS : layers) { Layer layer = tech.findLayer(layerS); startTask(layer.getName(), layer); } if (!checkArea()) startTask("Node Min Size.", null); } @Override public MTDRCResult mergeTaskResults(Map<Layer,MTDRCResult> taskResults) { int numTE = 0, numTW = 0; Set<Cell> goodSpacingSet = new HashSet<Cell>(); Set<Cell> goodAreaSet = new HashSet<Cell>(); Set<Cell> cleanSpacingSet = new HashSet<Cell>(); Set<Cell> cleanAreaSet = new HashSet<Cell>(); boolean runFine = true; for (Map.Entry<Layer, MTDRCResult> e : taskResults.entrySet()) { MTDRCResult p = e.getValue(); numTE += p.numErrors; numTW += p.numWarns; if (!p.runfine) runFine = false; // Collect all cells that must be clear cleanSpacingSet.addAll(p.cleanSpacingDRCDate); cleanAreaSet.addAll(p.cleanAreaDRCDate); } // Now that all the cells to be clean are collected, then good cells can be stored. for (Map.Entry<Layer, MTDRCResult> e : taskResults.entrySet()) { MTDRCResult p = e.getValue(); for (Cell c : p.goodSpacingDRCDate) { if (!cleanSpacingSet.contains(c)) goodSpacingSet.add(c); } for (Cell c : p.goodAreaDRCDate) { if (!cleanAreaSet.contains(c)) goodAreaSet.add(c); } } System.out.println("Finished " + ((runFine)?"without":"with") + " problems."); System.out.println("Total DRC Errors: " + numTE); System.out.println("Total DRC Warnings: " + numTW); long accuEndTime = System.currentTimeMillis() - globalStartTime; System.out.println("Total Time: " + TextUtils.getElapsedTime(accuEndTime)); if (runFine) { int activeSpacingBits = DRC.getActiveBits(topCell.getTechnology(), dp); DRC.addDRCUpdate(activeSpacingBits, goodSpacingSet, cleanSpacingSet, goodAreaSet, cleanAreaSet, null, dp); } return new MTDRCResult(numTE, numTW, runFine, null, null, null, null, null); } @Override public MTDRCResult runTask(Layer taskKey) { if (skipLayer(taskKey)) return null; return runTaskInternal(taskKey); } abstract MTDRCResult runTaskInternal(Layer taskKey); abstract boolean checkArea(); static boolean skipLayerInvalidForMinArea(Layer theLayer) { // via*, polyCut, activeCut if theLayer is not null // theLayer is null if it is checking node min sizes return theLayer == null || theLayer.getFunction().isContact(); // via*, polyCut, activeCut } boolean skipLayer(Layer theLayer) { if (theLayer == null) return false; if (theLayer.getFunction().isDiff() && theLayer.getName().toLowerCase().equals("p-active-well")) return true; // dirty way to skip the MoCMOS p-active well else if (theLayer.getFunction().isGatePoly()) return true; // check transistor-poly together with polysilicon-1 else if (checkArea() && skipLayerInvalidForMinArea(theLayer)) // via*, polyCut, activeCut return true; return false; } public static class MTDRCResult { private int numErrors, numWarns; private boolean runfine; private HashSet<Cell> goodSpacingDRCDate, goodAreaDRCDate; private HashSet<Cell> cleanSpacingDRCDate, cleanAreaDRCDate; MTDRCResult(int numE, int numW, boolean notAborted, HashSet<Cell> goodSpacingDRCD, HashSet<Cell> cleanSpacingDRCD, HashSet<Cell> goodAreaDRCD, HashSet<Cell> cleanAreaDRCD, HashMap<Geometric, List<Variable>> newVars) { this.numErrors = numE; this.numWarns = numW; this.runfine = notAborted; this.goodSpacingDRCDate = goodSpacingDRCD; this.cleanSpacingDRCDate = cleanSpacingDRCD; this.goodAreaDRCDate = goodAreaDRCD; this.cleanAreaDRCDate = cleanAreaDRCD; assert(newVars == null); // not implemented for Schematics DRC } public int getNumErrors() { return numErrors; } public int getNumWarnings() { return numWarns; } } }