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; 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]; }; }; 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 = { 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 CountCapa: PROC [wire: Core.Wire] 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 [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 BOOLEAN _ ALL[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 $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[ REAL _ IO.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. Œ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 Core Properties management Core hierarchical structure visiting, deepest first. PROC [actualWire, publicWire: Wire] Each wire capa evaluation $cmos => tech _ SinixCMos.extractAMode; Κ —˜šœ™J™>Icode™NK™,—code2šΟk ˜ Kšœœ)˜1Kšœ œ ˜Kšœ˜Kšœœ˜Kšœ œ˜/Kšœœ1˜=Kšœœ=˜JKšœœP˜dKšœ œ˜.Kšœœ˜Kšœœ˜(Kšœ œ˜Kšœœ˜%Kšœ˜Kšœ˜Kšœ ˜ —LšΟn œœ˜š˜LšœBœ(˜l—š˜Lšœ ˜ —šœ˜Kšœ˜Kšœœœ˜KšœœΟc7˜VKš œœœœœ˜+Kšœ œœœ˜-K˜K™K™šž œœ!˜1Kšœ?œ ˜OKšœŸ ˜ J˜—šž œ œœ˜@Kšœœœ<˜Tšœœ˜Kšœ˜K˜—šœ˜Kšœ ˜ Kšœ˜—Kšœ˜—šžœœ!˜-Kšœ?œ ˜OKšœŸ ˜ J˜—šžœ œœ˜Kšœœ˜7Kšœœ˜7Kšœœ˜'Kšœ œ˜Kšœœœœ˜šœœœ˜(Kšœœ˜(šœ œœ˜+Kšœœœ˜#Kšœ˜—Kšœ˜—Kšœ,˜,Jšœ,˜,š œ œœ'œ œ˜QKšœ2˜2Kšœœ˜šœœœR˜ešœœœR˜eKšœœ˜Kšœ˜—Kšœ˜—Kšœ˜—šœ œœ˜.šœœ˜šœœœ˜%šœœœ˜%šœœ˜Kšœ<˜<—Kšœ˜—Kšœ˜—K˜—Kšœ˜—K˜K˜—Kšœ œœ˜%Kšœ œ œ ˜:Kšœ œœœ˜Kš œœœœ œ˜1Kš œœœœœ˜@Kšœ œœ˜$Kš œ œœœœœœ˜=Kšœ œœ˜Kšœœœ ˜Kš œ œœ œœœ œ˜NKšœ œœœ˜(Kšœ˜Kšœœ ˜Kšœœ ˜Kšœœœœ˜/Kšœœœœ˜/Kšœ œœœ2˜GKšœ œœœ˜K˜š œœœœ"œœ˜IKšœ œ˜$šœ˜(šœ ˜ Kšœœ(˜/Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ.˜.Kšœ œ˜K˜—Jšœ Ÿ˜,—Kšœ˜—Jšœ3˜3Jšœ˜ KšœŸ ˜K˜—unitš ž œœœ'œ ˜SK˜Kšœœ˜Kšœ œ˜šœ ˜Kšœ'™'šœ ˜ Kšœ˜K˜KšœŸ˜(Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ%˜%Kšœ˜Kšœ&˜&Kšœ˜Kšœ˜K˜—šœ ˜ Kšœ$˜$K˜KšœŸ˜(Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœœ˜—˜Kšœ˜—KšœΠciŸ  ˜K˜—šΟb œ˜%Kšœ œ œ˜"Kšœœ˜,Kšœ˜—K˜š‘ œ˜"Kšœœœœ˜+Kšœ˜—K˜Kšœ œv˜‡Kšœ œv˜‡Kšœœ5˜H—Lšœ˜—…—$h2‹