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], HashTable USING [Store, Fetch, Create, Table, Pairs, EachPairAction, Key, Value], IO USING [PutF, real, GetReal], NMos, Sinix USING [Mode], SinixOps, Rope, WriteCapa; WriteCapaImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDSymbolicObjects, CDRects, CMosB, CoreClasses, CoreGeometry, CoreIO, CoreOps, CoreProperties, HashTable, IO, 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: HashTable.Table _ HashTable.Create[equal: CapaEqual, hash: CapaHash]; VisitRecurs: PROC [ct: Core.CellType, mode: Sinix.Mode] = { 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] + GetWireCap[wire, mode]]; }; }; 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; 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 _ HashTable.Create[]; IF CoreOps.VisitBinding[actual: rct[in].actual, public: rct[in].type.public, eachWirePair: AddOutsideCapa] THEN ERROR; ENDLOOP; internals _ HashTable.Create[]; CoreOps.VisitRootAtomics[root: rct.internal, eachWire: AddLocalCapa]; }; ENDCASE => { BackAnnotate: HashTable.EachPairAction ~ { CoreProperties.PutWireProp[on: NARROW[key], prop: rootCapProp, value: CoreProperties.GetWireProp[from: NARROW[value], prop: rootCapProp]] }; IF ct.class.recast#NIL THEN { rc: Core.CellType _ CoreOps.Recast[ct]; bindingTable: HashTable.Table _ CoreOps.RecastBindingTable[ct]; VisitRecurs[rc, mode]; [] _ HashTable.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; }; $nmos => { cPerArea _ 0.0012; -- pf/sq microns; cPerWidth _ 0.00025; -- pf/microns; 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 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: HashTable.Value; found: BOOLEAN; capa _ NEW[pfs _ c]; [found, value] _ HashTable.Fetch[cacheForGC, capa]; IF found THEN capa _ NARROW[value] ELSE [] _ HashTable.Store[cacheForGC, capa, capa]; }; CapaHash: PROC [k: HashTable.Key] RETURNS [hash: CARDINAL] ~ { ln: Basics.LongNumber; ln.real _ NARROW[k, REF REAL]^; hash _ Basics.BITXOR[ln.highbits, ln.lowbits]; }; CapaEqual: PROC [k1, k2: HashTable.Key] RETURNS [BOOL] ~ { ref1: REF REAL _ NARROW[k1]; ref2: REF REAL _ NARROW[k2]; 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 (C) 1986 by Xerox Corporation. All rights reserved. Louis Monier, Jean-Marc Frailong, Rick Barth, Giordano Beretta, and above all, Christian LeCocq April 16, 1987 1:25:10 pm PDT Bertrand Serlet October 18, 1986 7:59:14 pm PDT Core hierarchical structure visiting, deepest first. PROC [actualWire, publicWire: Wire] transistor: CoreClasses.Transistor _ NARROW[ct.data]; 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, transistor.length*transistor.width*cPerArea]; PutRootCap[ch1Wire, transistor.width*cPerWidth]; PutRootCap[ch2Wire, transistor.width*cPerWidth]; PROC [key: Key, value: Value] 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. other values in pf per sq CD units. 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... 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™>K™NK™.K™/K™—šΟk ˜ K˜Kšœœ-˜5Kšœ œ ˜Kšœœ˜Kšœœ˜'Kšœ˜Kšœœ˜Kšœ œ8˜IKšœ œE˜WKšœœ1˜=KšœœP˜]Kšœœq˜…Kšœ œB˜QKšœœ˜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˜—š œ œœ˜Kšœ˜Kšœ œœœ˜Kšœœ˜.K˜K˜—š  œœœœ˜:Kšœ œœ˜Kšœ œœ˜Kšœ˜K˜K˜—šΟb œ˜%Kšœ œ œ˜"Kšœœ˜,Kšœ˜K˜—š’ œ˜"Kšœœœ˜Kšœœœ˜Kšœ˜Kšœ˜K˜—šœ œ˜,šœ&˜&Kšœ˜KšœZ˜ZKšœ˜—Kšœ˜Kšœ˜Kšœ˜—šœ œ˜,šœ&˜&Kšœ˜KšœZ˜ZKšœ˜—Kšœ˜Kšœ˜Kšœ˜—Kšœœ5˜H—Kšœ˜™-K™ —™/K™P—™/K™——…—-ΐC’