SXTechnologyImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Written by Shand, June 12, 1984 3:11:49 pm PDT
Last Edited by: Shand, March 12, 1985 3:04:13 pm PST
Last Edited by: Jacobi, July 17, 1985 7:57:30 pm PDT
Last edited by: gbb August 9, 1985 4:26:09 pm PDT
DIRECTORY
CD USING [CreateDrawRef, DrawRectProc, DrawRef, Error, FetchObjectClass, Instance, lambda, Layer, Number, ObjectClass, Object, Orientation, Position, Rect, Technology],
CDBasics USING [Extend, NonEmpty, universe],
CDObjectProcs USING [RegisterFurther, StoreFurther],
CDProperties USING [PutPropOnTechnology],
CornerStitching USING [Area, ChangeRect, EastEdge, ENorthNeighbour, EnumerateArea, InlineChangeTile, NEastNeighbour, NewTesselation, NorthEdge, PerTileProc, Region, SouthEdge, SWestNeighbour, Tesselation, TilePtr, Value, WestEdge, WSouthNeighbour],
SX,
SXAccessInternal,
SXAtoms USING [coreOut, fini, init, rosePrint, spinifex, thymePrint],
SXOutput USING [LinkageHousekeeper, LinkagePrintProc],
SXTechnology;
SXTechnologyImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDObjectProcs, CDProperties, CornerStitching, SX, SXAccessInternal, SXAtoms
EXPORTS SXTechnology
SHARES CornerStitching =
BEGIN
polPtr: REF INT ← NEW[INT];
difPtr: REF INT ← NEW[INT];
chanPtr: REF INT ← NEW[INT];
Post:
TYPE ~
RECORD [
r: CD.Rect,
l: CD.Layer
];
AddRectParameters:
TYPE ~
RECORD [
tes: REF CornerStitching.Tesselation,
cir: REF SX.Circuit,
PerDrawRect: SXTechnology.PerDrawRectProc,
gateNode: REF SX.CircuitNode,
postRectList: LIST OF REF Post,
clientData: REF ANY
];
AddRectangle:
CD.DrawRectProc
-- [r: Rect, l: Layer, pr: DrawRef] -- ~ {
-- I don't care about efficiency here I'm afraid
data: REF AddRectParameters ~ NARROW[ pr.devicePrivate];
level: SXTechnology.TransistorMaterial ~ data.PerDrawRect[r, l, data.clientData];
IF ~CDBasics.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.Instance,
pos:
CD.Position,
orient:
CD.Orientation,
cir:
REF SX.Circuit,
difSpinifex, polSpinifex: SX.SpinifexLayerIndex,
difChannel, channelEdge:
REF SX.Constraint,
difChanSep, difToPolSep:
CD.Number,
PerDrawRect: SXTechnology.PerDrawRectProc,
data:
REF
ANY ←
NIL,
PostProcessor: SXTechnology.ReportDifProc ←
NIL]
RETURNS
[gateNode:
REF SX.CircuitNode, sourceDrainNodes:
LIST
OF
REF SX.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[CDBasics.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.InlineChangeTile[ t, node];
[] ← cir.AddRect[ lev~appl.ob.layer, dim~t.Area, value~node]
}
ELSE
WITH t.Value
SELECT
FROM
cn:
REF SX.CircuitNode =>
SX.LookupNode[cn].superceded ← node;
--Ch. J., Jan 30, 1985 included LookupNode without further thinking
ENDCASE;
};
node: REF SX.CircuitNode ← cir.AddRect[lev~appl.ob.layer, dim~tile.Area];
sdList ← CONS[ node, sdList];
tranGeom.InlineChangeTile[ 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, interestBloat~ [difChanSep, difChanSep, difChanSep, difChanSep], value~difChannel];
};
polPtr => NULL;
ENDCASE
};
AddParm: REF AddRectParameters ~ NEW[AddRectParameters];
tranGeom: REF CornerStitching.Tesselation ~ CornerStitching.NewTesselation[];
sdList: LIST OF REF SX.CircuitNode ← NIL;
dr: CD.DrawRef ~ CD.CreateDrawRef[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.devicePrivate ← AddParm;
appl.ob.class.drawMe[appl, pos, orient, dr];
IF (gateNode ← AddParm.gateNode) = NIL THEN ERROR;
[] ← tranGeom.EnumerateArea[ rect~CDBasics.universe, perTile~FindChannelEdge, data~tranGeom];
[] ← tranGeom.EnumerateArea[ rect~CDBasics.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 SX.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 SX.CircuitNode ~ sdList;
sdList ← sdList.rest;
IF sdfirst.first.superceded # NIL THEN LOOP;
FOR alreadySeen:
LIST
OF
REF SX.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;
};
SetUpResolution:
PUBLIC
PROCEDURE [constrArray:
REF SX.ConstraintArray, res: SXTechnology.ResolutionTable]
RETURNS [
REF SX.ConstraintResolution] ~ {
Index: TYPE ~ SX.ConstraintIndex;
CoreIndex: TYPE ~ [1 .. Index.LAST];
cnsRes: REF SX.ConstraintResolution ~ NEW [SX.ConstraintResolution ← ALL[ALL[NIL]]];
RowUsed, ColumnUsed: ARRAY CoreIndex OF BOOLEAN ← ALL[FALSE];
excl: Index ~ SX.excludeIndex; --2
viol: Index ~ SX.violateIndex; --3
exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint ← [ $ExcludeByOpaqueCell, SX.excludeIndex]];
violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint ← [ $OpaqueCellViolation, SX.violateIndex]];
-- First set up technology independent Opaque cell constraints.
RowUsed[excl] ← ColumnUsed[excl] ← RowUsed[viol] ← ColumnUsed[viol] ← TRUE;
cnsRes[0][excl] ← cnsRes[excl][0] ← exclusionConstraint;
cnsRes[0][viol] ← cnsRes[viol][0] ← violationConstraint;
FOR i: Index
IN [1 .. Index.
LAST]
DO
cnsRes[excl][i] ← cnsRes[i][excl] ← exclusionConstraint;
cnsRes[viol][i] ← cnsRes[i][viol] ← violationConstraint;
ENDLOOP;
cnsRes[excl][excl] ← violationConstraint;
-- Now copy the elements of constrArray to the first row and column of cnsRes.
FOR i: Index
IN [0..Index.
LAST]
DO
xi: Index ~ res[i][0];
xj: Index ~ res[0][i];
cnsRes[0][i] ← cnsRes[i][0] ← constrArray[i];
-- Debugging aid for technology writer.
IF constrArray[i] #
NIL
AND i # constrArray[i].index
THEN
CD.Error[ec~ other, explanation~ "constrArray entry position, index mismatch"];
IF xi # 0
THEN {
IF ColumnUsed[xi]
THEN
CD.Error[ec~ other, explanation~ "Duplicate column key in Constraint Resolution Table"];
ColumnUsed[xi] ← TRUE
};
IF xj # 0
THEN {
IF RowUsed[xj]
THEN
CD.Error[ec~ other, explanation~ "Duplicate row key in Constraint Resolution Table"];
RowUsed[xj] ← TRUE
};
ENDLOOP;
-- Debugging aid for technology writer.
FOR i: CoreIndex
IN CoreIndex
DO
IF RowUsed[i] # ColumnUsed[i]
THEN
CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table between row & column keys"];
ENDLOOP;
FOR i: CoreIndex
IN CoreIndex
DO
xi: Index ~ res[i][0];
IF xi = 0
THEN
FOR j: CoreIndex
IN CoreIndex
DO
IF res[i][j] # 0
THEN
CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"];
ENDLOOP
ELSE
FOR j: CoreIndex
IN CoreIndex
DO
xj: Index ~ res[0][j];
IF xj = 0
THEN
FOR k: CoreIndex
IN CoreIndex
DO
IF res[k][j] # 0
THEN
CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"];
ENDLOOP
ELSE {
result: Index ~ res[i][j];
IF result = 0
THEN
CD.Error[ec~ other, explanation~ "Missing entry in Constraint Resolution Table"];
cnsRes[xi][xj] ← constrArray[ result ]
}
ENDLOOP
ENDLOOP;
FOR i: CoreIndex
IN CoreIndex
DO
FOR j: CoreIndex
IN CoreIndex
DO
IF cnsRes[i][j] # cnsRes[j][i]
THEN
NULL;
CD.Error[ec~ other, explanation~ "Inconsistencies in Constraint Resolution Table entries"];
ENDLOOP
ENDLOOP;
RETURN [cnsRes]
};
RegisterTechnologyHandle:
PUBLIC
PROCEDURE [cdTech:
CD.Technology, technologyHandle:
REF SX.TechHandle] ~ {
FOR i: SX.SpinifexLayerIndex
IN [SX.SpinifexLayerIndex.
FIRST .. technologyHandle.numSpinifexLayers)
DO
IF technologyHandle.constraintResolutions[i] =
NIL
THEN
technologyHandle.constraintResolutions[i] ← defaultResolution;
IF technologyHandle.rules[i] =
NIL
THEN
technologyHandle.rules[i] ← technologyIndependentRules
ELSE {
FOR lastRule:
LIST
OF
REF SX.GeometricRule ← technologyHandle.rules[i], lastRule.rest
WHILE lastRule.rest #
NIL
DO
NULL;
REPEAT
FINISHED => {
IF lastRule.rest # NIL THEN ERROR;
lastRule.rest ← technologyIndependentRules
}
ENDLOOP
}
ENDLOOP;
CDProperties.PutPropOnTechnology[onto~ cdTech, prop~ SXAtoms.spinifex, val~ technologyHandle];
CDObjectProcs.RegisterFurther[key~ SXAtoms.spinifex, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
CDObjectProcs.RegisterFurther[key~ SXAtoms.thymePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
CDObjectProcs.RegisterFurther[key~ SXAtoms.rosePrint, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
CDObjectProcs.RegisterFurther[key~ SXAtoms.coreOut, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
CDObjectProcs.RegisterFurther[key~ SXAtoms.init, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
CDObjectProcs.RegisterFurther[key~ SXAtoms.fini, technology~ cdTech ! CD.Error => IF ec = doubleRegistration THEN CONTINUE];
};
RegisterSpinifexObjectProcs:
PUBLIC
PROCEDURE [cdTech:
CD.Technology, objectType:
ATOM, conv: SX.ConversionProc, thyme, rose, core: SXOutput.LinkagePrintProc ←
NIL, fini: SXOutput.LinkageHousekeeper ←
NIL] ~ {
op: REF CD.ObjectClass;
IF (op←CD.FetchObjectClass[ objectType~objectType, technology~cdTech]) = NIL THEN CD.Error[explanation: "Version mismatch among ChipNDale and Spinifex"];
CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.spinifex, value~ NEW[SX.ConversionProc𡤌onv]];
IF thyme #
NIL
THEN
CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.thymePrint, value~ NEW[SXOutput.LinkagePrintProc←thyme]];
IF rose #
NIL
THEN
CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.rosePrint, value~ NEW[SXOutput.LinkagePrintProc←rose]];
IF core #
NIL
THEN
CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.coreOut, value~ NEW[SXOutput.LinkagePrintProc𡤌ore]];
IF fini #
NIL
THEN
CDObjectProcs.StoreFurther[ p~op, key~SXAtoms.fini, value~ NEW[SXOutput.LinkageHousekeeper𡤏ini]];
};
technologyIndependentRules: LIST OF REF SX.GeometricRule;
InitTechnologyIndependentRules:
PROCEDURE ~ {
detectOpaqueViolation: REF SX.GeometricRule ~ NEW[ SX.GeometricRule ← [ extent~ CD.lambda, message~ "Opaque cell boundary violated", trigger1~ ALL[TRUE], trigger2~ ALL[TRUE]]];
-- We set violateIndex = FALSE, ALL else TRUE so that corner checks face inward, which should result in more logically pleasing error reports.
detectOpaqueViolation.trigger1[SX.violateIndex] ← FALSE;
technologyIndependentRules ← LIST[detectOpaqueViolation];
};
defaultResolution: REF SX.ConstraintResolution;
InitDefaultResolution:
PROCEDURE ~ {
Index: TYPE ~ SX.ConstraintIndex;
CoreIndex: TYPE ~ [1 .. Index.LAST];
excl: Index ~ SX.excludeIndex;
viol: Index ~ SX.violateIndex;
res: REF SX.ConstraintResolution;
exclusionConstraint: REF SX.Constraint ~ NEW[ SX.Constraint ← [ $ExcludeByOpaqueCell, SX.excludeIndex]];
violationConstraint: REF SX.Constraint ~ NEW[ SX.Constraint ← [ $OpaqueCellViolation, SX.violateIndex]];
-- Set up default technology independent Opaque cell constraints.
defaultResolution ← NEW[SX.ConstraintResolution];
res ← defaultResolution;
res[0][excl] ← res[excl][0] ← exclusionConstraint;
res[0][viol] ← res[viol][0] ← violationConstraint;
FOR i: CoreIndex
IN CoreIndex
DO
res[excl][i] ← res[i][excl] ← exclusionConstraint;
res[viol][i] ← res[i][viol] ← violationConstraint;
ENDLOOP;
res[excl][excl] ← violationConstraint;
};
GetCircuitFromCDObject:
PUBLIC
PROCEDURE [cdOb:
CD.Object]
RETURNS [c:
REF
SX.Circuit←
NIL] =
BEGIN
sx: REF SX.LogicalCell = SXAccessInternal.GetSXData[cdOb];
IF sx#
NIL
THEN {
IF sx.analysisState#useCircuit THEN ERROR;
c ← sx.circuit
}
END;
-- Module Initialization.
InitTechnologyIndependentRules[];
InitDefaultResolution[];
END.
Edited on January 30, 1985 8:09:05 pm PST, by jacobi
in CheckChangeAndAdd: "cn.superceded ← node" replaced by "SX.LookupNode[cn].superceded ← node"
Edited on March 7, 1985 1:43:51 am PST, by Shand
Add interest bound to difChannel to detect interatcions between channel and dif
changes to: ProcessMosTransistor new parameter to pass bloat distance, ConvertMaskGeom (local of ProcessMosTransistor) interestBloat parameter passed to AddBox.
Edited on March 9, 1985 5:33:13 pm PST, by Shand
Changed name of CircuitConstraint in SX to Constraint
Added new procedure SetUpResolution to aid technology dependent clients in the construction of ConstraintResolution ARRAYs.
changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SetUpResolution
Edited on March 12, 1985 3:04:13 pm PST, by Shand
Technology Independent constraints added for ensuring the integrity of Opaque cells. New procedure GetCircuitFromCDObject to allow SXAtoms to be confined to Technology Independent part.
changes to: DIRECTORY, ProcessMosTransistor, SetUpResolution, SXExtrasImpl, RegisterTechnologyHandle, RegisterSpinifexObjectClass, technologyIndependentRules, InitTechnologyIndependentRules, defaultResolution, InitDefaultResolution, GetCircuitFromCDObject, SetUpResolution
Edited on March 27, 1985 6:39:31 pm PST, by Beretta
changes to: SetUpResolution: debugging.
Edited on May 6, 1985 11:26:55 am PDT, by Beretta
Converted to ChipNDale CD20
gbb August 9, 1985 2:36:53 pm PDT
Implementation of Core output.
changes to: RegisterSpinifexObjectProcs: added parameter for core.