CDDesignRulesImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier December 3, 1985 2:33:53 pm PST
-- Add the rules for difContact!
DIRECTORY
CD, CDAtomicObjects, CDBasics, CDCells, CDLayers, CDSimpleRules, CDSymbolicObjects, CMosB, CMosBObjects, CDDesignRules;
CDDesignRulesImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDLayers, CDSimpleRules, CDSymbolicObjects, CMosB, CMosBObjects
EXPORTS CDDesignRules =
BEGIN OPEN CDDesignRules;
Design Rules
FindRules: PUBLIC PROC [a: ATOM] RETURNS [dr: DesignRules] ~ {
targetTech: CD.Technology ← CD.FetchTechnology[a]; -- extract techno from atom instead!
lambda: INT ← targetTech.lambda;
dr ← NEW [DesignRulesRep ← [
atom: a,
techno: targetTech,
lambda: lambda,
gateSDNodeSp: 3*lambda,
standardTrSize: [4*lambda, 2*lambda],
trPolExt: 2*lambda,
trDifExt: 3*lambda,
pol: GetLayer[targetTech, $pol],
met: GetLayer[targetTech, $met],
met2: GetLayer[targetTech, $met2],
cut: GetLayer[targetTech, $cut],
cut2: GetLayer[targetTech, $cut2],
gate: CD.NewLayer[CMosB.cmosB, $gate],
ndif: GetLayer[targetTech, $ndif],
pdif: GetLayer[targetTech, $pdif],
wndif: GetLayer[targetTech, $wndif],
wpdif: GetLayer[targetTech, $wpdif],
nwell: GetLayer[targetTech, $nwel],
pwell: GetLayer[targetTech, $pwel],
nwellCont: GetLayer[targetTech, $nwelCont],
pwellCont: GetLayer[targetTech, $pwelCont]
]];
};
Distance rules
MinWidth: PUBLIC PROC [dr: DesignRules, layer: CD.Layer] RETURNS [dist: CD.Number] = {
dist ← CDSimpleRules.MinWidth[layer];
};
-- Layers are electrically non-connected
MinDist: PUBLIC PROC [dr: DesignRules, l1, l2: CD.Layer] RETURNS [dist: CD.Number] = {
OPEN dr;
IF l1=gate OR l2=gate THEN RETURN [0]; -- think more!
IF l1=nwell OR l2=nwell THEN RETURN [0]; -- strange!
IF l1=l2 THEN
RETURN [SELECT l1 FROM
met => 3*lambda,
met2 => 4*lambda,
pol => 2*lambda+lambda/2,
ndif, pdif => 3*lambda+lambda/2,
pwell, nwell => 10*lambda,
cut => 3*lambda,
cut2 => 4*lambda,
ENDCASE => 0
];
-- both layers are distinct
IF l2=cut2 THEN {l2 ← l1; l1 ← cut2};
IF l1=cut2 THEN {
IF IsDiff[dr, l2] THEN RETURN[2*lambda];
IF l2=pol THEN RETURN[2*lambda];
};
-- no more cut2 (via)
IF l1=met OR l2=met THEN RETURN [0];
IF l1=met2 OR l2=met2 THEN RETURN [0];
-- no more met or met2
IF l2=pol THEN {l2 ← l1; l1 ← pol};
IF l1=pol THEN {IF IsDiff[dr, l2] THEN RETURN[lambda] ELSE RETURN[0]};
-- no more poly
IF l2=ndif THEN {l2 ← l1; l1 ← ndif};
IF l1=ndif THEN {
RETURN [SELECT l2 FROM
pdif => 10*lambda,
nwell => 5*lambda,
ENDCASE => 0
];
};
-- no more ndif
IF l2=pdif THEN {l2 ← l1; l1 ← pdif};
IF l1=pdif THEN {
RETURN [SELECT l2 FROM
pwell => 5*lambda,
ENDCASE => 0
];
};
RETURN [0]
};
-- Layers are electrically connected
MinConnectedDist: PUBLIC PROC [dr: DesignRules, l1, l2: CD.Layer] RETURNS [dist: CD.Number] = {
OPEN dr;
IF l1=nwell OR l2=nwell THEN RETURN [0]; -- good enough for now!
IF l1=met OR l2=met THEN RETURN [0];
IF l1=met2 OR l2=met2 THEN RETURN [0];
-- no more met or met2
IF l1=l2 THEN RETURN [0];
-- both layers are distinct
IF l2=cut2 THEN {l2 ← l1; l1 ← cut2};
IF l1=cut2 THEN {    -- flatness rules
IF IsDiff[dr, l2] THEN RETURN[2*lambda];
IF l2=pol THEN RETURN[2*lambda];
};
-- no more cut2 (via)
IF l2=pol THEN {l2 ← l1; l1 ← pol};
IF l1=pol THEN {IF IsDiff[dr, l2] THEN RETURN[lambda] ELSE RETURN[0]}; -- other than dif?
-- no more poly
IF l2=ndif THEN {l2 ← l1; l1 ← ndif};
IF l1=ndif THEN {
RETURN [SELECT l2 FROM
pdif => 10*lambda,
nwell => 5*lambda,
ENDCASE => 0
];
};
-- no more ndif
IF l2=pdif THEN {l2 ← l1; l1 ← pdif};
IF l1=pdif THEN {
RETURN [SELECT l2 FROM
pwell => 5*lambda,
ENDCASE => 0
];
};
RETURN [0]
};
Object generators
GetTechnology: PUBLIC PROC [dr: DesignRules] RETURNS [CD.Technology] ~ {
RETURN[dr.techno];
};
-- used when laying out a chip in a target technology (also duplicated in StixImpl)
GetLayer: PUBLIC PROC [technology, layer: REF] RETURNS [CD.Layer] ~ {
targetTech: CD.Technology ← NARROW[technology];
color: ATOMNARROW[layer];
RETURN [CDSimpleRules.GetLayer[targetTech, color]];
};
-- all dimensions in CD units, i.e. the multiplication by lambda has been done
-- zero means default value
Pin: PUBLIC PROC [size: CD.Position] RETURNS [CD.Object] ~ {
RETURN [CDSymbolicObjects.CreatePin[size]];
};
Rect: PUBLIC PROC [size: CD.Position, layer: CD.Layer] RETURNS [CD.Object] ~ {
RETURN [CDSimpleRules.Rect[size, layer]];
};
Contact: PUBLIC PROC [dr: DesignRules, l1, l2: CD.Layer, size: CD.Position] RETURNS [CD.Object] = {
RETURN [CDSimpleRules.Contact[l1, l2]];
};
-- size is [w, l], not the IRect
Transistor: PUBLIC PROC [dr: DesignRules, difL: CD.Layer, w, l: INT] RETURNS [CD.Object] = {
OPEN dr;
IF w= 0 THEN w ← standardTrSize.x;
IF l= 0 THEN l ← standardTrSize.y;
RETURN [CMosBObjects.CreateTransistor[size: [w+2*trPolExt, l+2*trDifExt], difLayer: difL]];
};
Getting information on the inside
-- Explode the StickPtr into a dummy cells containing only pins
Explode: PUBLIC PROC [dr: DesignRules, object: CD.Object] RETURNS [dummy: CD.Object] ~ {
OPEN dr;
dummy ← CDCells.CreateEmptyCell[];
SELECT TRUE FROM
IsMosContact[object] => {  -- any contact
dRects: DRects ← NARROW[object.specificRef, CDAtomicObjects.AtomicObsPtr].rList;
FOR l: DRects ← dRects, l.rest WHILE l#NIL DO
InsertPin[dummy, "contact", l.first.r, l.first.lev];
ENDLOOP;
};
IsWire[object] => { -- any rectangle
inLayer: CD.Layer ← InsideLayer[object.layer];
rect: CD.Rect ← CD.InterestRect[object];
surList: LIST OF LayerAndDistance ← NeedSurround[dr, object.layer];
InsertPin[dummy, "wire", rect, inLayer];
IF surList#NIL THEN {
rect ← CDBasics.Extend[rect, surList.first.amount]; -- 5 l
InsertPin[dummy, "wire", rect, surList.first.layer]; -- nWell
};
};
IsMosTransistor[object] => {
inLayer: CD.Layer ← InsideLayer[object.layer];
dGate: INT ← lambda; -- a hack
gate, ch1, ch2: CD.Rect ← CD.InterestRect[object]; -- bouding box of the transistor
gate ← [gate.x1, gate.y1+trDifExt, gate.x2, gate.y2-trDifExt];
ch1 ← [ch1.x1+trPolExt, ch1.y1, ch1.x2-trPolExt, ch1.y1+trDifExt-dGate];
ch2 ← [ch2.x1+trPolExt, ch2.y2-trDifExt+dGate, ch2.x2-trPolExt, ch2.y2];
InsertPin[dummy, "gate", gate, pol];
InsertPin[dummy, "ch1", ch1, inLayer];
InsertPin[dummy, "ch2", ch2, inLayer];
};
IsPin[object] => {};
ENDCASE => ERROR;
};
Well surround rules
NeedSurround: PUBLIC PROC [dr: DesignRules, layer: CD.Layer] RETURNS [surList: LIST OF LayerAndDistance] = {
OPEN dr;
IF layer#wpdif THEN RETURN[NIL];
surList ← LIST[[layer: nwell, amount: 5*lambda]];
};
Private procs
IsDiff: PROC [dr: DesignRules, layer: CD.Layer] RETURNS [BOOL] =
{OPEN dr;
RETURN[layer=ndif OR layer=pdif OR layer=wndif OR layer=wpdif OR layer=nwellCont OR layer=pwellCont]};
InsideLayer: PROC [layer: CD.Layer] RETURNS [inLayer: CD.Layer] ~ {
RETURN [CDLayers.AbstractToPaint[layer]]};
InsertPin: PROC [cell: CD.Object, name: ROPE, rect: CD.Rect, lay: CD.Layer] ~ {
pinOb: CD.Object ← CDSymbolicObjects.CreatePin[CDBasics.SizeOfRect[rect]];
pin: CD.Instance ← CDCells.IncludeOb[NIL, cell, pinOb, CDBasics.BaseOfRect[rect], 0, interrestCoords, interrestCoords].newInst;
CDSymbolicObjects.SetLayer[pin, lay];
CDSymbolicObjects.SetName[pin, name];
};
Decomposition in pins
IsPin: PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN[CDSymbolicObjects.IsSymbolicOb[ob]]};
IsWire: PROC [ob: CD.Object] RETURNS [BOOL] ~ {
RETURN[ob.class.wireTyped AND ~ob.class.symbolic]};
IsMosContact: PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN[IsMosViaContact[ob] OR IsMosCutContact[ob]]};
IsMosViaContact: PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN[ob.class=CD.FetchObjectClass[$C2Via, CMosB.cmosB]]};
IsMosCutContact: PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN[ob.class=CD.FetchObjectClass[$C2SimpleCon, CMosB.cmosB]
OR ob.class=CD.FetchObjectClass[$C2WellSimpleCon, CMosB.cmosB]]};
IsMosTransistor: PROC [ob: CD.Object] RETURNS [BOOL] = {
RETURN[ob.class=CD.FetchObjectClass[$C2Trans, CMosB.cmosB]
OR ob.class=CD.FetchObjectClass[$C2WellTrans, CMosB.cmosB]]};
END.