SpinifexExtrasImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Written by Shand, June 12, 1984 3:11:49 pm PDT
Last Edited by: Shand, July 28, 1984 7:23:52 pm PDT
DIRECTORY
CD USING [Rect, DesignNumber, DesignPosition, DesignRect, Orientation, Level, ObjectProcs, ApplicationPtr, DrawRef, DrawRectProc, NewNullDeviceDrawRef],
CDInline USING [Extend, NonEmpty, universe],
SpinifexCircuit USING [Circuit, CircuitNode, CircuitConstraint, SpinifexLayerIndex, AddRect, AddBox],
CornerStitching USING [NewTesselation, Tesselation, ChangeRect, EnumerateArea, ChangeTile, Region, PerTileProc, Area, Value, TilePtr, WestEdge, EastEdge, SouthEdge, NorthEdge, SWestNeighbour, NEastNeighbour, WSouthNeighbour, ENorthNeighbour],
SpinifexExtras
;
SpinifexExtrasImpl: CEDAR PROGRAM
IMPORTS CD, CDInline, SpinifexCircuit, CornerStitching
EXPORTS SpinifexExtras
~ BEGIN
polPtr: REF INT ← NEW[INT];
difPtr: REF INT ← NEW[INT];
chanPtr: REF INT ← NEW[INT];
Post:
TYPE ~
RECORD [
r: CD.DesignRect,
l: CD.Level
];
AddRectParameters:
TYPE ~
RECORD [
tes: REF CornerStitching.Tesselation,
cir: REF SpinifexCircuit.Circuit,
PerDrawRect: SpinifexExtras.PerDrawRectProc,
gateNode: REF SpinifexCircuit.CircuitNode,
postRectList: LIST OF REF Post,
clientData: REF ANY
];
AddRectangle:
CD.DrawRectProc
-- [r: DesignRect, l: Level, pr: DrawRef] -- ~ {
-- I don't care about efficiency here I'm afraid
data: REF AddRectParameters ~ NARROW[ pr.devicePrivate];
level: SpinifexExtras.TransistorMaterial ~ data.PerDrawRect[r, l, data.clientData];
IF ~CDInline.NonEmpty[r] THEN RETURN;
SELECT level
FROM
nothing => NULL;
diffusion => {
occupants: LIST OF REF CornerStitching.Region ← NARROW[data.tes.EnumerateArea[r]];
data.tes.ChangeRect[ r, difPtr];
WHILE occupants #
NIL
DO
SELECT occupants.first.value
FROM
polPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr];
chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr];
ENDCASE;
occupants ← occupants.rest
ENDLOOP
};
polysilicon => {
occupants: LIST OF REF CornerStitching.Region ← NARROW[data.tes.EnumerateArea[r]];
data.tes.ChangeRect[ r, polPtr];
WHILE occupants #
NIL
DO
SELECT occupants.first.value
FROM
difPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr];
chanPtr => data.tes.ChangeRect[ rect~occupants.first.rect, newValue~chanPtr];
ENDCASE;
occupants ← occupants.rest
ENDLOOP;
IF data.gateNode =
NIL
THEN
data.gateNode ← data.cir.AddRect[lev~l, dim~r]
ELSE
[] ← data.cir.AddRect[lev~l, dim~r, value~data.gateNode];
};
postProcess => {
-- Save on list and process and enumerate Diffusion nodes in this region later.
data.postRectList ← CONS[ NEW[Post ← [r~ r, l~ l]], data.postRectList];
};
ENDCASE; -- I guess the end case is implant, well let me tell you one thing I don't deal with implant OK.
};
ProcessMosTransistor:
PUBLIC
PROCEDURE [
appl:
CD.ApplicationPtr,
pos:
CD.DesignPosition,
orient:
CD.Orientation,
cir:
REF SpinifexCircuit.Circuit,
difSpinifex, polSpinifex: SpinifexCircuit.SpinifexLayerIndex,
difChannel, channelEdge:
REF SpinifexCircuit.CircuitConstraint,
difToPolSep:
CD.DesignNumber,
PerDrawRect: SpinifexExtras.PerDrawRectProc,
data:
REF
ANY ←
NIL,
PostProcessor: SpinifexExtras.ReportDifProc ←
NIL]
RETURNS
[gateNode:
REF SpinifexCircuit.CircuitNode, sourceDrainNodes:
LIST
OF
REF SpinifexCircuit.CircuitNode, sourceDrainCount:
INTEGER] ~ {
-- When we get these crazy bent guys well I tell you we just don't know what to do, so we grab ourselves a tile world and plunk it down in that, then maybe we can start to make sense of it.
FindChannelEdge: CornerStitching.PerTileProc
-- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{
occupants, tmp: LIST OF REF CornerStitching.Region;
tes: REF CornerStitching.Tesselation ~ NARROW[data];
IF tile.Value = chanPtr
THEN {
occupants ← NARROW[tes.EnumerateArea[CDInline.Extend[tile.Area, difToPolSep]]];
WHILE occupants #
NIL
DO
tmp ← occupants.rest;
IF occupants.first.value = difPtr
THEN {
occupants.rest ← chEdge;
chEdge ← occupants
};
occupants ← tmp
ENDLOOP
}
};
ConvertMaskGeom: CornerStitching.PerTileProc
-- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{
-- We are fairly liberal with interest boundaries here, its could be made a lot tighter as is done in the processing of normal Xstrs. All this means is that bent Xstrs will be instantiated for analysis even when they appear in isolation. Acutally this may be what we want since bent transistors are not so constrained that errors are totally precluded in an isolated object (they are for straight Xstrs). Also we let the other code calculate areas and perims, it is likely to be inaccurate.
SELECT tile.Value
FROM
difPtr => {
CheckChangeAndAdd:
PROCEDURE [t: CornerStitching.TilePtr] ~ {
IF t.Value = difPtr
THEN {
tranGeom.ChangeTile[ t, node];
[] ← cir.AddRect[ lev~appl.ob.level, dim~t.Area, value~node]
}
ELSE
WITH t.Value
SELECT
FROM
cn: REF SpinifexCircuit.CircuitNode => cn.superceded ← node;
ENDCASE;
};
node: REF SpinifexCircuit.CircuitNode ← cir.AddRect[lev~appl.ob.level, dim~tile.Area];
sdList ← CONS[ node, sdList];
tranGeom.ChangeTile[ tile, node];
FOR st: CornerStitching.TilePtr ← tile.WSouthNeighbour, st.NEastNeighbour
WHILE st.WestEdge < tile.EastEdge
DO
CheckChangeAndAdd[ st];
ENDLOOP;
FOR wt: CornerStitching.TilePtr ← tile.SWestNeighbour, wt.ENorthNeighbour
WHILE wt.SouthEdge < tile.NorthEdge
DO
CheckChangeAndAdd[ wt];
ENDLOOP;
FOR nt: CornerStitching.TilePtr ← tile.ENorthNeighbour, nt.SWestNeighbour
WHILE nt.EastEdge > tile.WestEdge
DO
CheckChangeAndAdd[ nt];
ENDLOOP;
FOR et: CornerStitching.TilePtr ← tile.NEastNeighbour, et.WSouthNeighbour
WHILE et.NorthEdge > tile.SouthEdge
DO
CheckChangeAndAdd[ et];
ENDLOOP;
};
chanPtr => {
[] ← cir.AddBox[ spinifexLayer~difSpinifex, dim~tile.Area, value~difChannel];
};
polPtr => NULL;
ENDCASE
};
AddParm: REF AddRectParameters ~ NEW[AddRectParameters];
tranGeom: REF CornerStitching.Tesselation ~ CornerStitching.NewTesselation[];
sdList: LIST OF REF SpinifexCircuit.CircuitNode ← NIL;
dr: CD.DrawRef ~ CD.NewNullDeviceDrawRef[NIL];
chEdge: LIST OF REF CornerStitching.Region ← NIL;
AddParm.tes ← tranGeom;
AddParm.cir ← cir;
AddParm.PerDrawRect ← PerDrawRect;
AddParm.gateNode ← NIL;
AddParm.postRectList ← NIL;
AddParm.clientData ← data;
dr.drawRect ← AddRectangle;
dr.saveRect ← AddRectangle;
dr.devicePrivate ← AddParm;
appl.ob.p.drawMe[appl, pos, orient, dr];
IF (gateNode ← AddParm.gateNode) = NIL THEN ERROR;
[] ← tranGeom.EnumerateArea[ rect~CDInline.universe, perTile~FindChannelEdge, data~tranGeom];
[] ← tranGeom.EnumerateArea[ rect~CDInline.universe, perTile~ConvertMaskGeom];
IF PostProcessor #
NIL
THEN
FOR pL:
LIST
OF
REF Post ← AddParm.postRectList, pL.rest
WHILE pL #
NIL
DO
FindNodes: CornerStitching.PerTileProc
-- [tile: TilePtr, data: REF ANY] RETURNS [REF ANY] -- ~{
-- Called for pullups where we can make a sensible decision on which node is the source.
WITH tile.Value
SELECT
FROM
cn: REF SpinifexCircuit.CircuitNode => PostProcessor[cn, pL.first.r, pL.first.l];
ENDCASE
};
[] ← tranGeom.EnumerateArea[ rect~pL.first.r, perTile~FindNodes];
ENDLOOP;
WHILE chEdge #
NIL
DO
[] ← cir.AddBox[ spinifexLayer~polSpinifex, dim~chEdge.first.rect, value~channelEdge];
chEdge ← chEdge.rest
ENDLOOP;
sourceDrainNodes ← NIL;
sourceDrainCount ← 0;
WHILE sdList #
NIL
DO
sdfirst: LIST OF REF SpinifexCircuit.CircuitNode ~ sdList;
sdList ← sdList.rest;
IF sdfirst.first.superceded # NIL THEN LOOP;
FOR alreadySeen:
LIST
OF
REF SpinifexCircuit.CircuitNode ← sourceDrainNodes, alreadySeen.rest
WHILE alreadySeen #
NIL
DO
IF alreadySeen.first = sdfirst.first THEN EXIT;
REPEAT
FINISHED => {
sdfirst.rest ← sourceDrainNodes;
sourceDrainNodes ← sdfirst;
sourceDrainCount ← sourceDrainCount.SUCC;
}
ENDLOOP;
ENDLOOP;
};
END.