<> <> <> <> DIRECTORY Atom, CD, CDProperties, CDRects, DesignRules, FS, IO, Real, RefTab, Rope; DesignRulesImpl: CEDAR PROGRAM IMPORTS Atom, CDProperties, CDRects, FS, IO, Real, RefTab, Rope EXPORTS DesignRules = BEGIN OPEN DesignRules; DesignRuleError: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; <> <<>> NewRules: PUBLIC PROC [id: ATOM, technology: CD.Technology, micronsPerLambdaValue: INT, micronsPerLambdaScale: INT _ 1] RETURNS [rules: Rules] = { rules _ NEW[RulesRec _ [id, technology, micronsPerLambdaValue, micronsPerLambdaScale]]; }; <<>> NewLayer: PUBLIC PROC [rules: Rules, id: ATOM, cifSymbol: Rope.ROPE, name: Rope.ROPE, description: Rope.ROPE, cdLayer: CD.Layer] RETURNS [layer: Layer] = { layer _ NEW[LayerRec _ [id, cifSymbol, name, description, cdLayer]]; rules.layers _ CONS[layer, rules.layers]; }; <<>> NewImplicitLayer: PUBLIC PROC [rules: Rules, layer, implicit: Layer, surround: RuleValue] = { layer.implicitLayers _ CONS[NEW[ImplicitLayerRec _ [implicit, surround]], layer.implicitLayers]; }; <<>> NewHoleType: PUBLIC PROC [rules: Rules, id: ATOM, layer1, layer2, cutLayer: Layer, layer1SurroundRule, layer2SurroundRule: RuleValue] = { rules.holes _ CONS[NEW[HoleTypeRec _ [id, layer1, layer2, cutLayer, layer1SurroundRule, layer2SurroundRule]], rules.holes]; }; <<>> NewMOSTransistorType: PUBLIC PROC [rules: Rules, id: ATOM, gate, sourceDrain, bulk: Layer, gateExtension, sourceDrainExtension, bulkSurround: RuleValue] = { rules.mosTransistors _ CONS[NEW[MOSTransistorTypeRec _ [id, gate, sourceDrain, bulk, gateExtension, sourceDrainExtension, bulkSurround]], rules.mosTransistors]; }; <<>> NewRule: PUBLIC PROC [rules: Rules, id: ATOM, type: RuleType, layer1, layer2: Layer, value: INT, name: Rope.ROPE, scale: INT _ 1] = { rules.values _ CONS[NEW[RuleValueRec _ [id, type, layer1, layer2, value, scale, name, FALSE]], rules.values]; }; <<>> NewMicronRule: PUBLIC PROC [rules: Rules, id: ATOM, type: RuleType, layer1, layer2: Layer, value: INT, name: Rope.ROPE, scale: INT _ 1] = { rules.values _ CONS[NEW[RuleValueRec _ [id, type, layer1, layer2, value, scale, name, TRUE]], rules.values]; }; <<>> FindRuleValue: PUBLIC PROC [rules: Rules, id: ATOM] RETURNS [ruleValue: RuleValue _ NIL] = { FOR rvl: RuleValueList _ rules.values, rvl.rest UNTIL rvl=NIL DO IF rvl.first.id=id THEN { ruleValue _ rvl.first; EXIT; }; ENDLOOP; }; <<>> <> ruleSets: RefTab.Ref _ RefTab.Create[]; RegisterRuleSet: PUBLIC PROC [rules: Rules] = { ruleValueTab: RefTab.Ref _ RefTab.Create[]; [] _ RefTab.Store[x: ruleSets, key: rules.id, val: rules]; FOR rvl: RuleValueList _ rules.values, rvl.rest UNTIL rvl=NIL DO IF NOT RefTab.Store[x: ruleValueTab, key: rvl.first.id, val: rvl.first.id] THEN SIGNAL DesignRuleError["Not a unique rule value id"]; [] _ CheckAndScale[rules, rvl.first]; ENDLOOP; }; <<>> GetRuleSet: PUBLIC PROC [id: ATOM] RETURNS [rules: Rules] = { IF (rules _ NARROW[RefTab.Fetch[x: ruleSets, key: id].val])=NIL THEN SIGNAL DesignRuleError["Can't find rule set"]; }; <<>> CopyRuleSet: PUBLIC PROC [rules: Rules] RETURNS [newRules: Rules] = { layerTable: RefTab.Ref _ RefTab.Create[]; ruleValueTable: RefTab.Ref _ RefTab.Create[]; newRules _ NEW[RulesRec _ rules^]; newRules.layers _ NIL; newRules.holes _ NIL; newRules.mosTransistors _ NIL; newRules.values _ NIL; FOR layerList: LayerList _ rules.layers, layerList.rest UNTIL layerList=NIL DO l: Layer _ NEW[LayerRec _ layerList.first^]; newRules.layers _ CONS[l, newRules.layers]; IF NOT RefTab.Store[x: layerTable, key: layerList.first, val: l] THEN ERROR; ENDLOOP; FOR ruleValueList: RuleValueList _ rules.values, ruleValueList.rest UNTIL ruleValueList=NIL DO v: RuleValue _ NEW[RuleValueRec _ ruleValueList.first^]; v.layer1 _ NARROW[RefTab.Fetch[x: layerTable, key: v.layer1].val]; v.layer2 _ NARROW[RefTab.Fetch[x: layerTable, key: v.layer2].val]; newRules.values _ CONS[v, newRules.values]; IF NOT RefTab.Store[x: ruleValueTable, key: ruleValueList.first, val: v] THEN ERROR; ENDLOOP; FOR layerList: LayerList _ newRules.layers, layerList.rest UNTIL layerList=NIL DO oill: ImplicitLayerList _ layerList.first.implicitLayers; layerList.first.implicitLayers _ NIL; FOR ill: ImplicitLayerList _ oill, ill.rest UNTIL ill=NIL DO il: ImplicitLayer _ NEW[ImplicitLayerRec]; il.layer _ NARROW[RefTab.Fetch[x: layerTable, key: ill.first.layer].val]; il.surround _ NARROW[RefTab.Fetch[x: ruleValueTable, key: ill.first.surround].val]; layerList.first.implicitLayers _ CONS[il, layerList.first.implicitLayers]; ENDLOOP; ENDLOOP; FOR holeList: HoleTypeList _ rules.holes, holeList.rest UNTIL holeList=NIL DO h: HoleType _ NEW[HoleTypeRec _ holeList.first^]; h.layer1 _ NARROW[RefTab.Fetch[x: layerTable, key: h.layer1].val]; h.layer2 _ NARROW[RefTab.Fetch[x: layerTable, key: h.layer2].val]; h.cutLayer _ NARROW[RefTab.Fetch[x: layerTable, key: h.cutLayer].val]; h.layer1Surround _ NARROW[RefTab.Fetch[x: ruleValueTable, key: h.layer1Surround].val]; h.layer2Surround _ NARROW[RefTab.Fetch[x: ruleValueTable, key: h.layer2Surround].val]; newRules.holes _ CONS[h, newRules.holes]; ENDLOOP; FOR mosTranList: MOSTransistorTypeList _ rules.mosTransistors, mosTranList.rest UNTIL mosTranList=NIL DO t: MOSTransistorType _ NEW[MOSTransistorTypeRec _ mosTranList.first^]; t.gate _ NARROW[RefTab.Fetch[x: layerTable, key: t.gate].val]; t.sourceDrain _ NARROW[RefTab.Fetch[x: layerTable, key: t.sourceDrain].val]; t.bulk _ NARROW[RefTab.Fetch[x: layerTable, key: t.bulk].val]; t.gateExtension _ NARROW[RefTab.Fetch[x: ruleValueTable, key: t.gateExtension].val]; t.sourceDrainExtension _ NARROW[RefTab.Fetch[x: ruleValueTable, key: t.sourceDrainExtension].val]; t.bulkSurround _ NARROW[RefTab.Fetch[x: ruleValueTable, key: t.bulkSurround].val]; newRules.mosTransistors _ CONS[t, newRules.mosTransistors]; ENDLOOP; }; <<>> SetValue: PUBLIC PROC [rules: Rules, id: ATOM, value: INT, scale: INT _ 1] = { ruleValue: RuleValue _ FindRuleValue[rules, id]; IF ruleValue=NIL THEN SIGNAL DesignRuleError["Rule not found"] ELSE { ruleValue.value _ value; ruleValue.scale _ scale; [] _ CheckAndScale[rules, ruleValue]; }; }; FillInTemplate: PUBLIC PROC [rules: Rules, template: Rope.ROPE, filled: Rope.ROPE] = { in: IO.STREAM _ FS.StreamOpen[template]; out: IO.STREAM _ FS.StreamOpen[filled, $create]; { ENABLE UNWIND => { IO.Close[in]; IO.Close[out]; }; UNTIL IO.EndOf[in] DO c: CHAR _ IO.GetChar[in]; IF c='$ THEN { id: Rope.ROPE _ IO.GetID[in]; ruleValue: RuleValue _ FindRuleValue[rules, Atom.MakeAtom[id]]; IF ruleValue=NIL THEN ERROR DesignRuleError["Rule not found"]; IO.PutF[out, "%g", IF ruleValue.scale=1 THEN IO.int[ruleValue.value] ELSE IO.real[Real.Float[ruleValue.value] / Real.Float[ruleValue.scale]]]; } ELSE IO.PutChar[out, c]; ENDLOOP; IO.Close[in]; IO.Close[out]; }; }; <<>> designRuleProp: ATOM = $DesignRulesDesignRules; FetchRulesID: PUBLIC PROC [design: CD.Design] RETURNS [id: ATOM] = { id _ NARROW[CDProperties.GetDesignProp[from: design, prop: designRuleProp]]; }; <<>> StoreRulesID: PUBLIC PROC [design: CD.Design, id: ATOM] = { CDProperties.PutDesignProp[onto: design, prop: designRuleProp, val: id]; }; <<>> <> GetScaledValue: PUBLIC PROC [rules: Rules, id: ATOM] RETURNS [v: CD.Number _ 0, d: Rope.ROPE _ NIL] = { ruleValue: RuleValue _ FindRuleValue[rules, id]; IF ruleValue=NIL THEN SIGNAL DesignRuleError["Rule not found"] ELSE [v, d] _ CheckAndScale[rules, ruleValue]; }; MinWidth: PUBLIC PROC [rules: Rules, layer: CD.Layer] RETURNS [w: CD.Number _ 0, d: Rope.ROPE _ NIL] = { [w, d] _ CheckAndScale[rules, FindRuleValueByTypeAndLayer[rules, width, layer]]; }; MaxWidth: PUBLIC PROC [rules: Rules, layer: CD.Layer] RETURNS [w: CD.Number _ 0, d: Rope.ROPE _ NIL] = { [w, d] _ CheckAndScale[rules, FindRuleValueByTypeAndLayer[rules, maxWidth, layer]]; }; MinSpace: PUBLIC PROC [rules: Rules, l1, l2: CD.Layer] RETURNS [s: CD.Number _ 0, d: Rope.ROPE _ NIL] = { [s, d] _ CheckAndScale[rules, IF l1=l2 THEN FindRuleValueByTypeAndLayer[rules, intraspace, l1] ELSE FindRuleValueByTypeAndLayers[rules, interspace, l1, l2]]; }; <<>> <> Rectangle: PUBLIC PROC [rules: Rules, layer: CD.Layer, l: INT, w: INT _ 0, scale: INT _ 1] RETURNS [rectangle: CD.Object] = { mw: CD.Number _ MinWidth[rules, layer].w; sl: CD.Number _ CheckWidthViolation[rules, l, scale, mw]; sw: CD.Number _ IF w=0 THEN mw ELSE CheckWidthViolation[rules, w, scale, mw]; rectangle _ CDRects.CreateRect[[sl, sw], layer] }; <<>> <> <> <> <> <> <> <> < CMosBObjects.CreateLargeVia[[sl,sw]],>> < IF h.layer2=CMosB.pol THEN CMosBObjects.CreateLargePolyCon[[sl,sw]] ELSE CMosBObjects.CreateLargeDifCon[[sl,sw], h.layer2],>> < ERROR;>> <<};>> <<>> <> <<};>> <<>> <> <> <> <> <> <> <> <<};>> <> <<};>> <<>> FindRuleValueByTypeAndLayer: PROC [rules: Rules, type: RuleType, layer: CD.Layer] RETURNS [ruleValue: RuleValue _ NIL] = { CheckLayer[rules, layer]; FOR rvl: RuleValueList _ rules.values, rvl.rest UNTIL rvl=NIL DO rv: RuleValue _ rvl.first; IF rv.type=type AND rv.layer1.cdLayer=layer THEN { ruleValue _ rv; EXIT; }; ENDLOOP; }; <<>> FindRuleValueByTypeAndLayers: PROC [rules: Rules, type: RuleType, l1, l2: CD.Layer] RETURNS [ruleValue: RuleValue _ NIL] = { CheckLayer[rules, l1]; CheckLayer[rules, l2]; FOR rvl: RuleValueList _ rules.values, rvl.rest UNTIL rvl=NIL DO rv: RuleValue _ rvl.first; IF rv.type=type AND ((rv.layer1.cdLayer=l1 AND rv.layer2.cdLayer=l2) OR (rv.layer1.cdLayer=l2 AND rv.layer2.cdLayer=l1)) THEN { ruleValue _ rv; EXIT; }; ENDLOOP; }; <<>> CheckLayer: PROC [rules: Rules, layer: CD.Layer] = { FOR ll: LIST OF CD.Layer _ rules.technology.usedLayers, ll.rest UNTIL ll=NIL DO IF ll.first=layer THEN EXIT; REPEAT FINISHED => SIGNAL DesignRuleError["Layer is not defined for this technology"] ENDLOOP; }; <<>> CheckAndScale: PROC [rules: Rules, ruleValue: RuleValue] RETURNS [v: CD.Number _ 0, d: Rope.ROPE _ NIL] = { IF ruleValue#NIL THEN { v _ CheckAndScaleBasic[rules, ruleValue.value, ruleValue.scale, ruleValue.micronRule]; d _ Rope.Cat[Atom.GetPName[rules.id], " ", ruleValue.name]; }; }; <<>> CheckWidthViolation: PROC [rules: Rules, value, scale: INT, minimum: CD.Number] RETURNS [v: CD.Number] = { v _ CheckAndScaleBasic[rules, value, scale, FALSE]; IF v < minimum THEN SIGNAL DesignRuleError["Minimum width violation"]; }; <<>> CheckAndScaleBasic: PROC [rules: Rules, value, scale: INT, micronScale: BOOL] RETURNS [v: CD.Number] = { divisor: INT _ scale; v _ value * rules.technology.lambda; IF micronScale THEN { v _ v * rules.micronsPerLambdaScale; divisor _ divisor * rules.micronsPerLambdaValue; }; IF (v MOD divisor) # 0 THEN SIGNAL DesignRuleError["Scale violation"]; v _ v / divisor; }; <<>> END.