CDStitchedViasImpl.mesa
Copyright © 1987 by Xerox Corporation. All rights reversed.
Created by: Christian Jacobi, March 23, 1987 12:37:36 pm PST;
Using actual creation code from Brian Preas
Last edited by: Christian Jacobi, March 23, 1987 2:33:09 pm PST
Semi technology dependent:
Does not import technology, but works correctly only for a certain
range of technologies.
DIRECTORY
CD, CDAtomicObjects, CDBasics, CDCells, CDEvents, CDLayers, CDProperties, CDRects, CDSimpleRules, CDSimpleRulesBackdoor, CDOps, LRUCache, RealOps;
CDStitchedViasImpl:
CEDAR
PROGRAM
IMPORTS CD, CDAtomicObjects, CDBasics, CDCells, CDEvents, CDLayers, CDOps, CDProperties, CDRects, CDSimpleRules, CDSimpleRulesBackdoor, LRUCache, RealOps =
BEGIN
Rules: TYPE = CDSimpleRules.Rules;
GetSimpleBigContact:
PROC [size:
CD.Position, layer1, layer2:
CD.Layer]
RETURNS [obj:
CD.Object ←
NIL] = {
tech: CD.Technology ← CD.LayerTechnology[layer1];
IF tech#
NIL
THEN
SELECT tech.key
FROM
$cmosB => {
l1a: ATOM ← CD.LayerKey[layer1];
l2a: ATOM ← CD.LayerKey[layer2];
SELECT
TRUE
FROM
(l1a = $met2
AND l2a = $met)
OR (l1a = $met
AND l2a = $met2) =>
obj ← CDAtomicObjects.CreateAtomicOb[$C2LargeVia, size, tech];
(l1a = $pol
AND l2a = $met) =>
obj ← CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer1];
(l1a = $met
AND l2a = $pol) =>
obj ← CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer2];
ENDCASE => NULL;
};
ENDCASE => NULL
};
GetSingleViaForStitching:
PROC [rules: Rules, size:
CD.Position, layer1, layer2:
CD.Layer]
RETURNS [via:
CD.Object ←
NIL] = {
--this is semi technology dependent;
tech: CD.Technology ~ CD.LayerTechnology[layer1];
minBigContact: CD.Object ~ GetSimpleBigContact[[1, 1], layer1, layer2];
IF minBigContact=
NIL
OR tech=
NIL
THEN {
--no big contacts, must do it with small ones
via ← CDSimpleRules.Contact[rules, layer1, layer2]
}
ELSE {
-- big contact exists, determine size to use
lambda: CD.Number ~ tech.lambda;
ctSize: CD.Position ~ CD.InterestSize[minBigContact];
IF ctSize.x <= size.x
AND ctSize.y <= size.y
THEN {
--use 2, 3, or 4 lambda square vias that give largest perimeter
perim2x2: CD.Number ~ RealOps.ModalRound[size.x/(6*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(6*lambda), RealOps.FixMode]*8*lambda; -- 2x2 contacts go in a 6x6 square
perim3x3: CD.Number ~ RealOps.ModalRound[size.x/(7*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(7*lambda), RealOps.FixMode]*12*lambda; -- 3x3 contacts go in a 7x7 square
perim4x4: CD.Number ~ RealOps.ModalRound[size.x/(8*lambda), RealOps.FixMode]*RealOps.ModalRound[size.y/(8*lambda), RealOps.FixMode]*16*lambda; -- 4x4 contacts go in a 8x8 square
SELECT
TRUE
FROM
perim4x4 >= perim2x2
AND perim4x4 >= perim3x3 =>
via ← GetSimpleBigContact[[8*lambda, 8*lambda], layer1, layer2];
perim3x3 >= perim2x2
AND perim3x3 >= perim4x4 =>
via ← GetSimpleBigContact[[7*lambda, 7*lambda], layer1, layer2];
perim2x2 >= perim4x4
AND perim2x2 >= perim3x3 =>
via ← GetSimpleBigContact[[6*lambda, 6*lambda], layer1, layer2];
ENDCASE => ERROR;
}
ELSE {
-- big contact too big, must do it with small ones
via ← CDSimpleRules.Contact[rules, layer1, layer2]
}
}
};
MinDist:
PROC [rules: Rules, layer1, layer2:
CD.Layer]
RETURNS [m:
CD.Number←-1] = {
--sorry: halfway technology dependent
-- assumes contact exists
-- assumes contact is atomic object
minCt: CD.Object = CDSimpleRules.Contact[rules, layer1, layer2];
ap: CDAtomicObjects.AtomicObsSpecific = NARROW[minCt.specific];
layer1 ← CDLayers.AbstractToPaint[layer1];
layer2 ← CDLayers.AbstractToPaint[layer2];
FOR dl: CDAtomicObjects.DrawList ← ap.rList, dl.rest
WHILE dl#
NIL
DO
IF ~CDBasics.Inside[dl.first.r, ap.ir] THEN LOOP; --ignore wells
IF dl.first.layer=layer1 OR dl.first.layer=layer2 THEN LOOP; --ignore layer1, layer2
m ← MAX[m, CDSimpleRules.MinWidth[rules, dl.first.layer] +
CDSimpleRules.MinSpace[rules, dl.first.layer, dl.first.layer]];
ENDLOOP;
IF m<1 OR m>1000--catch in case of non implementation-- THEN ERROR;
};
InternalStitchedVia:
PROC [rules: Rules, size:
CD.Position, layer1, layer2:
CD.Layer]
RETURNS [via:
CD.Object] = {
Incl:
PROC [cell:
CD.Object, ob:
CD.Object, iPos:
CD.Position←[0, 0]] = {
[] ← CDCells.IncludeOb[cell: cell, ob: ob, trans: [CDBasics.SubPoints[iPos, CD.InterestBase[ob]]], mode: dontResize];
};
contact: CD.Object ← GetSingleViaForStitching[rules, size, layer1, layer2];
ctSize: CD.Position ← CD.InterestSize[contact];
IF ctSize.x >= size.x AND ctSize.y >= size.y THEN via ← contact
ELSE {
tech: CD.Technology ~ CD.LayerTechnology[layer1];
minDist: CD.Number ← MinDist[rules, layer1, layer2];
grid: CD.Number ← IF tech#NIL THEN tech.lambda ELSE 1;
step: CD.Position ← [MAX[minDist, ctSize.x], MAX[minDist, ctSize.y]];
numY: INT ← MAX[1, size.y/step.y];
numX: INT ← MAX[1, size.x/step.x];
ctCov: CD.Position ← [(numX-1)*step.x+ctSize.x, (numY-1)*step.y+ctSize.y];
off:
CD.Position ← [
(MAX[size.x-ctCov.x, 0]/(2*grid))*grid,
(MAX[size.y-ctCov.y, 0]/(2*grid))*grid
];
via ← CDCells.CreateEmptyCell[];
FOR indexY:
CD.Number
IN [0 .. numY)
DO
FOR indexX:
CD.Number
IN [0 .. numX)
DO
Incl[via, contact, [off.x+indexX*step.x, off.y+indexY*step.y]];
ENDLOOP;
ENDLOOP;
Incl[via, CDRects.CreateRect[size, layer1]];
Incl[via, CDRects.CreateRect[size, layer2]];
CDCells.ToSequenceMode[via];
[] ← CDCells.ResizeCell[NIL, via];
CDProperties.PutObjectProp[via, $CreatedBy, $StitchedVias];
IF ~CDOps.MakeImmutable[via] THEN ERROR;
};
};
DescRep:
TYPE =
RECORD [size:
CD.Position, layer1, layer2:
CD.Layer, ob:
CD.Object←
NIL, rules: Rules];
--Convention: layer1, layer2 are ordered!
cache: LRUCache.Handle ← LRUCache.Create[17, Hash, Equal];
Hash:
PROC [x:
REF]
RETURNS [h:
CARDINAL] = {
--it doesn't really matter whether the hash function is very good
d: REF DescRep = NARROW[x];
h ← (d.size.x
MOD 10000B)*3+(d.size.y
MOD 1000B)*19+d.layer1+d.layer2*13
--layer1, layer2 are ordered
};
Equal:
PROC [x, y:
REF]
RETURNS [
BOOL] = {
d1: REF DescRep = NARROW[x];
d2: REF DescRep = NARROW[y];
RETURN [d1.size=d2.size
AND d1.layer1=d2.layer1
AND d1.layer2=d2.layer2 AND d1.rules=d2.rules]
--layer1, layer2 are ordered
};
StitchedVia:
PROC [rules: Rules, design:
CD.Design, size:
CD.Position, l1, l2:
CD.Layer]
RETURNS [via:
CD.Object←
NIL] = {
d:
REF DescRep ←
NEW[DescRep←[
size: size,
layer1: MIN[l1, l2],
layer2: MAX[l1, l2],
rules: CDSimpleRules.GetRulesKey[rules]
]];
d ← NARROW[LRUCache.Include[cache, d].used];
IF d.ob#NIL THEN RETURN [via ← d.ob];
BEGIN
--not found with exact size
new: CD.Object ← InternalStitchedVia[size: size, layer1: l1, layer2: l2, rules: rules];
IF new=NIL OR size=CD.InterestSize[new] THEN RETURN [via ← d.ob ← new]
ELSE {
--size was not exact
d1:
REF DescRep ←
NEW[DescRep←[
size: CD.InterestSize[new],
layer1: d.layer1,
layer2: d.layer2,
rules: d.rules
]];
d1 ← NARROW[LRUCache.Include[cache, d1].used];
IF d1.ob#NIL THEN RETURN [via ← d.ob ← d1.ob]; --discard new to increase sharing
RETURN [via ← d.ob ← d1.ob ← new];
};
END;
--if we want to introduce caching per design, use cache ← CDValue.Fetch[...
};
EachTechnology:
CD.TechnologyEnumerator = {
SELECT tech.key
FROM
$cmosB, $CMosA, $NMosA =>
CDSimpleRulesBackdoor.RegisterRules[[
key: NIL,
technology: tech,
largeContact: StitchedVia
]];
ENDCASE => NULL;
};
RegisterTechnology: CDEvents.EventProc = {
[] ← EachTechnology[NARROW[x]]
};
CDEvents.RegisterEventProc[$RegisterTechnology, RegisterTechnology];
[] ← CD.EnumerateTechnologies[EachTechnology];
END.