/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: MOSRules.java * * Copyright (c) 2003 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.technology.technologies.utils; import com.sun.electric.database.text.TextUtils; import com.sun.electric.database.topology.Geometric; import com.sun.electric.technology.DRCRules; import com.sun.electric.technology.DRCTemplate; import com.sun.electric.technology.Layer; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.Technology; import java.util.Iterator; import java.util.List; import java.util.ArrayList; /** * Class to define a complete set of design rules. * Includes constructors for initializing the data from a technology. */ public class MOSRules implements DRCRules { /** the technology */ private Technology tech; /** number of layers in the technology */ public int numLayers; /** size of upper-triangle of layers */ public int uTSize; /** width limit that triggers wide rules */ public Double wideLimit; /** names of layers */ public String [] layerNames; /** minimum width of layers */ public Double [] minWidth; /** minimum width rules */ public String [] minWidthRules; /** minimum distances when connected */ public Double [] conList; /** minimum distance ruless when connected */ public String [] conListRules; /** minimum distance ruless when connected */ public String [] conListNodes; /** minimum distances when unconnected */ public Double [] unConList; /** minimum distance rules when unconnected */ public String [] unConListRules; /** minimum distance rules when unconnected */ public String [] unConListNodes; /** minimum distances when connected (wide) */ public Double [] conListWide; /** minimum distance rules when connected (wide) */ public String [] conListWideRules; /** minimum distances when unconnected (wide) */ public Double [] unConListWide; /** minimum distance rules when unconnected (wide) */ public String [] unConListWideRules; /** minimum distances when connected (multi-cut) */ public Double [] conListMulti; /** minimum distance rules when connected (multi-cut) */ public String [] conListMultiRules; /** minimum distances when unconnected (multi-cut) */ public Double [] unConListMulti; /** minimum distance rules when unconnected (multi-cut) */ public String [] unConListMultiRules; /** minimum edge distances */ public Double [] edgeList; /** minimum edge distance rules */ public String [] edgeListRules; /** minimum area rules */ public Double [] minArea; /** minimum area rule names */ public String [] minAreaRules; /** maximum slot size rules */ public Double [] slotSize; /** maximum slot size rule names */ public String [] slotSizeRules; /** number of nodes in the technology */ public int numNodes; /** names of nodes */ public String [] nodeNames; /** minimim node size in the technology */ public Double [] minNodeSize; /** minimim node size rules */ public String [] minNodeSizeRules; /** cut size in the technology */ public Double [] cutNodeSize; /** cut size rules */ public String [] cutNodeSizeRules; /** cut 1D spacing in the technology */ public Double [] cutNodeSpa1D; /** cut 1D s[acing rules */ public String [] cutNodeSpa1DRules; /** cut 2D spacing in the technology */ public Double [] cutNodeSpa2D; /** cut 2D s[acing rules */ public String [] cutNodeSpa2DRules; /** Only 1 surround per contact node! **/ /** cut surround in the technology */ public Double [] cutNodeSurround; /** cut surround rules */ public String [] cutNodeSurroundRules; /** poly overhang/surround along gate **/ public double transPolyOverhang; /** number of rules stored */ private int numberOfRules; /** DEFAULT null rule */ private final static int MOSNORULE = -1; public MOSRules() {} /** * Method to set minimum node size * @param index represents node, widths are stored in index*2 and height in index*2+j * @param name * @param width * @param height */ private void setMinNodeSize(int index, String name, double width, double height) { minNodeSizeRules[index] = name; minNodeSize[index*2] = new Double(width); minNodeSize[index*2+1] = new Double(height); } /** * * @param index represents node, widths are stored in index*2 and height in index*2+j * @param when represents the foundry being used * @return a rule describing the minimum node size. */ public DRCTemplate getMinNodeSize(int index, int when) { // That division by 2 might be a problem double[] vals = {minNodeSize[index*2].doubleValue(), minNodeSize[index*2+1].doubleValue()}; // width and height DRCTemplate rule = new DRCTemplate(minNodeSizeRules[index], when, DRCTemplate.DRCRuleType.NODSIZ, 0, 0, null, null, vals, -1); return (rule); } /** * Method to determine the technology associated with this rules set. * @return the technology associated with this rules set. */ public Technology getTechnology() {return tech;} public MOSRules(Technology t) { this.tech = t; // compute sizes numLayers = tech.getNumLayers(); numNodes = tech.getNumNodes(); int numIndices = numLayers + numNodes; uTSize = (numIndices * numIndices + numIndices) / 2; //uTSize = (numLayers * numLayers + numLayers) / 2; // initialize the width limit wideLimit = new Double(0); // add names layerNames = new String[numLayers]; int j = 0; for(Iterator<Layer> it = tech.getLayers(); it.hasNext(); ) { Layer layer = it.next(); layerNames[j++] = layer.getName(); } nodeNames = new String[numNodes]; j = 0; for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); ) { PrimitiveNode np = it.next(); nodeNames[j++] = np.getName(); } // allocate tables conList = new Double[uTSize]; conListRules = new String[uTSize]; conListNodes = new String[uTSize]; unConList = new Double[uTSize]; unConListRules = new String[uTSize]; unConListNodes = new String[uTSize]; conListWide = new Double[uTSize]; conListWideRules = new String[uTSize]; unConListWide = new Double[uTSize]; unConListWideRules = new String[uTSize]; conListMulti = new Double[uTSize]; conListMultiRules = new String[uTSize]; unConListMulti = new Double[uTSize]; unConListMultiRules = new String[uTSize]; edgeList = new Double[uTSize]; edgeListRules = new String[uTSize]; minWidth = new Double[numLayers]; minWidthRules = new String[numLayers]; minArea = new Double[numLayers]; minAreaRules = new String[numLayers]; slotSize = new Double[numLayers]; slotSizeRules = new String[numLayers]; // clear all tables for(int i=0; i<uTSize; i++) { conList[i] = new Double(MOSNORULE); conListRules[i] = ""; unConList[i] = new Double(MOSNORULE); unConListRules[i] = ""; conListWide[i] = new Double(MOSNORULE); conListWideRules[i] = ""; unConListWide[i] = new Double(MOSNORULE); unConListWideRules[i] = ""; conListMulti[i] = new Double(MOSNORULE); conListMultiRules[i] = ""; unConListMulti[i] = new Double(MOSNORULE); unConListMultiRules[i] = ""; edgeList[i] = new Double(MOSNORULE); edgeListRules[i] = ""; } for(int i=0; i<numLayers; i++) { minWidth[i] = new Double(MOSNORULE); minWidthRules[i] = ""; minArea[i] = new Double(MOSNORULE); minAreaRules[i] = ""; slotSize[i] = new Double(MOSNORULE); slotSizeRules[i] = ""; } // build node size tables minNodeSize = new Double[numNodes*2]; minNodeSizeRules = new String[numNodes]; cutNodeSize = new Double[numNodes]; cutNodeSizeRules = new String[numNodes]; cutNodeSurround = new Double[numNodes]; cutNodeSurroundRules = new String[numNodes]; cutNodeSpa1D = new Double[numNodes]; cutNodeSpa1DRules = new String[numNodes]; cutNodeSpa2D = new Double[numNodes]; cutNodeSpa2DRules = new String[numNodes]; j = 0; for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); ) { PrimitiveNode np = it.next(); PrimitiveNode.NodeSizeRule minSizeRule = np.getMinSizeRule(); minNodeSize[j*2] = minSizeRule != null ? minSizeRule.getWidth() : 0; // autoboxing minNodeSize[j*2+1] = minSizeRule != null ? minSizeRule.getHeight() : 0; // autoboxing minNodeSizeRules[j] = minSizeRule != null ? minSizeRule.getRuleName() : ""; cutNodeSizeRules[j] = ""; cutNodeSize[j] = new Double(MOSNORULE); cutNodeSurroundRules[j] = ""; cutNodeSurround[j] = new Double(MOSNORULE); cutNodeSpa1DRules[j] = ""; cutNodeSpa1D[j] = new Double(MOSNORULE); cutNodeSpa2DRules[j] = ""; cutNodeSpa2D[j] = new Double(MOSNORULE); j++; } } /** * Method to determine the index in the upper-left triangle array for two layers/nodes. This function * assumes no rules for primitives nor single layers are stored. * @param index1 the first layer/node index. * @param index2 the second layer/node index. * @return the index in the array that corresponds to these two layers/nodes. */ public int getRuleIndex(int index1, int index2) { return getRuleIndex(index1, index2, tech.getNumLayers()); } /** * Method to determine the index in the upper-left triangle array for two layers/nodes. This function * assumes no rules for primitives nor single layers are stored. * @param index1 the first layer/node index. * @param index2 the second layer/node index. * @param numLayers the number of layers * @return the index in the array that corresponds to these two layers/nodes. */ public static int getRuleIndex(int index1, int index2, int numLayers) { if (index1 > index2) { int temp = index1; index1 = index2; index2 = temp; } int pIndex = (index1+1) * (index1/2) + (index1&1) * ((index1+1)/2); pIndex = index2 + numLayers * index1 - pIndex; return pIndex; } /** * Method to return overhang of poly in transistors along the gate * @return the overhang of poly in transistors along the gate. */ public double getPolyOverhang() { return transPolyOverhang; } /** * Method to determine if given node is not allowed by foundry. * @param nodeIndex index of node in DRC rules map to examine. * @param type rule type. * @return the rule if this is a forbidden node otherwise returns null. */ public DRCTemplate isForbiddenNode(int nodeIndex, DRCTemplate.DRCRuleType type) { return null; } // /** // * Method to create a set of Design Rules from some simple spacing arrays. // * Used by simpler technologies that do not have full-sets of design rules. // * @param tech the Technology to load. // * @param conDist an upper-diagonal array of layer-to-layer distances (when connected). // * @param unConDist an upper-diagonal array of layer-to-layer distances (when unconnected). // * @return a set of design rules for the Technology. // */ // public static DRCRules makeSimpleRules(Technology tech, double [] conDist, double [] unConDist) // { // MOSRules rules = new MOSRules(tech); // if (conDist != null) // { // for(int i=0; i<conDist.length; i++) // { // rules.conList[i] = (conDist[i]); // autoboxing // } // } // if (unConDist != null) // { // for(int i=0; i<unConDist.length; i++) // { // rules.unConList[i] = (unConDist[i]); // autoboxing // } // } // rules.calculateNumberOfRules(); // return rules; // } /** * Method to find the worst spacing distance in the design rules. * Finds the largest spacing rule in the Technology. * @return the largest spacing distance in the Technology. Zero if nothing found * @param lastMetal */ public double getWorstSpacingDistance(int lastMetal) { assert(lastMetal == -1); // not implemented for only metals yet double worstInteractionDistance = 0; for(int i = 0; i < uTSize; i++) { double dist = unConList[i]; if (dist > worstInteractionDistance) worstInteractionDistance = dist; dist = unConListWide[i]; if (dist > worstInteractionDistance) worstInteractionDistance = dist; dist = unConListMulti[i]; if (dist > worstInteractionDistance) worstInteractionDistance = dist; } return worstInteractionDistance; } /** * Method to find the maximum design-rule distance around a layer. * @param layer the Layer to examine. * @return the maximum design-rule distance around the layer. -1 if nothing found. */ public double getMaxSurround(Layer layer, double maxSize) { double worstLayerRule = -1; int layerIndex = layer.getIndex(); int tot = tech.getNumLayers(); double wide = wideLimit; for(int i=0; i<tot; i++) { int pIndex = getRuleIndex(layerIndex, i); double dist = unConList[pIndex]; if (dist > worstLayerRule) worstLayerRule = dist; if (maxSize > wide) { dist = unConListWide[pIndex]; if (dist > worstLayerRule) worstLayerRule = dist; } } return worstLayerRule; } /** * Method to find all rules of specified type associated to Layer layer1 * @param layer1 layer * @param type rule type * @return all rules of specified type associated to Layer layer1 */ public List<DRCTemplate> getRules(Layer layer1, DRCTemplate.DRCRuleType type) { return null; // not available for CMOS } /** * Method to find the extension rule between two layer. * @param layer1 the first layer. * @param layer2 the second layer. * @param isGateExtension to decide between the rule EXTENSIONGATE or EXTENSION * @return the extension rule between the layers. * Returns null if there is no extension rule. */ public DRCTemplate getExtensionRule(Layer layer1, Layer layer2, boolean isGateExtension) { return null; // not available for CMOS } /** * Method to find the edge spacing rule between two layer. * @param layer1 the first layer. * @param layer2 the second layer. * @return the edge rule distance between the layers. * Returns null if there is no edge spacing rule. */ public DRCTemplate getEdgeRule(Layer layer1, Layer layer2) { int pIndex = getRuleIndex(layer1.getIndex(), layer2.getIndex()); double[] dist = {edgeList[pIndex]}; if (dist[0] < 0) return null; return new DRCTemplate(edgeListRules[pIndex], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.SPACINGE, 0, 0, null, null, dist, -1); } /** * Method to find the spacing rule between two layer. * @param layer1 the first layer. * @param layer2 the second layer. * @param connected true to find the distance when the layers are connected. * @param multiCut 1 to find the distance when this is part of a multicut contact. * @param wideS widest polygon * @param length length of the intersection * @return the spacing rule between the layers. * Returns null if there is no spacing rule. */ public DRCTemplate getSpacingRule(Layer layer1, Geometric geo1, Layer layer2, Geometric geo2, boolean connected, int multiCut, double wideS, double length) { int pIndex = getRuleIndex(layer1.getIndex(), layer2.getIndex()); String n1 = DRCTemplate.getSpacingCombinedName(layer1, geo1); String n2 = DRCTemplate.getSpacingCombinedName(layer2, geo2); double[] bestDist = {-1}; String rule = null; if (connected) { double dist = conList[pIndex]; boolean validName = true; if (conListNodes[pIndex] != null && (!n1.equals(conListNodes[pIndex]) && !n2.equals(conListNodes[pIndex]))) validName = false; if (validName && dist >= 0) { bestDist[0] = dist; rule = conListRules[pIndex]; } } else { double dist = unConList[pIndex]; // autoboxing boolean validName = true; if (unConListNodes[pIndex] != null && (!n1.equals(unConListNodes[pIndex]) && !n2.equals(unConListNodes[pIndex]))) validName = false; if (validName && dist >= 0) { bestDist[0] = dist; rule = unConListRules[pIndex]; } } if (wideS > wideLimit) // autoboxing { if (connected) { double dist = conListWide[pIndex]; // autoboxing if (dist >= 0) { bestDist[0] = dist; rule = conListWideRules[pIndex]; } } else { double dist = unConListWide[pIndex]; // autoboxing if (dist >= 0) { bestDist[0] = dist; rule = unConListWideRules[pIndex]; } } } if (multiCut == 1) { if (connected) { double dist = conListMulti[pIndex]; // autoboxing if (dist >= 0) { bestDist[0] = dist; rule = conListMultiRules[pIndex]; } } else { double dist = unConListMulti[pIndex]; // autoboxing if (dist >= 0) { bestDist[0] = dist; rule = unConListMultiRules[pIndex]; } } } if (bestDist[0] < 0) return null; return new DRCTemplate(rule, DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.SPACING, 0, 0, bestDist, multiCut); } /** * Method to tell whether there are any design rules between two layers. * @param layer1 the first Layer to check. * @param layer2 the second Layer to check. * @return true if there are design rules between the layers. */ public boolean isAnySpacingRule(Layer layer1, Layer layer2) { int pIndex = getRuleIndex(layer1.getIndex(), layer2.getIndex()); if (conList[pIndex] >= 0) return true; if (unConList[pIndex] >= 0) return true; if (conListWide[pIndex] >= 0) return true; if (unConListWide[pIndex] >= 0) return true; if (conListMulti[pIndex] >= 0) return true; if (unConListMulti[pIndex] >= 0) return true; if (edgeList[pIndex] >= 0) return true; return false; } /** * Method to tell UI if multiple wide rules are allowed. * @param index the index in the upper-diagonal table of layers. * @return true if multiple wide rules are allowed. */ public boolean doesAllowMultipleWideRules(int index) { return (unConListWide[index] == MOSNORULE); } /** * Method to retrieve total number of rules stored. */ public int getNumberOfRules() { return numberOfRules; } /** * To retrieve those nodes that have rules. * @return an array of nodes that have rules. */ public String[] getNodesWithRules() {return nodeNames;} public void addRule(int index, DRCTemplate rule) { new Error("Not implemented"); } /** * Method to add a rule based on template @param index * @param rule * @param wideRules */ public void addRule(int index, DRCTemplate rule, DRCTemplate.DRCRuleType spacingCase, boolean wideRules) { if (rule.ruleType == DRCTemplate.DRCRuleType.NODSIZ) setMinNodeSize(index, rule.ruleName, rule.getValue(0), rule.getValue(1)); else { // if (rule.value1 <= 0) rule.value1 = MOSNORULE; switch (rule.ruleType) { case CONSPA: // Connected { switch (spacingCase) { case SPACING: { if (!wideRules) { conList[index] = (rule.getValue(0)); // autoboxing conListRules[index] = rule.ruleName; if (rule.maxWidth > 0) wideLimit = (rule.maxWidth); // autoboxing } else { conListWide[index] = (rule.getValue(0)); // autoboxing conListWideRules[index] = rule.ruleName; if (rule.maxWidth > 0) wideLimit = (rule.maxWidth); } } break; case UCONSPA2D: conListMulti[index] = (rule.getValue(0)); // autoboxing conListMultiRules[index] = rule.ruleName; break; case SPACINGE: // edge rules edgeList[index] = (rule.getValue(0)); // autoboxing edgeListRules[index] = rule.ruleName; break; default: System.out.println("Error in MOSRules.setSpacingRules"); } } break; case UCONSPA: // Connected { switch (spacingCase) { case SPACING: { if (!wideRules) { unConList[index] = (rule.getValue(0)); // autoboxing unConListRules[index] = rule.ruleName; if (rule.maxWidth > 0) wideLimit = (rule.maxWidth);// autoboxing } else { unConListWide[index] = (rule.getValue(0)); // autoboxing unConListWideRules[index] = rule.ruleName; if (rule.maxWidth > 0) wideLimit = (rule.maxWidth);// autoboxing } break; } case UCONSPA2D: unConListMulti[index] = (rule.getValue(0)); // autoboxing unConListMultiRules[index] = rule.ruleName; break; default: System.out.println("Error in MOSRules.setSpacingRules"); } } break; default: System.out.println("Error in MOSRules.setSpacingRules"); } } } /** * Method to delete a given spacing rule * @param index * @param rule */ public void deleteRule(int index, DRCTemplate rule) { // Reset the actual value conListWide[index] = new Double(MOSNORULE); conListWideRules[index] = ""; unConListWide[index] = new Double(MOSNORULE); unConListWideRules[index] = ""; } /** * * @param index * @param newRules * @param spacingCase SPACING for normal case, SPACINGW for wide case, CUTSPA for multi cuts * @param wideRules */ public void setSpacingRules(int index, List<DRCTemplate> newRules, DRCTemplate.DRCRuleType spacingCase, boolean wideRules) { for (DRCTemplate rule : newRules) { addRule(index, rule, spacingCase, false); } } /** * Method to retrieve different spacing rules depending on type. * @param index the index of the layer being queried. * @param type SPACING (normal values), SPACINGW (wide values), * SPACINGE (edge values) and CUTSPA (multi cuts). * @param wideRules * @return list of rules subdivided in UCONSPA and CONSPA */ public List<DRCTemplate> getSpacingRules(int index, DRCTemplate.DRCRuleType type, boolean wideRules) { List<DRCTemplate> list = new ArrayList<DRCTemplate>(2); // SMR changed the four lines listed below...widelimit should appear in the SPACINGW rule, not the SPACING rule switch (type) { case SPACING: // normal rules { if (!wideRules) { double[] dist = {conList[index]}; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(conListRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.CONSPA, 0, 0, null, null, dist, -1)); dist[0] = unConList[index]; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(unConListRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.UCONSPA, 0, 0, null, null, dist, -1)); } else { double[] dist = {conListWide[index]}; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(conListWideRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.CONSPA, wideLimit, 0, null, null, dist, -1)); // autoboxing dist[0] = unConListWide[index]; if (dist[0] >= 0) list.add(new DRCTemplate(unConListWideRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.UCONSPA, wideLimit, 0, null, null, dist, -1)); // autoboxing } } break; case UCONSPA2D: // multi contact rules { double[] dist = {conListMulti[index]}; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(conListMultiRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.CONSPA, 0, 0, null, null, dist, 1)); dist[0] = unConListMulti[index]; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(unConListMultiRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.UCONSPA, 0, 0, null, null, dist, 1)); } break; case SPACINGE: // edge rules { double[] dist = {edgeList[index]}; // autoboxing if (dist[0] >= 0) list.add(new DRCTemplate(edgeListRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.SPACINGE, 0, 0, null, null, dist, -1)); } break; default: System.out.println("Error in MOSRules.getSpacingRules"); } return (list); } /** * Method to calculate final number of rules */ private void calculateNumberOfRules() { int count = 0; // autoboxing was applied below for(int i = 0; i < uTSize; i++) { //Uncon if (unConList[i] > MOSNORULE) count++; if (unConListWide[i] > MOSNORULE) count++; if (unConListMulti[i] > MOSNORULE) count++; // Con if (conList[i] > MOSNORULE) count++; if (conListWide[i] > MOSNORULE) count++; if (conListMulti[i] > MOSNORULE) count++; // Edge rules if (edgeList[i] > MOSNORULE) count++; } for(int i=0; i<numLayers; i++) { if (minWidth[i] > MOSNORULE) count++; } for(int i=0; i<minNodeSize.length; i++) { if (minNodeSize[i] > MOSNORULE) count++; } numberOfRules = count; } /** * Method to get the minimum <type> rule for a Layer * where <type> is the rule type. E.g. MinWidth or Area * @param layer the Layer to examine. * @param type rule type * @return the minimum rule for the layer. * Returns null if there is no minimum width rule. */ public DRCTemplate getMinValue(Layer layer, DRCTemplate.DRCRuleType type) { int index = layer.getIndex(); switch(type) { case MINWID: { double[] dist = {minWidth[index]}; // autoboxing if (dist[0] < 0) return null; return (new DRCTemplate(minWidthRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.MINWID, 0, 0, null, null, dist, -1)); } case MINAREA: { double[] dist = {minArea[index]}; // autoboxing if (dist[0] < 0) return null; return (new DRCTemplate(minAreaRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.MINAREA, 0, 0, null, null, dist, -1)); } case SLOTSIZE: { double[] dist = {slotSize[index]}; // autoboxing if (dist[0] < 0) return null; return (new DRCTemplate(slotSizeRules[index], DRCTemplate.DRCMode.ALL.mode(), DRCTemplate.DRCRuleType.SLOTSIZE, 0, 0, null, null, dist, -1)); } } return null; } /** * Method to retrieve simple layer or node rules * @param index the index of the layer or node * @param type the rule type. * @return the requested rule. */ public DRCTemplate getRule(int index, DRCTemplate.DRCRuleType type) { switch(type) { case MINWID: double[] minSize = {minWidth[index], minWidth[index]}; // autoboxing if (minSize[0] < 0) return null; return (new DRCTemplate(minWidthRules[index], DRCTemplate.DRCMode.ALL.mode(), type, 0, 0, null, null, minSize, -1)); case UCONSPA2D: double[] cutSpa = {cutNodeSpa1D[index]}; // autoboxing if (cutSpa[0] < 0) return null; return (new DRCTemplate(cutNodeSpa1DRules[index], DRCTemplate.DRCMode.ALL.mode(), type, 0, 0, null, null, cutSpa, -1)); } return null; } /** * Method to retrieve specific rules stored per node that involve two layers * @param index the combined index of the two layers involved * @param type * @param nodeName name of the primitive * @return null */ public DRCTemplate getRule(int index, DRCTemplate.DRCRuleType type, String nodeName) { new Error("not implemented"); return null; } /** * Method to set the minimum <type> rule for a Layer * where <type> is the rule type. E.g. MinWidth or Area * @param layer the Layer to examine. * @param name the rule name * @param value the new rule value * @param type rule type */ public void setMinValue(Layer layer, String name, double value, DRCTemplate.DRCRuleType type) { int index = layer.getIndex(); if (value <= 0) value = MOSNORULE; switch (type) { case MINWID: minWidth[index] = (value); // autoboxing minWidthRules[index] = name; break; case MINAREA: minArea[index] = (value); // autoboxing minAreaRules[index] = name; break; default: System.out.println("Not implemented for " + type + " in MOSRules.setMinValue"); } } /** * Method to apply overrides to a set of rules. * @param override the override string. * @param tech the Technology in which these rules live. */ public void applyDRCOverrides(String override, Technology tech) { int pos = 0; int len = override.length(); while (pos < len) { int startKey = pos; int endKey = override.indexOf(':', startKey); if (endKey < 0) break; String key = override.substring(startKey, endKey); if (key.equals("c") || key.equals("cr") || key.equals("u") || key.equals("ur") || key.equals("cw") || key.equals("cwr") || key.equals("uw") || key.equals("uwr") || key.equals("cm") || key.equals("cmr") || key.equals("um") || key.equals("umr") || key.equals("e") || key.equals("er")) { startKey = endKey + 1; Layer layer1 = Technology.getLayerFromOverride(override, startKey, '/', tech); if (layer1 == null) break; startKey = override.indexOf('/', startKey); if (startKey < 0) break; Layer layer2 = Technology.getLayerFromOverride(override, startKey+1, '=', tech); if (layer2 == null) break; startKey = override.indexOf('=', startKey); if (startKey < 0) break; endKey = override.indexOf(';', startKey); if (endKey < 0) break; String newValue = override.substring(startKey+1, endKey); int index = getRuleIndex(layer1.getIndex(), layer2.getIndex()); if (key.equals("c")) { conList[index] = TextUtils.atof(newValue); } else if (key.equals("cr")) { conListRules[index] = newValue; } else if (key.equals("u")) { unConList[index] = TextUtils.atof(newValue); } else if (key.equals("ur")) { unConListRules[index] = newValue; } else if (key.equals("cw")) { conListWide[index] = TextUtils.atof(newValue); } else if (key.equals("cwr")) { conListWideRules[index] = newValue; } else if (key.equals("uw")) { unConListWide[index] = TextUtils.atof(newValue); } else if (key.equals("uwr")) { unConListWideRules[index] = newValue; } else if (key.equals("cm")) { conListMulti[index] = TextUtils.atof(newValue); } else if (key.equals("cmr")) { conListMultiRules[index] = newValue; } else if (key.equals("um")) { unConListMulti[index] = TextUtils.atof(newValue); } else if (key.equals("umr")) { unConListMultiRules[index] = newValue; } else if (key.equals("e")) { edgeList[index] = TextUtils.atof(newValue); } else if (key.equals("er")) { edgeListRules[index] = newValue; } pos = endKey + 1; continue; } if (key.equals("m") || key.equals("mr")) { startKey = endKey + 1; Layer layer = Technology.getLayerFromOverride(override, startKey, '=', tech); if (layer == null) break; startKey = override.indexOf('=', startKey); if (startKey < 0) break; endKey = override.indexOf(';', startKey); if (endKey < 0) break; String newValue = override.substring(startKey+1, endKey); int index = layer.getIndex(); if (key.equals("m")) { minWidth[index] = TextUtils.atof(newValue); } else if (key.equals("mr")) { minWidthRules[index] = newValue; } pos = endKey + 1; continue; } if (key.equals("n") || key.equals("nr")) { startKey = endKey + 1; int endPos = override.indexOf('=', startKey); if (endPos < 0) break; String nodeName = override.substring(startKey, endPos); PrimitiveNode np = tech.findNodeProto(nodeName); if (np == null) break; int index = 0; for(Iterator<PrimitiveNode> it = tech.getNodes(); it.hasNext(); ) { PrimitiveNode oNp = it.next(); if (oNp == np) break; index++; } if (key.equals("n")) { startKey = override.indexOf('=', startKey); if (startKey < 0) break; endKey = override.indexOf('/', startKey); if (endKey < 0) break; String newValue1 = override.substring(startKey+1, endKey); int otherEndKey = override.indexOf(';', startKey); if (otherEndKey < 0) break; String newValue2 = override.substring(endKey+1, otherEndKey); minNodeSize[index*2] = TextUtils.atof(newValue1); minNodeSize[index*2+1] = TextUtils.atof(newValue2); } else if (key.equals("nr")) { startKey = override.indexOf('=', startKey); if (startKey < 0) break; endKey = override.indexOf(';', startKey); if (endKey < 0) break; minNodeSizeRules[index] = override.substring(startKey+1, endKey); } pos = endKey + 1; continue; } if (key.equals("w")) { startKey = endKey + 1; endKey = override.indexOf(';', startKey); if (endKey < 0) break; String newValue = override.substring(startKey, endKey); wideLimit = TextUtils.atof(newValue); pos = endKey + 1; continue; } // Skip this format endKey = override.indexOf(';', startKey); pos = endKey + 1; } } }