DIRECTORY CD USING [Layer, Number, undefLayer], CDProperties USING [RegisterProperty], CMosB USING [cut, cut2, lambda, met, met2, ndif, nwell, nwellCont, ovg, pdif, pol, pwell, pwellCont], CoreProperties USING [propPrint, PropPrintProc, Props, RegisterProperty, StoreProperties], DesignRules USING [DesignRuleError, GetScaledValue, MaxWidth, MinSpace, MinWidth, Rules], Drc USING [CellProc, CoreCell, Rect, State, Tech, TechRec, Wire, WireInstance, WirePairProc, WireProc], DrcCmosb, DrcCmosbMain USING [CompleteSeparation, FullWireCheck, SimpleMaterialSeparation, SimpleWidthCheck, VerifyWells], DrcUtilities USING [IsWell, PrintChecked], Rope USING [Cat, ROPE], Saguaro USING [gate]; DrcCmosbRulesImpl: CEDAR PROGRAM IMPORTS CDProperties, CMosB, CoreProperties, DesignRules, DrcCmosbMain, DrcUtilities, Rope, Saguaro EXPORTS DrcCmosb SHARES Drc ~ BEGIN OPEN CMosB, Drc, DrcCmosb, DrcCmosbMain, DrcUtilities; gate: Layer ~ Saguaro.gate; Layer: TYPE ~ CD.Layer; ROPE: TYPE ~ Rope.ROPE; cMosBsimpleKey: PUBLIC ATOM ~ CoreProperties.RegisterProperty [$simpleGenista]; cMosBcompleteKey: PUBLIC ATOM ~ CoreProperties.RegisterProperty [$completeGenista]; CMosbTable: PUBLIC TYPE ~ REF CMosbTableRec; Rule: TYPE ~ DrcCmosb.Rule; CMosbTableRec: TYPE ~ DrcCmosb.CMosbTableRec; cachedTech: RECORD [t: Tech _ NIL, tk: ATOM _ NIL]; NewTechnology: PUBLIC PROC [key: ATOM, rules: DesignRules.Rules] RETURNS [tech: Tech] ~ BEGIN rt: CMosbTable; toto: Rule; ComputeMaxSeparation: PROC [key: ATOM] RETURNS [max: CD.Number] ~ BEGIN sep: CD.Number; max _ 0; FOR s1: Layer IN Layer DO IF tech.illegalLayer[s1] THEN LOOP; FOR s2: Layer IN Layer DO IF tech.illegalLayer[s2] THEN LOOP; SELECT key FROM cMosBsimpleKey => NULL; -- all standard cMosBcompleteKey => IF (IsWell [s1] AND IsWell [s2]) THEN LOOP; ENDCASE => ERROR; sep _ DesignRules.MinSpace [rules, s1, s2 ! DesignRules.DesignRuleError => LOOP].s; max _ MAX [max, sep] ENDLOOP ENDLOOP END; -- ComputeMaxSeparation IF (key # cMosBsimpleKey) AND (key # cMosBcompleteKey) THEN RETURN [NIL]; IF (cachedTech.t # NIL) AND (key = cachedTech.t.checkedBy) AND (rules.id = cachedTech.tk) THEN BEGIN IF (key = cMosBcompleteKey) AND (cachedTech.t.verifyCell = NIL) THEN cachedTech.t.verifyCell _ VerifyWells; RETURN [cachedTech.t] END; tech _ NEW [TechRec]; tech.illegalLayer[ndif] _ tech.illegalLayer[pdif] _ tech.illegalLayer[nwell] _ tech.illegalLayer[pwellCont] _ tech.illegalLayer[nwellCont] _ tech.illegalLayer[pol] _ tech.illegalLayer[met] _ tech.illegalLayer[met2] _ tech.illegalLayer[cut] _ tech.illegalLayer[cut2] _ tech.illegalLayer[ovg] _ tech.illegalLayer[gate] _ FALSE; tech.lambda _ lambda; SELECT key FROM cMosBsimpleKey => BEGIN tech.checkedBy _ cMosBsimpleKey; tech.maxSeparation _ ComputeMaxSeparation [cMosBsimpleKey]; tech.ttMaxSep _ tech.ctMaxSep _ tech.maxSeparation; tech.verifyWire _ SimpleWidthCheck; tech.verifyWirePair _ SimpleMaterialSeparation END; cMosBcompleteKey => BEGIN tech.checkedBy _ cMosBcompleteKey; tech.maxSeparation _ ComputeMaxSeparation [cMosBcompleteKey]; tech.ttMaxSep _ tech.ctMaxSep _ tech.maxSeparation; -- fixed later tech.verifyWire _ FullWireCheck; tech.verifyWirePair _ CompleteSeparation; tech.verifyCell _ VerifyWells END; ENDCASE => ERROR; rt _ NEW [CMosbTableRec]; FOR i: Layer IN Layer DO rt.separation[i] _ NEW [ARRAY Layer OF Rule] ENDLOOP; FOR i: Layer IN Layer DO IF tech.illegalLayer[i] THEN LOOP; [toto.extent, toto.msg] _ DesignRules.MinWidth [rules, i ! DesignRules.DesignRuleError => LOOP]; rt.minWidth[i] _ toto; [toto.extent, toto.msg] _ DesignRules.MaxWidth [rules, i ! DesignRules.DesignRuleError => LOOP]; rt.maxWidth[i] _ toto; IF (rt.maxWidth[i].extent = 0) THEN rt.maxWidth[i].extent _ CD.Number.LAST / lambda; rt.separation[i] _ NEW [ARRAY Layer OF Rule]; FOR j: Layer IN [0 .. i] DO IF tech.illegalLayer[j] THEN LOOP; [toto.extent, toto.msg] _ DesignRules.MinSpace [rules, i, j ! DesignRules.DesignRuleError => LOOP]; rt.separation[i][j] _ rt.separation[j][i] _ toto ENDLOOP ENDLOOP; FOR i: Layer IN Layer DO IF tech.illegalLayer[i] THEN LOOP; rt.separation[i][gate] _ rt.separation[gate][i] _ rt.separation[pol][i] ENDLOOP; IF rt.separation[nwellCont][gate].extent = 0 THEN rt.separation[nwellCont][gate] _ rt.separation[pwellCont][gate] _ rt.separation[gate][nwellCont] _ rt.separation[gate][pwellCont] _ [3 * lambda, "VTI 6.5.2.3"]; rt.minWidth[gate] _ rt.minWidth[pol]; rt.maxWidth[gate] _ rt.maxWidth[pol]; rt.separation[nwell][nwell].msg _ "Well spacing or notch"; rt.minWidth[nwell].msg _ "Missing well (well width)"; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $DifViaSpace]; rt.viaOnFieldOxideAvoidsDiff _ toto; rt.viaOnFieldOxideAvoidsDiff.msg _ rt.viaOnFieldOxideAvoidsDiff.msg.Cat [" Separation to diff (advisory)"]; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $PolyViaSpace]; rt.viaOnFieldOxideAvoidsPoly _ toto; rt.viaOnFieldOxideAvoidsPoly.msg _ rt.viaOnFieldOxideAvoidsPoly.msg.Cat [" Separation to poly (advisory)"]; rt.fieldOxideSurroundsViaOnFieldOxide _ [MAX [rt.viaOnFieldOxideAvoidsDiff.extent, rt.viaOnFieldOxideAvoidsPoly.extent], "Separation to poly or diff (advisory)"]; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $DifViaSurround]; rt.diffSurroundsViaOnDiff _ toto; rt.diffSurroundsViaOnDiff.msg _ rt.diffSurroundsViaOnDiff.msg.Cat [" Insufficient diff surround (advisory)"]; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $PolyViaSurround]; rt.polySurroundsViaOnPoly _ toto; rt.polySurroundsViaOnPoly.msg _ rt.polySurroundsViaOnPoly.msg.Cat [" Insufficient poly surround (advisory)"]; rt.viaOnPolyAndDiff _ [1 * lambda, "Topology not flat (advisory)"]; -- more for the sake of robustness rt.viaSeparation _ [1 * lambda, "Via to via separation"]; -- only overlaps checked rt.viaOverGate _ [1 * lambda, "Via not allowed over gate"]; rt.viaOverPoly _ [1 * lambda, "Via not allowed over poly (advisory)"]; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $NWellPDifSurround]; rt.nWellSurround _ toto; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $NWellNWellDifSurround]; rt.nWellContact _ toto; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $NWellMaxConnect]; rt.wellContactSpacing _ toto; rt.wellContactSpacing.msg _ rt.wellContactSpacing.msg.Cat [" Well contact required (advisory)"]; -- 6.13.3.1 rt.wellConflict _ [2 * lambda, "p-well overlaps n-well"]; rt.NinN _ [2 * lambda, "n-diffusion in n-well"]; rt.PinP _ [2 * lambda, "p-diffusion in p-well"]; rt.isolatedWell _ [2 * lambda, "Isolated well"]; [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $ContactGateSpace]; -- rule 6.5.1.6 rt.diffCutToGate _ toto; -- rule 6.5.1.6 rt.largeDiffCutToGate _ rt.diffCutToGate; -- rule 6.5.1.6 [toto.extent, toto.msg] _ DesignRules.GetScaledValue [rules, $DifCutViaSpace]; -- rule 6.7.8 rt.difCutViaSpace _ toto; -- rule 6.7.8 rt.minPadSize.extent _ DesignRules.GetScaledValue [rules, $PadMetalWidth].v - 2 * DesignRules.GetScaledValue [rules, $PadMetalViaSurround].v; -- rule 6.9.2 - 2* 6.9.3 tech.ttMaxSep _ tech.ctMaxSep _ 0; FOR s: Layer IN Layer DO IF tech.illegalLayer[s] THEN LOOP; tech.ctMaxSep _ MAX [tech.ctMaxSep, rt.separation[pol][s].extent]; tech.ctMaxSep _ MAX [tech.ctMaxSep, rt.separation[gate][s].extent]; tech.ctMaxSep _ MAX [tech.ctMaxSep, rt.separation[pdif][s].extent] ENDLOOP; tech.ttMaxSep _ MAX [rt.separation[pol][pdif].extent, rt.separation[gate][pdif].extent, rt.separation[pol][pol].extent, rt.separation[pdif][pdif].extent]; tech.ruleTables _ rt; cachedTech _ [tech, rules.id] END; -- NewTechnology FlushTechCache: PUBLIC PROC ~ BEGIN cachedTech _ [t: NIL, tk: NIL] END; -- FlushTechCache IF NOT CDProperties.RegisterProperty [cMosBsimpleKey, $gbb] THEN FlushTechCache; [] _ CDProperties.RegisterProperty [cMosBcompleteKey, $gbb]; CoreProperties.StoreProperties [prop: cMosBsimpleKey, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc _ PrintChecked]]]]; CoreProperties.StoreProperties [prop: cMosBcompleteKey, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc _ PrintChecked]]]]; IF (CD.undefLayer # 0) THEN ERROR -- check the definition of specialLayers END. †DrcCmosbRulesImpl.Mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Opera di Giordano Bruno Beretta January 18, 1988 3:25:17 pm PST gbb January 21, 1988 3:24:13 pm PST Spinned out of DrcCMOSBimpl.Mesa because of "Storage overflow in pass 4" of compiler. cMosBsimple does the same thing SoS did; cMosBcomplete verifies all VTI rules eccept for wells and transistors, which are not in Core. Ze rulez Allocation of technology records. Fills the rule tables for a given set of design rules. Must be called before calling CheckDesignRules. The key must be one of those exported from a technology dependent part of Genista. Returns NIL if a key is invalid. Conservative (looks at all layers, not only the legal ones). Extractor cannot handle wells adequately. Try to filter out inappropriate layers. Via flatness rules In  units from the minimal metal border of the via (not from the cut). rt.viaOnFieldOxideAvoidsDiff _ DesignRules.GetScaledValue [rules, $DifViaSpace]; rt.viaOnFieldOxideAvoidsPoly _ DesignRules.GetScaledValue [rules, $PolyViaSpace]; rt.diffSurroundsViaOnDiff _ DesignRules.GetScaledValue [rules, $DifViaSurround]; rt.polySurroundsViaOnPoly _ DesignRules.GetScaledValue [rules, $PolyViaSurround]; In the following rules the extent is used only to determine the overlap of the error rectangle. Well rules rt.pWellSurround _ DesignRules.GetScaledValue [rules, $NWellNDifSpace]; rt.pWellSurround.msg _ rt.pWellSurround.msg.Cat ["n-well too small or p-diffusion too close to p-well "]; rt.nWellSurround _ DesignRules.GetScaledValue [rules, $NWellPDifSurround]; rt.nWellContact _ DesignRules.GetScaledValue [rules, $NWellNWellDifSurround]; rt.pWellContact _ DesignRules.GetScaledValue [rules, $PWellDifNWellSpace]; rt.wellContactSpacing _ DesignRules.GetScaledValue [rules, $NWellMaxConnect]; In the following rules the extent is used only to determine the overlap of the error rectangle. Exception to gate rules: rt.diffCutToGate _ DesignRules.GetScaledValue [rules, $ContactGateSpace]; -- rule 6.5.1.6 Miscellaneous rules: rt.difCutViaSpace _ DesignRules.GetScaledValue [rules, $DifCutViaSpace]; -- rule 6.7.8 Compute max separation Initialisation Κ‘˜codešœ™šœ<™Lšœ˜Kšœœœ˜Kšœœœ˜Lšœœœ4˜Ošœœœ6˜SKšΟe œŸ œP™†—Lšœ œœœ˜,Kšœœ˜Kšœœ˜-—head™Lš œ œ œœœ˜3š Οn œ œœœ˜]KšœwŸœŸœl™όKšœ˜K˜ unitš  œœœœœ ˜GK™