<> <> <> <> <> 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 <> [] _ CDProperties.RegisterProperty [cMosBsimpleKey, $gbb]; [] _ 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.