DIRECTORY Basics, 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], IO USING [PutF, real, GetReal], Sinix USING [Mode], SinixOps, Rope, WriteCapa; WriteCapaImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDSymbolicObjects, CDRects, CMosB, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties, RefTab, IO, SinixOps 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]; 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 = { 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 => { }; 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 ~ { 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 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 = { 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 = { 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 $cmosB => { cPerArea _ 0.0012; -- pf/sq microns; cPerWidth _ 0.00025; -- pf/sq microns; 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; }; ENDCASE => ERROR; VisitRecurs[coreCell, mode] }; -- WriteWireCapa 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^; } ELSE { cap _ 0.0; }; }; 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] ~ { 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 ~ { ln: Basics.LongNumber; ln.real _ NARROW[key, REF REAL]^; RETURN[Basics.BITXOR[ln.hi, ln.lo]]; }; CapaEqual: RefTab.EqualProc ~ { ref1: REF REAL _ NARROW[key1]; ref2: REF REAL _ NARROW[key2]; RETURN[ref1^=ref2^]; }; OutputReal: CoreIO.PropWriteProc ~ { valreal: REF REAL _ NARROW[value]; IO.PutF[h.stream, "%g ", IO.real[ valreal^]] }; InputReal: CoreIO.PropReadProc ~ { v:REAL _ IO.GetReal[h.stream]; refv: REF REAL _ GetRefCapa[v]; 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. š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 April 15, 1987 4:15:59 pm PDT Barth, April 16, 1987 10:13:10 pm PDT Christian Le Cocq April 28, 1987 10:46:03 am PDT , Transistor, TransistorPort, lengthProp, widthProp], NMos, , NMos Core hierarchical structure visiting, deepest first. PROC [actualWire, publicWire: Wire] 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]; PROC [key: Key, val: Val] RETURNS [quit: BOOLEAN _ FALSE] Each wire capa evaluation PROC [instance: CoreGeometry.Instance] RETURNS [quit: BOOL _ FALSE] PROC [instance: CoreGeometry.Instance] RETURNS [quit: BOOL _ FALSE] $cmos => tech _ SinixCMos.extractAMode; other values in pf per sq CD units. $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; }; Core Properties management This horrible hack to try to decrease the GC allocation, because many values will be identical and noone should change the REAL once computed... PROC [key: RefTab.Key] RETURNS [CARDINAL] ~ { PROC [key1, key2: RefTab.Key] RETURNS [BOOL] ~ { 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 Κ(– "cedar" style˜codešœ™K™BK™NK™.K™-K™%K™0K™—šΟk ˜ K˜Kšœœ-˜5Kšœ œ ˜Kšœœ˜Kšœœ˜'Kšœ˜Kšœœ˜šœ œ8˜IKšœ5™5—Kšœ œE˜WKšœœ1˜=KšœœP˜]Kšœœq˜…KšœœN˜ZKšœœ˜Kšœ™Kšœœ˜K˜ Kšœ˜Kšœ ˜ K˜—šΠbl œœ˜šœ€œ˜‘Kšœ™—Kšœ ˜Kšœ˜—šœ˜Kš œœœœœœ˜Kšœœ˜7Kšœœ˜7Kšœœ˜'šœœœ˜(Kšœœ˜(šœ œœ˜+Kšœœœ˜#Kšœ˜—Kšœ˜—Kšœ,˜,Kšœ,˜,KšœI˜Išœ œœ˜.šœœ˜šœœœ˜%šœœœ˜%šœœ˜Kšœ<˜<—Kšœ˜—Kšœ˜—K˜—Kšœ˜—K˜K˜—š  œ#˜0Kšœ#œœœ™Cšœœ˜šœ-˜-KšœœH˜OKšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœ0œ˜5KšœA˜H—K˜—Kšœœ ˜Kšœœ ˜Kšœœœœ˜/Kšœœœœ˜/šœ0œ˜9KšœJ˜JKšœ6˜6K˜—Kšœ˜ KšœŸ ˜K˜—š   œœœ'œ ˜SKšœ8˜8Kšœœ˜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˜——™š  œœ˜/šœœ˜KšœœœB˜ZKšœœœ1Ÿ˜XK˜—Kšœ˜K˜—š  œœ!˜1Kšœœ˜!KšœF˜FKšœŸ ˜ K˜—š  œ œœ˜@Kšœœœ<˜Tšœœ˜Kšœ˜K˜—šœ˜Kšœ ˜ Kšœ˜—Kšœ˜K˜—š œœ!˜-Kšœœ˜ KšœE˜EKšœŸ ˜ K˜—š œ œœ˜