DesignRulesImpl.mesa 
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Barth, April 27, 1987 2:53:58 pm PDT
gbb April 30, 1987 6:06:46 pm PDT
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;
Creation
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;
};
Operations
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.STREAMFS.StreamOpen[template];
out: IO.STREAMFS.StreamOpen[filled, $create];
{
ENABLE UNWIND => {
IO.Close[in];
IO.Close[out];
};
UNTIL IO.EndOf[in] DO
c: CHARIO.GetChar[in];
IF c='$ THEN {
id: Rope.ROPEIO.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];
};
Rule Set Access
GetScaledValue: PUBLIC PROC [rules: Rules, id: ATOM] RETURNS [v: CD.Number ← 0, d: Rope.ROPENIL] = {
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.ROPENIL] = {
[w, d] ← CheckAndScale[rules, FindRuleValueByTypeAndLayer[rules, width, layer]];
};
MaxWidth: PUBLIC PROC [rules: Rules, layer: CD.Layer] RETURNS [w: CD.Number ← 0, d: Rope.ROPENIL] = {
[w, d] ← CheckAndScale[rules, FindRuleValueByTypeAndLayer[rules, maxWidth, layer]];
};
MinSpace: PUBLIC PROC [rules: Rules, l1, l2: CD.Layer] RETURNS [s: CD.Number ← 0, d: Rope.ROPENIL] = {
[s, d] ← CheckAndScale[rules, IF l1=l2 THEN FindRuleValueByTypeAndLayer[rules, intraspace, l1] ELSE FindRuleValueByTypeAndLayers[rules, interspace, l1, l2]];
};
Object Construction
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]
};
Hole: PUBLIC PROC [rules: Rules, l1, l2: CD.Layer, l, w: INT ← 0, scale: INT ← 1] RETURNS [hole: CD.Object] = {
h: Hole ← FindHole[rules, l1, l2];
mw: CD.Number ← MinWidth[rules, h.cutLayer];
sl: CD.Number ← IF l=0 THEN mw ELSE CheckWidthViolation[rules, l, scale, mw];
sw: CD.Number ← IF w=0 THEN mw ELSE CheckWidthViolation[rules, w, scale, mw];
We've checked the request against the design rule database. Now generate the hole assuming CMosB technology since to do otherwise would be a pain until the design rule database defines the layers and layer combinations as well as the numbers.
hole ← SELECT h.cutLayer FROM
CMosB.cut2 => CMosBObjects.CreateLargeVia[[sl,sw]],
CMosB.cut => IF h.layer2=CMosB.pol THEN CMosBObjects.CreateLargePolyCon[[sl,sw]] ELSE CMosBObjects.CreateLargeDifCon[[sl,sw], h.layer2],
ENDCASE => ERROR;
};
Transistor: PUBLIC PROC [rules: Rules, l, w, a: INT ← 0, scale: INT ← 1] RETURNS [transistor: CD.Object] = {
};
Utilities
FindHole: PROC [rules: Rules, l1, l2: CD.Layer] RETURNS [hole: Hole ← NIL] = {
FOR hl: HoleList ← rules.holes, hl.rest UNTIL hl=NIL DO
h: Hole ← hl.first;
IF (h.layer1=l1 AND h.layer2=l2) OR (h.layer1=l2 AND h.layer2=l1) THEN {
hole ← h;
EXIT;
};
ENDLOOP;
};
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.ROPENIL] = {
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.