📄 drc.java
字号:
static boolean mayTouch(Technology tech, boolean con, Layer layer1, Layer layer2) { boolean maytouch = false; if (tech.sameLayer(layer1, layer2)) { Layer.Function fun = layer1.getFunction(); if (con) { if (!fun.isContact()) maytouch = true; } else { if (fun.isSubstrate()) maytouch = true; // Special cases for thick actives else { // Searching for THICK bit int funExtras = layer1.getFunctionExtras(); if (fun.isDiff() && (funExtras&Layer.Function.THICK) != 0) { if (Job.LOCALDEBUGFLAG) System.out.println("Thick active found in Quick.checkDist"); maytouch = true; } } } } return maytouch; } /** * Method to check if a PrimitiveNode contains a layer that is forbidden in the current technology * @param ni node to analyze * @param reportInfo data for the report * @return True if the node is forbidden */ static boolean checkNodeAgainstCombinationRules(NodeInst ni, ReportInfo reportInfo) { Cell cell = ni.getParent(); NodeProto np = ni.getProto(); Technology tech = np.getTechnology(); if (np instanceof PrimitiveNode) { DRCTemplate forbidRule = DRC.isForbiddenNode(((PrimitiveNode)np).getPrimNodeIndexInTech(), -1, DRCTemplate.DRCRuleType.FORBIDDEN, tech); if (forbidRule != null) { DRC.createDRCErrorLogger(reportInfo, DRC.DRCErrorType.FORBIDDEN, " is not allowed by selected foundry", cell, -1, -1, forbidRule.ruleName, null, ni, null, null, null, null); return true; } } return false; } /** * Method to check which combination of OD2 layers are allowed * @param layer * @return true if there is an invalid combination of OD2 layers */ static boolean checkOD2Combination(Technology tech, NodeInst ni, Layer layer, Map<Layer,NodeInst> od2Layers, ReportInfo reportInfo) { int funExtras = layer.getFunctionExtras(); boolean notOk = false; if (layer.getFunction().isImplant() && (funExtras&Layer.Function.THICK) != 0) { // Only stores first node found od2Layers.put(layer, ni); // More than one type used. if (od2Layers.size() != 1) { for (Map.Entry<Layer,NodeInst> e : od2Layers.entrySet()) { Layer lay1 = e.getKey(); if (lay1 == layer) continue; DRCTemplate rule = isForbiddenNode(lay1.getIndex(), layer.getIndex(), DRCTemplate.DRCRuleType.FORBIDDEN, tech); if (rule != null) { NodeInst node = e.getValue(); // od2Layers.get(lay1); String message = "- combination of layers '" + layer.getName() + "' and '" + lay1.getName() + "' (in '" + node.getParent().getName() + ":" + node.getName() +"') not allowed by selected foundry"; createDRCErrorLogger(reportInfo, DRCErrorType.FORBIDDEN, message, ni.getParent(), -1, -1, rule.ruleName, null, ni, null, null, node, null); return true; } } } } return notOk; } /*********************************** QUICK DRC ERROR REPORTING ***********************************/ public static enum DRCErrorType { // the different types of errors SPACINGERROR, MINWIDTHERROR, NOTCHERROR, MINSIZEERROR, BADLAYERERROR, LAYERSURROUNDERROR, MINAREAERROR, ENCLOSEDAREAERROR, SURROUNDERROR, FORBIDDEN, RESOLUTION, CUTERROR, SLOTSIZEERROR, CROOKEDERROR, // Different types of warnings ZEROLENGTHARCWARN, TECHMIXWARN } public static class ReportInfo { /** error type search */ DRC.DRCCheckMode errorTypeSearch; /** minimum output grid resolution */ double minAllowedResolution; /** true to ignore center cuts in large contacts. */ boolean ignoreCenterCuts = DRC.isIgnoreCenterCuts();; /** maximum area to examine (the worst spacing rule). */ double worstInteractionDistance; /** time stamp for numbering networks. */ int checkTimeStamp; /** for numbering networks. */ int checkNetNumber; /** total errors found in all threads. */ int totalSpacingMsgFound; /** for logging errors */ ErrorLogger errorLogger; /** for interactive error logging */ boolean interactiveLogger = DRC.isInteractiveLoggingOn(); /** to cache current extra bits */ int activeSpacingBits = 0; Map<Cell, Area> exclusionMap = new HashMap<Cell,Area>(); // The DRCExclusion object lists areas where Generic:DRC-Nodes exist to ignore errors. boolean inMemory = DRC.isDatesStoredInMemory(); public ReportInfo(ErrorLogger eL, Technology tech, boolean specificGeoms) { errorLogger = eL; activeSpacingBits = DRC.getActiveBits(tech); worstInteractionDistance = DRC.getWorstSpacingDistance(tech, -1); // minimim resolution different from zero if flag is on otherwise stays at zero (default) minAllowedResolution = tech.getResolution(); errorTypeSearch = DRC.getErrorType(); if (specificGeoms) { errorTypeSearch = DRC.DRCCheckMode.ERROR_CHECK_CELL; } } } public static void createDRCErrorLogger(ReportInfo reportInfo, DRCErrorType errorType, String msg, Cell cell, double limit, double actual, String rule, PolyBase poly1, Geometric geom1, Layer layer1, PolyBase poly2, Geometric geom2, Layer layer2) { ErrorLogger errorLogger = reportInfo.errorLogger; if (errorLogger == null) return; // if this error is in an ignored area, don't record it StringBuffer DRCexclusionMsg = new StringBuffer(); if (reportInfo.exclusionMap != null && reportInfo.exclusionMap.get(cell) != null) { // determine the bounding box of the error List<PolyBase> polyList = new ArrayList<PolyBase>(2); List<Geometric> geomList = new ArrayList<Geometric>(2); polyList.add(poly1); geomList.add(geom1); if (poly2 != null) { polyList.add(poly2); geomList.add(geom2); } boolean found = checkExclusionMap(reportInfo.exclusionMap, cell, polyList, geomList, DRCexclusionMsg); // At least one DRC exclusion that contains both if (found) return; } // describe the error Cell np1 = (geom1 != null) ? geom1.getParent() : null; Cell np2 = (geom2 != null) ? geom2.getParent() : null; // Message already logged boolean onlyWarning = (errorType == DRCErrorType.ZEROLENGTHARCWARN || errorType == DRCErrorType.TECHMIXWARN); // Until a decent algorithm is in place for detecting repeated errors, ERROR_CHECK_EXHAUSTIVE might report duplicate errros if ( geom2 != null && reportInfo.errorTypeSearch != DRCCheckMode.ERROR_CHECK_EXHAUSTIVE && errorLogger.findMessage(cell, geom1, geom2.getParent(), geom2, !onlyWarning)) return; StringBuffer errorMessage = new StringBuffer(); DRCCheckLogging loggingType = getErrorLoggingType(); int sortKey = cell.hashCode(); // 0; if (errorType == DRCErrorType.SPACINGERROR || errorType == DRCErrorType.NOTCHERROR || errorType == DRCErrorType.SURROUNDERROR) { // describe spacing width error if (errorType == DRCErrorType.SPACINGERROR) errorMessage.append("Spacing"); else if (errorType == DRCErrorType.SURROUNDERROR) errorMessage.append("Surround"); else errorMessage.append("Notch"); if (layer1 == layer2) errorMessage.append(" (layer '" + layer1.getName() + "')"); errorMessage.append(": "); if (np1 != np2) { errorMessage.append(np1 + ", "); } else if (np1 != cell && np1 != null) { errorMessage.append("[in " + np1 + "] "); } if (geom1 != null) errorMessage.append(geom1); if (layer1 != layer2) errorMessage.append(", layer '" + layer1.getName() + "'"); if (actual < 0) errorMessage.append(" OVERLAPS (BY " + TextUtils.formatDouble(limit-actual) + ") "); else if (actual == 0) errorMessage.append(" TOUCHES "); else errorMessage.append(" LESS (BY " + TextUtils.formatDouble(limit-actual) + ") THAN " + TextUtils.formatDouble(limit) + ((geom2!=null)?" TO ":"")); if (np1 != np2 && np2 != null) errorMessage.append(np2 + ", "); if (geom2 != null) errorMessage.append(geom2); if (layer1 != layer2) errorMessage.append(", layer '" + layer2.getName() + "'"); if (msg != null) errorMessage.append("; " + msg); } else { // describe minimum width/size or layer error StringBuffer errorMessagePart2 = null; switch (errorType) { case CROOKEDERROR: errorMessage.append("Crooked error:"); errorMessagePart2 = new StringBuffer(" is not horizontal nor vertical"); break; case RESOLUTION: errorMessage.append("Resolution error:"); errorMessagePart2 = new StringBuffer(msg); break; case FORBIDDEN: errorMessage.append("Forbidden error:"); errorMessagePart2 = new StringBuffer(msg); break; case SLOTSIZEERROR: errorMessage.append("Slot size error:"); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); errorMessagePart2.append(" BIGGER THAN " + TextUtils.formatDouble(limit) + " IN LENGTH (IS " + TextUtils.formatDouble(actual) + ")"); break; case MINAREAERROR: errorMessage.append("Minimum area error:"); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); errorMessagePart2.append(" LESS THAN " + TextUtils.formatDouble(limit) + " IN AREA (IS " + TextUtils.formatDouble(actual) + ")"); break; case ENCLOSEDAREAERROR: errorMessage.append("Enclosed area error:"); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); errorMessagePart2.append(" LESS THAN " + TextUtils.formatDouble(limit) + " IN AREA (IS " + TextUtils.formatDouble(actual) + ")"); break; case TECHMIXWARN: errorMessage.append("Technology mixture warning:"); errorMessagePart2 = new StringBuffer(msg); break; case ZEROLENGTHARCWARN: errorMessage.append("Zero width warning:"); errorMessagePart2 = new StringBuffer(msg); break; case CUTERROR: errorMessage.append("Maximum cut error" + ((msg != null) ? ("(" + msg + "):") : "")); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); errorMessagePart2.append(" BIGGER THAN " + TextUtils.formatDouble(limit) + " WIDE (IS " + TextUtils.formatDouble(actual) + ")"); break; case MINWIDTHERROR: errorMessage.append("Minimum width/height error" + ((msg != null) ? ("(" + msg + "):") : "")); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); errorMessagePart2.append(" LESS THAN " + TextUtils.formatDouble(limit) + " WIDE (IS " + TextUtils.formatDouble(actual) + ")"); break; case MINSIZEERROR: errorMessage.append("Minimum size error on " + msg + ":"); errorMessagePart2 = new StringBuffer(" LESS THAN " + TextUtils.formatDouble(limit) + " IN SIZE (IS " + TextUtils.formatDouble(actual) + ")"); break; case BADLAYERERROR: errorMessage.append("Invalid layer ('" + layer1.getName() + "'):"); break; case LAYERSURROUNDERROR: errorMessage.append("Layer surround error: " + msg); errorMessagePart2 = new StringBuffer(", layer '" + layer1.getName() + "'"); String layerName = (layer2 != null) ? layer2.getName() : "Select"; errorMessagePart2.append(" NEEDS SURROUND OF LAYER '" + layerName + "' BY " + limit); break; default: assert(false); // it should not happen } errorMessage.append(" " + cell + " "); if (geom1 != null) { errorMessage.append(geom1); } // only when is flat -> use layer index for sorting if (layer1 != null && loggingType == DRCCheckLogging.DRC_LOG_FLAT) sortKey = layer1.getIndex(); errorMessage.append(errorMessagePart2); } if (rule != null && rule.length() > 0) errorMessage.append(" [rule '" + rule + "']"); errorMessage.append(DRCexclusionMsg); List<Geometric> geomList = new ArrayList<Geometric>(); List<PolyBase> polyList = new ArrayList<PolyBase>(); if (poly1 != null) polyList.add(poly1); else if (geom1 != null) geomList.add(geom1); if (poly2 != null) polyList.add(poly2); else if (geom2 != null) geomList.add(geom2); switch (loggingType) { case DRC_LOG_PER_CELL: errorLogger.setGroupName(sortKey, cell.getName()); break; case DRC_LOG_PER_RULE: String theRuleName = rule; if (theRuleName == null) theRuleName = errorType.name();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -