WriteCapaImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Louis Monier, Jean-Marc Frailong, Rick Barth, Giordano Beretta, and above all,
Christian LeCocq April 14, 1987 4:52:10 pm PDT
Bertrand Serlet May 7, 1988 11:52:21 pm PDT
Barth, April 16, 1987 10:13:10 pm PDT
Christian Le Cocq April 28, 1987 10:46:03 am PDT
DIRECTORY
Basics,
BrineIO,
CD USING [Number, Rect, InterestRect, Object, Layer],
CDBasics USING [MapRect],
CDRects USING [bareRectClass],
CDSymbolicObjects USING [IsSymbolicOb],
CMosB,
Core USING [CellType, Wire],
CoreClasses USING [recordCellClass, transistorCellClass, RecordCellType],
CoreGeometry USING [EnumerateGeometry, EachInstanceProc, FlattenInstance, HasGeometry],
CoreIO USING [PropWriteProc, PropReadProc, RegisterProperty],
CoreOps USING [Recast, RecastBindingTable, VisitRootAtomics, VisitBinding, EachWirePairProc],
CoreProperties USING [GetWireProp, PutWireProp, GetCellTypeProp, PutCellTypeProp, RegisterProperty, Props, propPrint, PropDontPrint],
RefTab USING [Store, Fetch, Create, Ref, Pairs, EachPairAction, Val, HashProc, EqualProc],
NMos,
Sinix USING [Mode],
SinixOps,
Rope,
WriteCapa;
WriteCapaImpl:
CEDAR
PROGRAM
IMPORTS Basics, BrineIO,
CD, CDBasics, CDSymbolicObjects, CDRects, CMosB, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties, RefTab, SinixOps
, NMos
EXPORTS WriteCapa
SHARES CDRects
~
BEGIN
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;
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];
pfs: TYPE = REAL;
zeroCapPtr: REF pfs ← NEW[pfs ← 0.0];
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;
cPerArea, cPerWidth: pfs;
cacheForGC: RefTab.Ref ← RefTab.Create[equal: CapaEqual, hash: CapaHash];
Core hierarchical structure visiting, deepest first.
VisitRecurs:
PROC [ct: Core.CellType, mode: Sinix.Mode] = {
AddLocalCapa:
PROC[wire: Core.Wire] = {
IF
NOT RefTab.Fetch[internals, wire].found
THEN {
[] ← RefTab.Store[internals, wire, $Internal];
PutRootCap[wire, GetRootCap[wire] + GetWireCap[wire, mode]];
};
};
AddOutsideCapa: CoreOps.EachWirePairProc = {
PROC [actualWire, publicWire: Wire]
IF publicWire.size=0
THEN {
IF
NOT RefTab.Fetch[publics, publicWire].found
THEN {
PutRootCap[actualWire, GetRootCap[publicWire] + GetRootCap[actualWire]];
[] ← RefTab.Store[publics, publicWire, $Public];
};
};
};
internals: RefTab.Ref;
publics: RefTab.Ref;
IF CoreProperties.GetCellTypeProp[ct, capaLabelProp]#NIL THEN RETURN;
SELECT ct.class
FROM
CoreClasses.transistorCellClass => {
transistor: CoreClasses.Transistor ← NARROW[ct.data];
transistorLength: INT ← NARROW[CoreProperties.GetCellTypeProp[ct, CoreClasses.lengthProp], REF INT]^;
transistorWidth: INT ← NARROW[CoreProperties.GetCellTypeProp[ct, CoreClasses.widthProp], REF INT]^;
gateWire: Core.Wire ~ ct.public[ORD[CoreClasses.TransistorPort.gate]];
ch1Wire: Core.Wire ~ ct.public[ORD[CoreClasses.TransistorPort.ch1]];
ch2Wire: Core.Wire ~ ct.public[ORD[CoreClasses.TransistorPort.ch2]];
PutRootCap[gateWire, transistorLength*transistorWidth*cPerArea];
PutRootCap[ch1Wire, transistorWidth*cPerWidth];
PutRootCap[ch2Wire, transistorWidth*cPerWidth];
};
CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType ~ NARROW[ct.data];
FOR in:
NAT
IN [0..rct.size)
DO
VisitRecurs[ct: rct[in].type, mode: mode];
publics ← RefTab.Create[];
IF CoreOps.VisitBinding[actual: rct[in].actual, public: rct[in].type.public, eachWirePair: AddOutsideCapa] THEN ERROR;
ENDLOOP;
internals ← RefTab.Create[];
CoreOps.VisitRootAtomics[root: rct.internal, eachWire: AddLocalCapa];
};
ENDCASE => {
BackAnnotate: RefTab.EachPairAction ~ {
PROC [key: Key, val: Val] RETURNS [quit: BOOLEAN ← FALSE]
CoreProperties.PutWireProp[on: NARROW[key], prop: rootCapProp, value: CoreProperties.GetWireProp[from: NARROW[val], prop: rootCapProp]]
};
IF ct.class.recast#
NIL
THEN {
rc: Core.CellType ← CoreOps.Recast[ct];
bindingTable: RefTab.Ref ← CoreOps.RecastBindingTable[ct];
VisitRecurs[rc, mode];
[] ← RefTab.Pairs[bindingTable, BackAnnotate];
};
};
CoreProperties.PutCellTypeProp[ct, capaLabelProp, capaLabelProp];
}; --VisitRecurs
Each wire capa evaluation
CountCapa:
PROC [wire: Core.Wire, mode: Sinix.Mode]
RETURNS [capa: pfs ← 0]~ {
AddValue:
PROC [ia: IndexArray, index:
INTEGER, value:
INT] ~ {
iseq: CARDINAL ← ABS[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: CARDINAL ← ABS[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];
prevNum ← ilist.first;
ENDLOOP;
};
PackedBitMap:
PROC [wire: Core.Wire, mode: Sinix.Mode, ix, iy: IndexArray, xAxis, yAxis: Axis]
RETURNS [capa: pfs ← 0] ~ {
PaintOneRect: CoreGeometry.EachInstanceProc = {
PROC [instance: CoreGeometry.Instance] RETURNS [quit: BOOL ← FALSE]
SELECT
TRUE
FROM
instance.obj.class=CDRects.bareRectClass => {
rec: CD.Rect ← CDBasics.MapRect[CD.InterestRect[instance.obj], instance.trans];
thisLayer: INTEGER ← myCDLayerNumber[instance.obj.layer];
truthTable[thisLayer] ← TRUE;
FOR x:
INTEGER
IN [IndexOfVal[ix, rec.x1]..IndexOfVal[ix, rec.x2])
DO
FOR y:
INTEGER
IN [IndexOfVal[iy, rec.y1]..IndexOfVal[iy, rec.y2])
DO
bitMap[x][y][thisLayer] ← TRUE;
ENDLOOP;
ENDLOOP;
};
CDSymbolicObjects.IsSymbolicOb[instance.obj] => NULL;
ENDCASE => quit ← CoreGeometry.FlattenInstance[instance, PaintOneRect];
};
truthTable: ARRAY [0..myCDLayerLimit) OF BOOLEAN ← ALL[FALSE];
xGridScale: GridScale ← NEW[GridScaleRep[xAxis.nStep]];
yGridScale: GridScale ← NEW[GridScaleRep[yAxis.nStep]];
bitMap: BitMap ← NEW[Row[xAxis.nStep]];
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];
[] ← CoreGeometry.EnumerateGeometry[mode.decoration, wire, PaintOneRect];
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;
};
AddRectBounds: CoreGeometry.EachInstanceProc = {
PROC [instance: CoreGeometry.Instance] RETURNS [quit: BOOL ← FALSE]
SELECT
TRUE
FROM
instance.obj.class=CDRects.bareRectClass => {
rec: CD.Rect ← CDBasics.MapRect[CD.InterestRect[instance.obj], instance.trans];
AddInAxis[xAxis, rec.x1];
AddInAxis[xAxis, rec.x2];
AddInAxis[yAxis, rec.y1];
AddInAxis[yAxis, rec.y2];
};
CDSymbolicObjects.IsSymbolicOb[instance.obj] => NULL;
ENDCASE => quit ← CoreGeometry.FlattenInstance[instance, AddRectBounds];
};
xAxis: Axis ← NEW[AxisRep];
yAxis: Axis ← NEW[AxisRep];
ix: IndexArray ← NEW[IndexArrayRep ← ALL[NIL]];
iy: IndexArray ← NEW[IndexArrayRep ← ALL[NIL]];
IF CoreGeometry.HasGeometry[mode.decoration, wire]
THEN {
[] ← CoreGeometry.EnumerateGeometry[mode.decoration, wire, AddRectBounds];
capa ← PackedBitMap[wire, mode, ix, iy, xAxis, yAxis];
};
RETURN[capa];
}; -- CountCapa
WriteWireCapa:
PUBLIC
PROC [coreCell: Core.CellType, technology:
ATOM ← $cmosB] ~ {
mode: Sinix.Mode ← SinixOps.GetExtractMode[technology];
myCDLayerNumber ← ALL[0];
layerCapa ← ALL[0.0];
SELECT technology
FROM
$cmos => tech ← SinixCMos.extractAMode;
$cmosB => {
cPerArea ← 0.0012; -- pf/sq microns;
cPerWidth ← 0.00025; -- pf/sq microns;
other values in pf per sq CD units.
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 => {
cPerArea ← 0.0012; -- pf/sq microns;
cPerWidth ← 0.00025; -- pf/microns;
other values in pf per sq CD units.
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, mode]
}; -- WriteWireCapa
Core Properties management
AddRootCap:
PUBLIC CoreOps.EachWirePairProc ~ {
IF publicWire.size=0
THEN {
capRef: REF pfs ← NARROW[CoreProperties.GetWireProp[from: actualWire, prop: rootCapProp]];
IF capRef=NIL THEN PutRootCap[actualWire, GetRootCap[publicWire]]; -- do not do it twice
};
};
PutRootCap:
PROC [wire: Core.Wire, cap: pfs] = {
value: REF pfs ← GetRefCapa[cap];
CoreProperties.PutWireProp[on: wire, prop: rootCapProp, value: value];
}; -- 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^;
}
};
PutCap:
PROC [wire: Core.Wire, cap: pfs] = {
capa: REF pfs ← GetRefCapa[cap];
CoreProperties.PutWireProp[on: wire, prop: wireCapProp, value: capa];
}; -- PutCap
GetCap:
PUBLIC
PROC [wire: Core.Wire]
RETURNS [cap: pfs] = {
capRef: REF REAL ← NARROW[CoreProperties.GetWireProp[from: wire, prop: wireCapProp]];
cap ← IF capRef#NIL THEN capRef^ ELSE 0.0;
};
GetWireCap:
PUBLIC
PROC [wire: Core.Wire, mode: Sinix.Mode]
RETURNS [cap: pfs] = {
capRef: REF REAL ← NARROW[CoreProperties.GetWireProp[from: wire, prop: wireCapProp]];
IF capRef#
NIL
THEN {
cap ← capRef^;
}
ELSE {
cap ← CountCapa[wire, mode];
PutCap[wire, cap];
};
};
GetRefCapa:
PROC [c:
REAL]
RETURNS [capa:
REF
REAL] ~ {
This horrible hack to try to decrease the GC allocation, because many values will be identical and noone should change the REAL once computed...
value: RefTab.Val;
found: BOOLEAN;
capa ← NEW[pfs ← c];
[found, value] ← RefTab.Fetch[cacheForGC, capa];
IF found THEN capa ← NARROW[value] ELSE [] ← RefTab.Store[cacheForGC, capa, capa];
};
CapaHash: RefTab.HashProc ~ {
PROC [key: RefTab.Key] RETURNS [CARDINAL] ~ {
ln: Basics.LongNumber;
ln.real ← NARROW[key, REF REAL]^;
RETURN[Basics.BITXOR[ln.hi, ln.lo]];
};
CapaEqual: RefTab.EqualProc ~ {
PROC [key1, key2: RefTab.Key] RETURNS [BOOL] ~ {
ref1: REF REAL ← NARROW[key1];
ref2: REF REAL ← NARROW[key2];
RETURN[ref1^=ref2^];
};
OutputReal: CoreIO.PropWriteProc ~ {
rreal: REF REAL ← NARROW [value];
BrineIO.WriteReal[stream, rreal^];
};
InputReal: CoreIO.PropReadProc ~ {
real: REAL ← BrineIO.ReadReal[stream];
refv: REF REAL ← GetRefCapa[real];
RETURN [refv];
};
wireCapProp:
ATOM = CoreIO.RegisterProperty[
prop: CoreProperties.RegisterProperty[
prop: $WireCap,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
],
write: OutputReal,
read: InputReal
];
rootCapProp:
ATOM = CoreIO.RegisterProperty[
prop: CoreProperties.RegisterProperty[
prop: $RootCap,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
],
write: OutputReal,
read: InputReal
];
capaLabelProp: ATOM = CoreProperties.RegisterProperty[prop: $CapaLabel];
END.
Christian LeCocq June 24, 1986 2:59:01 pm PDT
6.1 -ized
Christian LeCocq August 18, 1986 9:03:42 am PDT
Compatibility with CoreGeometry, removed registration of real Props with CoreIO.
Christian LeCocq October 7, 1986 3:24:59 pm PDT
tracked changes to CoreGeometry