WriteCapaImpl.mesa
Copyright (C) 1986 by Xerox Corporation. All rights reserved.
Louis Monier, Jean-Marc Frailong, Rick Barth, Giordano Beretta, and above all,
Christian LeCocq June 9, 1986 2:37:39 pm PDT
DIRECTORY
CD USING [Number, Rect, Instance, Object, Layer],
CDInstances USING [InstRectI],
CMosB,
Core USING [CellType, Wire],
CoreClasses USING [RecordCellType, Transistor],
CoreIO USING [PropWriteProc, PropReadProc, RegisterProperty],
CoreOps USING [ToBasic, VisitAtomicWires, VisitBinding, EachWirePairProc],
CoreProperties USING [GetWireProp, PutWireProp, GetCellTypeProp, PutCellTypeProp, RegisterProperty],
HashTable USING [Store, Fetch, Create, Table],
IO USING [PutF, real, GetReal],
Sinix USING [GetWireGeometryProp, Mode],
SinixCMos USING [extractBMode],
SinixNMosExtract USING [extractMode],
NMos,
Rope,
WriteCapa;
WriteCapaImpl: CEDAR PROGRAM
IMPORTS
CDInstances, CMosB, CoreIO, CoreOps, CoreProperties, HashTable, IO, Sinix, SinixCMos, SinixNMosExtract, NMos
EXPORTS
WriteCapa
~ BEGIN
tech: Sinix.Mode;
pfs: TYPE = REAL;
myCDLayerLimit: CARDINAL = 16; -- OK one should never do this, but it is sufficient...
myCDLayerNumber: ARRAY CD.Layer OF INTEGER;
layerCapa: ARRAY [0..myCDLayerLimit) OF REAL;
Core Properties management
PutRootCap: PROC [wire: Core.Wire, cap: pfs] = {
CoreProperties.PutWireProp[on: wire, prop: rootCapProp, value: NEW[pfs ← cap]];
}; -- PutCap
GetRootCap: PUBLIC PROC [wire: Core.Wire] RETURNS [cap: pfs] = {
capRef: REF pfs ← NARROW[CoreProperties.GetWireProp[from: wire, prop: rootCapProp]];
IF capRef#NIL THEN {
cap ← capRef^;
}
ELSE {
cap ← 0.0;
};
};
PutCap: PROC [wire: Core.Wire, cap: pfs] = {
CoreProperties.PutWireProp[on: wire, prop: wireCapProp, value: NEW[pfs ← cap]];
}; -- PutCap
GetCap: PUBLIC PROC [wire: Core.Wire] RETURNS [cap: pfs] = {
capRef: REF pfs ← NARROW[CoreProperties.GetWireProp[from: wire, prop: wireCapProp]];
IF capRef#NIL THEN {
cap ← capRef^;
}
ELSE {
cap ← CountCapa[wire];
PutCap[wire, cap];
};
};
Core hierarchical structure visiting, deepest first.
VisitRecurs: PROC [ct: Core.CellType] = {
AddLocalCapa: PROC[wire: Core.Wire] = {
IF NOT HashTable.Fetch[table: internals, key: wire].found THEN {
[] ← HashTable.Store[table: internals, key: wire, value: $Internal];
PutRootCap[wire, GetRootCap[wire] + GetCap[wire]];
};
};
AddOutsideCapa: CoreOps.EachWirePairProc = {
PROC [actualWire, publicWire: Wire]
IF publicWire.size=0 THEN {
IF NOT HashTable.Fetch[table: publics, key: publicWire].found THEN {
PutRootCap[actualWire, GetRootCap[publicWire] + GetRootCap[actualWire]];
[] ← HashTable.Store[table: publics, key: publicWire, value: $Public];
};
};
};
internals: HashTable.Table;
publics: HashTable.Table;
rc: Core.CellType;
totalCapa: pfs;
IF CoreProperties.GetCellTypeProp[ct, capaLabelProp]#NIL THEN RETURN;
totalCapa ← 0.0;
rc ← CoreOps.ToBasic[ct];
WITH rc.data SELECT FROM
tct: CoreClasses.Transistor => {};
rct: CoreClasses.RecordCellType => {
FOR in: NAT IN [0..rct.size) DO
VisitRecurs[ct: rct[in].type];
publics ← HashTable.Create[];
IF CoreOps.VisitBinding[actual: rct[in].actual, public: rct[in].type.public, eachWirePair: AddOutsideCapa] THEN ERROR;
ENDLOOP;
internals ← HashTable.Create[];
CoreOps.VisitAtomicWires[wire: rct.internal, eachWire: AddLocalCapa];
};
ENDCASE => ERROR;
CoreProperties.PutCellTypeProp[ct, capaLabelProp, NEW[pfs ← totalCapa]];
}; --VisitRecurs
Each wire capa evaluation
CountCapa: PROC [wire: Core.Wire] RETURNS [capa: pfs ← 0]~ {
AddValue: PROC [ia: IndexArray, index: INTEGER, value: INT] ~ {
iseq: CARDINALABS[value MOD 8192]/8;
elem: BiINT ← [index: index, value: value];
ia[iseq] ← CONS[elem, ia[iseq]];
};
IndexOfVal: PROC [ia: IndexArray, value: INT] RETURNS [index: INTEGER] ~ {
iseq: CARDINALABS[value MOD 8192]/8;
FOR ib: LIST OF BiINT ← ia[iseq], ib.rest DO
IF value = ib.first.value THEN RETURN[ib.first.index];
ENDLOOP;
};
AddInAxis: PROC [axis: Axis, n: INT] ~ {
ibuff: LIST OF INT;
IF axis.axisList=NIL THEN {
axis.axisList ← LIST[n];
axis.nStep ← 1;
RETURN
};
FOR i: LIST OF INT ← axis.axisList, i.rest WHILE i#NIL DO
IF i.first = n THEN RETURN;
IF i.first > n THEN {
i.rest ← CONS[i.first, i.rest];
i.first ← n;
axis.nStep ← axis.nStep + 1;
RETURN;
};
ibuff ← i;
ENDLOOP;
ibuff.rest ← CONS[n, ibuff.rest];
axis.nStep ← axis.nStep + 1;
};
IndexInList: PROC [list: LIST OF INT, array: IndexArray, gridScale: GridScale] ~ {
index: INT ← 0;
prevNum: INT ← list.first;
AddValue[array, index, list.first];
FOR ilist: LIST OF INT ← list.rest, ilist.rest WHILE ilist#NIL DO
gridScale[index] ← ilist.first - prevNum;
index ← index + 1;
AddValue[array, index, ilist.first];
prevNumilist.first;
ENDLOOP;
};
PackedBitMap: PROC [eqp: LIST OF IntermediateRect, ix: IndexArray, iy: IndexArray, xAxis: Axis, yAxis: Axis] RETURNS [capa: pfs ← 0] ~ {
Square: TYPE = PACKED ARRAY [0..myCDLayerLimit) OF BOOLEAN ;
Column: TYPE = RECORD [SEQUENCE cmax: INTEGER OF Square];
Row: TYPE = RECORD [SEQUENCE rmax: INTEGER OF REF Column];
BitMap: TYPE = REF Row;
truthTable: ARRAY [0..myCDLayerLimit) OF BOOLEANALL[FALSE];
xGridScale: GridScale ← NEW[GridScaleRep[xAxis.nStep]];
yGridScale: GridScale ← NEW[GridScaleRep[yAxis.nStep]];
bitMap: BitMap ← NEW[Row[xAxis.nStep]];
thisLayer: INTEGER;
IF eqp = NIL THEN RETURN[0];
FOR iRow: INTEGER IN [0..xAxis.nStep) DO
bitMap[iRow] ← NEW[Column[yAxis.nStep]];
FOR iColumn: INTEGER IN [0..yAxis.nStep) DO
bitMap[iRow][iColumn] ← ALL[FALSE];
ENDLOOP;
ENDLOOP;
IndexInList[xAxis.axisList, ix, xGridScale];
IndexInList[yAxis.axisList, iy, yGridScale];
FOR ecurrent: LIST OF IntermediateRect ← eqp, ecurrent.rest WHILE ecurrent#NIL DO
thisLayer ← myCDLayerNumber[ecurrent.first.layer];
truthTable[thisLayer] ← TRUE;
FOR x: INTEGER IN [IndexOfVal[ix, ecurrent.first.rect.x1]..IndexOfVal[ix, ecurrent.first.rect.x2]) DO
FOR y: INTEGER IN [IndexOfVal[iy, ecurrent.first.rect.y1]..IndexOfVal[iy, ecurrent.first.rect.y2]) DO
bitMap[x][y][thisLayer] ← TRUE;
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR ilayer: CD.Layer IN [0..myCDLayerLimit) DO
IF truthTable[ilayer] THEN {
FOR x: INTEGER IN [0..xAxis.nStep) DO
FOR y: INTEGER IN [0..yAxis.nStep) DO
IF bitMap[x][y][ilayer] THEN
capa ← capa + xGridScale[x]*yGridScale[y]*layerCapa[ilayer];
ENDLOOP;
ENDLOOP;
}
ENDLOOP;
};
IndexArray: TYPE = REF IndexArrayRep;
IndexArrayRep: TYPE = ARRAY CARDINAL [0..1024) OF ListInt;
ListInt: TYPE = LIST OF BiINT;
BiINT: TYPE = RECORD[index: INTEGER, value: INT];
IntermediateRect: TYPE = RECORD[rect: CD.Rect, layer: CD.Layer];
GridScale: TYPE = REF GridScaleRep;
GridScaleRep: TYPE = RECORD [SEQUENCE gmax: INTEGER OF INT];
GridStep: TYPE = CD.Number;
Axis: TYPE = REF AxisRep;
AxisRep: TYPE = RECORD [nStep: INTEGER ← 0, axisList: LIST OF GridStep ← NIL];
equipot: LIST OF IntermediateRect ← NIL;
iRect: IntermediateRect;
xAxis: Axis ← NEW[AxisRep];
yAxis: Axis ← NEW[AxisRep];
ix: IndexArray ← NEW[IndexArrayRep ← ALL[NIL]];
iy: IndexArray ← NEW[IndexArrayRep ← ALL[NIL]];
instances: LIST OF CD.Instance ← Sinix.GetWireGeometryProp[tech ,wire];
IF instances = NIL THEN RETURN;
FOR iList: LIST OF CD.Instance ← instances, iList.rest WHILE iList#NIL DO
instance: CD.Instance ← iList.first;
SELECT instance.ob.class.objectType FROM
$Rect => {
rec: CD.Rect ← CDInstances.InstRectI[instance];
AddInAxis[xAxis, rec.x1];
AddInAxis[xAxis, rec.x2];
AddInAxis[yAxis, rec.y1];
AddInAxis[yAxis, rec.y2];
iRect ← [rect: rec, layer: instance.ob.layer];
equipot ← CONS[iRect, equipot];
};
ENDCASE => {};  -- we will see that later...
ENDLOOP;
capa ← PackedBitMap[equipot, ix, iy, xAxis, yAxis];
RETURN[capa];
}; -- CountCapa
WriteWireCapa: PUBLIC PROC [coreCell: Core.CellType, technology: ATOM ← $cmosB] ~ {
myCDLayerNumber ← ALL[0];
layerCapa ← ALL[0.0];
SELECT technology FROM
$cmos => tech ← SinixCMos.extractAMode;
$cmosB => {
tech ← SinixCMos.extractBMode;
layerCapa[0] ← 0.0;  -- for other layers
myCDLayerNumber[CMosB.met2] ← 1;
layerCapa[1] ← 2.0e-7;
myCDLayerNumber[CMosB.cut2] ← 2;
layerCapa[2] ← 0.0;
myCDLayerNumber[CMosB.met] ← 3;
layerCapa[3] ← 3.0e-7;
myCDLayerNumber[CMosB.cut] ← 4;
layerCapa[4] ← 0.0;
myCDLayerNumber[CMosB.ovg] ← 5;
layerCapa[5] ← 0.0;
myCDLayerNumber[CMosB.pol] ← 6;
layerCapa[6] ← 6.0e-7;
myCDLayerNumber[CMosB.pdif] ← 7;
layerCapa[7] ← 3.0e-6;
myCDLayerNumber[CMosB.ndif] ← 8;
layerCapa[8] ← 1.0e-6;
myCDLayerNumber[CMosB.pwellCont] ← 9;
layerCapa[9] ← 0.0;
myCDLayerNumber[CMosB.nwellCont] ← 10;
layerCapa[10] ← 0.0;
};
$nmos => {
tech ← SinixNMosExtract.extractMode;
layerCapa[0] ← 0.0;  -- for other layers
myCDLayerNumber[NMos.dif] ← 1;
layerCapa[1] ← 1.0e-6;
myCDLayerNumber[NMos.pol] ← 2;
layerCapa[2] ← 6.0e-7;
myCDLayerNumber[NMos.met] ← 3;
layerCapa[3] ← 3.0e-7;
myCDLayerNumber[NMos.met2] ← 4;
layerCapa[4] ← 2.0e-7;
myCDLayerNumber[NMos.cut] ← 5;
layerCapa[5] ← 0.0;
myCDLayerNumber[NMos.cut2] ← 6;
layerCapa[6] ← 0.0;
myCDLayerNumber[NMos.imp] ← 7;
layerCapa[7] ← 0.0;
myCDLayerNumber[NMos.imp0] ← 8;
layerCapa[8] ← 0.0;
myCDLayerNumber[NMos.impWeak] ← 9;
layerCapa[9] ← 0.0;
myCDLayerNumber[NMos.ovg] ← 10;
layerCapa[10] ← 0.0;
myCDLayerNumber[NMos.bur] ← 11;
layerCapa[11] ← 0.0;
};
ENDCASE => ERROR;
VisitRecurs[coreCell]
}; -- WriteWireCapa
OutputReal: CoreIO.PropWriteProc ~ {
valreal: REF REAL ← NARROW[value];
IO.PutF[h.stream, "%g ", IO.real[ valreal^]]
};
InputReal: CoreIO.PropReadProc ~ {
RETURN[ NEW[ REALIO.GetReal[h.stream]]];
};
wireCapProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $WireCap], write: OutputReal, read: InputReal];
rootCapProp: ATOM = CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $RootCap], write: OutputReal, read: InputReal];
capaLabelProp: ATOM = CoreProperties.RegisterProperty[prop: $CapaLabel];
END.