CDMEBESGeomFns.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
McCreight, December 10, 1986 6:24:56 pm PST
Hoel, February 27, 1986 3:33:39 pm PST
DIRECTORY
Atom, CD, CDBasics, CDMEBES, CStitching, IO;
CDMEBESGeomFns: CEDAR PROGRAM
IMPORTS Atom, CDBasics, CDMEBES, CStitching, IO =
BEGIN OPEN CDMEBES;
NOTFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
ComplementTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], $covered]};
basis: Tesselation ← GenerateCover[ms, spec.first, extInfluenceDiameter];
result ← NewTesselation[NIL];
[] ← basis.EnumerateArea[rect: CDBasics.universe, eachTile: ComplementTile, skip: $covered];
basis ← DisposeTesselation[basis];
END;
ANDFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
NilTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], NIL]};
result ← GenerateCover[ms, spec.first, extInfluenceDiameter];
FOR rest: LIST OF REF ANY ← spec.rest, rest.rest WHILE rest # NIL DO
term: Tesselation ← GenerateCover[ms, rest.first, extInfluenceDiameter];
[] ← term.EnumerateArea[rect: CDBasics.universe, eachTile: NilTile, skip: $covered];
term ← DisposeTesselation[term];
ENDLOOP;
END;
ANDNOTFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
NilTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], NIL]};
result ← GenerateCover[ms, spec.first, extInfluenceDiameter];
FOR rest: LIST OF REF ANY ← spec.rest, rest.rest WHILE rest # NIL DO
term: Tesselation ← GenerateCover[ms, rest.first, extInfluenceDiameter];
[] ← term.EnumerateArea[rect: CDBasics.universe, eachTile: NilTile, skip: NIL];
term ← DisposeTesselation[term];
ENDLOOP;
END;
ORFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
This is a very common case, so we speed it up by separating it into two lists: CDLayer's with nonnegative deltaDiameter's, and other things. We compute the other things first, and then take a single pass at the design for the CDLayer's with nonnegative deltaDiameter's.
CoverTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[tile.Area, $covered]};
layers: LIST OF CDLayer ← NIL;
otherThings: LIST OF REF ANYNIL;
FOR subList: LIST OF REF ANY ← spec, subList.rest WHILE subList # NIL DO
WITH subList.first SELECT FROM
layer: CDLayer =>
IF layer.deltaDiameter >= 0 THEN layers ← CONS[layer, layers]
ELSE otherThings ← CONS[layer, otherThings];
ENDCASE => otherThings ← CONS[subList.first, otherThings];
ENDLOOP;
IF otherThings = NIL THEN result ← NewTesselation[NIL]
ELSE
BEGIN
result ← GenerateCover[ms, otherThings.first, extInfluenceDiameter];
FOR rest: LIST OF REF ANY ← otherThings.rest, rest.rest WHILE rest # NIL DO
term: Tesselation ← GenerateCover[ms, rest.first, extInfluenceDiameter];
[] ← term.EnumerateArea[rect: CDBasics.universe, eachTile: CoverTile];
term ← DisposeTesselation[term];
ENDLOOP;
END;
IF layers # NIL THEN
DrawLayersWithPosDeltas[ms: ms, rects: result, layers: layers, extInfluenceDiameter: extInfluenceDiameter];
END;
RunRec: TYPE = RECORD [
desc: ROPE,
areaInSqMeters: REAL ← 0,
perimInMeters: Meters ← 0.0,
runsInMeters: ARRAY Sense OF RECORD [
sense: ROPE,
r: REF RunArray
]
];
RunArray: TYPE = RECORD [ ra: SEQUENCE size: NAT OF Meters ];
MeasureRuns: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
PixelRunArray: TYPE = RECORD [ ra: SEQUENCE size: NAT OF MEBESPixels ];
TadCoverRec: TYPE = RECORD [ sense: ROPE, maxInterestDist, minFeature: Tad ← 0, r: REF PixelRunArray ];
areaInSqPixels: INT ← 0;
perimInPixels: MEBESPixels ← 0;
table: ARRAY Sense OF REF TadCoverRec ← ALL[NIL];
runRef: REF RunRec ← NIL; -- for external consumption
mebesPixelPitch: Meters ← ms.mebesPixelPitch -- nm -- *1.0E-9;
tadsPerPixel: Tad = ms.mebesPixelPitch*ms.tadsPerNm;
LookForRuns: PROC [tile: CStitching.Tile, data: REF ANY]
-- CStitching.PerTileProc -- =
BEGIN
ComplainAboutFeature: PROC [ dia: Tad, pos: TadPosition ] =
BEGIN
chose: NAT = ComplainAt[ms: ms, pos: pos,
explanation: IO.PutFR["Too-small %g", IO.rope[c.sense]],
choice: LIST ["Reduce min feature", "Proceed"]];
SELECT chose FROM
1 => c.minFeature ← dia;
ENDCASE => NULL;
END;
EWRuns: PROC [ cov: CStitching.Tile, x1, x2: Tad ] =
BEGIN
IF cov.NEdge < keyTileArea.y2+c.maxInterestDist THEN
BEGIN
covHeightTads: Tad = cov.NEdge-keyTileArea.y2;
covHeightPixels: MEBESPixels = covHeightTads/tadsPerPixel;
FOR tile: CStitching.Tile ← cov.EN, tile.SW WHILE x1 < tile.EEdge DO
tx1: Tad = MAX[x1, tile.WEdge];
tx2: Tad = MIN[x2, tile.EEdge];
dxPixels: MEBESPixels = (tx2-tx1)/tadsPerPixel;
SELECT TRUE FROM
tx2 <= tx1 => NULL;
tile.value # keyTilevalue =>
BEGIN
IF covHeightTads = 0 THEN
perimInPixels ← perimInPixels+dxPixels;
EWRuns[cov: tile, x1: tx1, x2: tx2];
END;
covHeightTads >= c.minFeature =>
c.r[covHeightPixels] ← c.r[covHeightPixels]+dxPixels;
covHeightTads > 0 => -- IN (0..minFeature) --
BEGIN
ComplainAboutFeature[covHeightTads, [x: (tx1+tx2)/2, y: (cov.NEdge+keyTileArea.y2)/2]];
c.r[covHeightPixels] ← c.r[covHeightPixels]+dxPixels;
END;
ENDCASE => NULL;
ENDLOOP;
END;
END; -- of EWRuns
NSRuns: PROC [ cov: CStitching.Tile, y1, y2: Tad ] =
BEGIN
IF cov.EEdge < keyTileArea.x2+c.maxInterestDist THEN
BEGIN
covWidthTads: Tad = cov.EEdge-keyTileArea.x2;
covWidthPixels: MEBESPixels = covWidthTads/tadsPerPixel;
FOR tile: CStitching.Tile ← cov.NE, tile.WS WHILE y1 < tile.NEdge DO
ty1: MEBESPixels = MAX[y1, tile.SEdge];
ty2: MEBESPixels = MIN[y2, tile.NEdge];
dyPixels: MEBESPixels = (ty2-ty1)/tadsPerPixel;
SELECT TRUE FROM
ty2 <= ty1 => NULL;
tile.value # keyTilevalue =>
BEGIN
IF covWidthTads = 0 THEN perimInPixels ← perimInPixels+dyPixels;
NSRuns[cov: tile, y1: ty1, y2: ty2];
END;
covWidthTads >= c.minFeature =>
c.r[covWidthPixels] ← c.r[covWidthPixels]+dyPixels;
covWidthTads > 0 => -- IN (0..minFeature) --
BEGIN
ComplainAboutFeature[covWidthTads, [x: (cov.EEdge+keyTileArea.x2)/2, y: (ty1+ty2)/2]];
c.r[covWidthPixels] ← c.r[covWidthPixels]+dyPixels;
END;
ENDCASE => NULL;
ENDLOOP;
END;
END; -- of NSRuns
keyTilevalue: REF ANY = tile.value;
c: REF TadCoverRec = table[(IF keyTilevalue = NIL THEN cover ELSE space)];
keyTileArea: TadRect = tile.Area;
clippedKeyTileArea: TadRect = CDBasics.Intersection[ms.tadStripeClip, keyTileArea];
IF keyTilevalue # NIL THEN
areaInSqPixels ← areaInSqPixels+
((clippedKeyTileArea.x2-clippedKeyTileArea.x1)/tadsPerPixel)*
((clippedKeyTileArea.y2-clippedKeyTileArea.y1)/tadsPerPixel);
We examine first the north and then the east neighbors of this key rectangle, noting the nearest rectangle of the same kind in the direction of view.
IF keyTileArea.y2 IN (ms.tadStripeClip.y1 .. ms.tadStripeClip.y2] THEN
EWRuns[cov: tile, x1: clippedKeyTileArea.x1, x2: clippedKeyTileArea.x2];
IF keyTileArea.x2 IN (ms.tadStripeClip.x1 .. ms.tadStripeClip.x2] THEN
NSRuns[cov: tile, y1: clippedKeyTileArea.y1, y2: clippedKeyTileArea.y2];
END; -- of LookForRuns
GetCoverRec: PROC [sense: ROPE, l: LIST OF REF ANY] RETURNS [c: REF TadCoverRec] =
BEGIN
c ← NEW[TadCoverRec ← [sense: sense]];
c.maxInterestDist ← NARROW[l.first, REF Nm]^*ms.tadsPerNm;
c.minFeature ← NARROW[l.rest.first, REF Nm]^*ms.tadsPerNm;
c.r ← NEW[PixelRunArray[c.maxInterestDist/(ms.mebesPixelPitch*ms.tadsPerNm)]];
FOR width: MEBESPixels IN [0..c.r.size) DO
c.r[width] ← 0;
ENDLOOP;
END;
table[cover] ← GetCoverRec["cover", spec.rest.rest];
table[space] ← GetCoverRec["space", spec.rest.rest.rest.rest];
result ← GenerateCover[ms, spec.rest.first, extInfluenceDiameter+MAX[table[cover].maxInterestDist, table[space].maxInterestDist]];
[] ← result.EnumerateArea[rect: ms.tadStripeClip, eachTile: LookForRuns, skip: $none];
ms.data ← runRef ← NEW[RunRec ← [
desc: NARROW[spec.first],
areaInSqMeters: areaInSqPixels*mebesPixelPitch*mebesPixelPitch,
perimInMeters: perimInPixels*mebesPixelPitch,
runsInMeters: [
space: [sense: "space", r: NEW[RunArray[table[space].r.size]]],
cover: [sense: "cover", r: NEW[RunArray[table[cover].r.size]]]
]
]];
FOR sense: Sense IN Sense DO
FOR width: MEBESPixels IN [0..table[sense].r.size) DO
runRef.runsInMeters[sense].r[width] ← table[sense].r[width]*mebesPixelPitch;
ENDLOOP;
ENDLOOP;
END;
RestrictedEnlarge: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
PlaceNImplant: PROC [tile: CStitching.Tile, data: REF ANY]
-- CStitching.PerTileProc -- =
BEGIN
InteractWithPImplant: PROC [tile: CStitching.Tile, data: REF ANY]
-- CStitching.PerTileProc -- =
BEGIN
Relationship: TYPE = {pNn, pEn, pSn, pWn};
pTile: CStitching.Tile = tile;
pTileArea: TadRect = pTile.Area;
bestDir: Relationship;
bestGap: Tad ← -1;
tGap: Tad;
gaps: ARRAY Relationship OF Tad ← ALL[maxRadialExtension];
deInsertedArea: TadRect;
IF (tGap ← nTileArea.x1-pTileArea.x2)>bestGap THEN
{bestDir ← $pWn; bestGap ← tGap};
IF (tGap ← pTileArea.x1-nTileArea.x2)>bestGap THEN
{bestDir ← $pEn; bestGap ← tGap};
IF (tGap ← nTileArea.y1-pTileArea.y2)>bestGap THEN
{bestDir ← $pSn; bestGap ← tGap};
IF (tGap ← pTileArea.y1-nTileArea.y2)>bestGap THEN
{bestDir ← $pNn; bestGap ← tGap};
IF bestGap<0 THEN ERROR; -- design rule violation
IF NOT anyInteractingPImplant THEN
BEGIN
anyInteractingPImplant ← TRUE;
nImplPieces.ChangeRect[CDBasics.universe, NIL];
nImplPieces.ChangeRect[desiredNImplant, $covered];
END;
gaps[bestDir] ← bestGap/2;
deInsertedArea ← [x1: pTileArea.x1-gaps[$pEn], y1: pTileArea.y1-gaps[$pNn], x2: pTileArea.x2+gaps[$pWn], y2: pTileArea.y2+gaps[$pSn]];
IF CDBasics.NonEmpty[deInsertedArea] THEN nImplPieces.ChangeRect[deInsertedArea, NIL];
END;
CoverNegotiatedPiece: PROCEDURE [tile: CStitching.Tile, data: REF ANY]
-- CStitching.PerTileProc -- =
{area: TadRect = tile.Area; result.ChangeRect[area, $covered]};
nTile: CStitching.Tile = tile;
nTileArea: TadRect = nTile.Area;
desiredNImplant: TadRect = CDBasics.Extend[nTileArea, maxRadialExtension];
anyInteractingPImplant: BOOLFALSE;
[] ← pDif.EnumerateArea[rect: CDBasics.Extend[nTileArea, 2*maxRadialExtension], eachTile: InteractWithPImplant];
IF NOT anyInteractingPImplant THEN result.ChangeRect[desiredNImplant, $covered]
ELSE [] ← nImplPieces.EnumerateArea[desiredNImplant, CoverNegotiatedPiece];
END;
maxRadialExtension: Tad = NARROW[spec.first, REF Nm]^*ms.tadsPerNm;
nDif: Tesselation ← GenerateCover[ms, spec.rest.first, extInfluenceDiameter+2*maxRadialExtension];
pDif: Tesselation ← GenerateCover[ms, spec.rest.rest.first, extInfluenceDiameter+2*maxRadialExtension];
nImplPieces: Tesselation ← NewTesselation[];
result ← NewTesselation[];
[] ← nDif.EnumerateArea[rect: CDBasics.universe, eachTile: PlaceNImplant];
nDif ← DisposeTesselation[nDif];
pDif ← DisposeTesselation[pDif];
nImplPieces ← DisposeTesselation[nImplPieces];
END;
EnlargeFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
deltaDiameterNm: Nm = NARROW[spec.first, REF Nm]^;
deltaDiameterTads: MEBESPixels = deltaDiameterNm*ms.tadsPerNm;
SELECT deltaDiameterTads FROM
=0 => result ← GenerateCover[ms, spec.rest.first, extInfluenceDiameter];
>0 =>
BEGIN
EnlargeTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[Bloat[tile.Area, deltaDiameterTads], tile.value]};
basis: Tesselation ← GenerateCover[ms, spec.rest.first, extInfluenceDiameter+deltaDiameterTads];
result ← NewTesselation[NIL];
[] ← basis.EnumerateArea[rect: CDBasics.universe, eachTile: EnlargeTile];
basis ← DisposeTesselation[basis];
END;
<0 =>
BEGIN
EnlargeGap: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{result.ChangeRect[CDBasics.Intersection[CDBasics.universe, Bloat[tile.Area, -deltaDiameterTads]], tile.value]};
basis: Tesselation ← GenerateCover[ms, spec.rest.first, extInfluenceDiameter-deltaDiameterTads];
result ← NewTesselation[NIL];
result.ChangeRect[CDBasics.universe, $covered];
[] ← basis.EnumerateArea[rect: CDBasics.universe, eachTile: EnlargeGap, skip: $covered];
basis ← DisposeTesselation[basis];
END;
ENDCASE => ERROR;
END;
DeNotchFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
BEGIN
deltaDiams: ARRAY [-1..2] OF Nm ← ALL[0];
ndd: [0..2];
newSpec: REF;
FOR ndd𡤀, ndd+1 WHILE ndd<2 DO
WITH spec.first SELECT FROM
rnm: REF Nm => {deltaDiams[ndd] ← rnm^; spec ← spec.rest};
ENDCASE => EXIT;
ENDLOOP;
newSpec ← spec.first;
FOR i: [0..2] IN [0..ndd] DO
IF deltaDiams[i] # deltaDiams[i-1] THEN
newSpec ← LIST[$Enlarge, NEW[Nm ← (deltaDiams[i]-deltaDiams[i-1])], newSpec];
ENDLOOP;
result ← GenerateCover[ms, newSpec, extInfluenceDiameter];
END;
SizeLEqFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad ← 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- =
SizeLEq returns a tesselation of all isolated $covered rectangles from input tesselation L3 which are no larger than L1 x L2 nanometers, where L1, L2, and L3 are the elements of spec. Shapes larger than L1 x L2 nanometers, as well as non-rectangular shapes, are omitted. This was added February 27, 1986 to handle VTI's requirement to enlarge minimum size vias over diffusion. JHH.
BEGIN
sieveWidth: Nm = NARROW[spec.first, REF Nm]^;
sieveHeight: Nm = NARROW[spec.rest.first, REF Nm]^;
sieveWidthTads: MEBESPixels = MAX[sieveWidth, sieveHeight]*ms.tadsPerNm;
sieveHeightTads: MEBESPixels = MIN[sieveWidth, sieveHeight]*ms.tadsPerNm;
BEGIN
SizeFilterTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- =
{
tileWidth, tileHeight: Tad;
IsolatedTile: PROC [tile: CStitching.Tile] RETURNS [b:BOOLEAN] ~ {
Returns TRUE iff tile doesn't touch other tiles of the same value.
Assumes the cornerstitched plane has tiles of only two values.
en: CStitching.Tile ← tile.EN;
ws: CStitching.Tile ← tile.WS;
b ← (
(en.value # tile.value) AND (en.WEdge < tile.WEdge) AND
(ws.value # tile.value) AND (ws.EEdge > tile.EEdge)
);
};
tileWidth ← MAX[(tile.EEdge - tile.WEdge), (tile.NEdge - tile.SEdge)];
tileHeight ← MIN[(tile.EEdge - tile.WEdge), (tile.NEdge - tile.SEdge)];
IF (
IsolatedTile[tile] AND
(sieveWidthTads >= tileWidth) AND
(sieveHeightTads >= tileHeight)
) THEN
result.ChangeRect[rect: tile.Area, new: $covered];
};
result ← CStitching.NewTesselation[];
[] ← CStitching.EnumerateArea[
plane: GenerateCover[ms, spec.rest.rest.first, extInfluenceDiameter],
rect: CDBasics.universe,
eachTile: SizeFilterTile];
END;
END;
Init: PROC =
BEGIN
Atom.PutProp[$CDMEBESCoverProcs, $NOT, NEW[CoverProc ← NOTFn]];
Atom.PutProp[$CDMEBESCoverProcs, $AND, NEW[CoverProc ← ANDFn]];
Atom.PutProp[$CDMEBESCoverProcs, $ANDNOT, NEW[CoverProc ← ANDNOTFn]];
Atom.PutProp[$CDMEBESCoverProcs, $OR, NEW[CoverProc ← ORFn]];
Atom.PutProp[$CDMEBESCoverProcs, $MeasureRuns, NEW[CoverProc ← MeasureRuns]];
Atom.PutProp[$CDMEBESCoverProcs, $RestrictedEnlarge, NEW[CoverProc ← RestrictedEnlarge]];
Atom.PutProp[$CDMEBESCoverProcs, $Enlarge, NEW[CoverProc ← EnlargeFn]];
Atom.PutProp[$CDMEBESCoverProcs, $DeNotch, NEW[CoverProc ← DeNotchFn]];
Atom.PutProp[$CDMEBESCoverProcs, $SizeLEq, NEW[CoverProc ← SizeLEqFn]];
END;
Init[];
END. -- of CDMEBESGeomFns