<> <> <> <> <> <<>> DIRECTORY CD, CDAtomicObjects, CDBasics, CDCells, CDInstances, CDLayers, CDProperties, CDOrient, CDRects, CDSatellites, CDSymbolicObjects, CDTexts, NMos, NMosContacts, NMosTransistors, Core, CoreClasses, CoreOps, CoreProperties, PW, PWObjects, PWPins, Rope, Sinix, SinixNMos, SinixHighlight; SinixNMosExtract: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDInstances, CDLayers, CDOrient, CDProperties, CDRects, CDSatellites, CDSymbolicObjects, CDTexts, NMos, CoreClasses, CoreOps, CoreProperties, PW, PWObjects, PWPins, Rope, Sinix, SinixHighlight EXPORTS SinixNMos SHARES CDCells, CDLayers, CDRects, CDSymbolicObjects, CDTexts = BEGIN OPEN SinixNMos; <> specialcontact: ATOM = PW.RegisterProp[$SinixNMosHandcraftedContact, TRUE, FALSE]; flattenProcProp: ATOM = PW.RegisterProp[$SinixNMosFlatten, TRUE, TRUE]; extractMode: PUBLIC Sinix.Mode _ NEW [Sinix.ModeRec _ [ name: "NMos", extractProcProp: PW.RegisterProp[$SinixNMosExtractProc, TRUE, TRUE], pinsProp: CoreProperties.RegisterProperty[$SinixNMosPins, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]], wireGeometryProp: CoreProperties.RegisterProperty[$SinixNMosWireGeometry, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy], [CoreProperties.propPrint, CoreProperties.PropDontPrint]]], instanceProp: CoreProperties.RegisterProperty[$SinixNMosInstance, CoreProperties.Props[[CoreProperties.propCopy, CoreProperties.PropDoCopy], [CoreProperties.propPrint, CoreProperties.PropDontPrint]]], nbOfLayers: NbOfInterestingLayers, instanceLayer: InstanceLayer, cacheProp: PW.RegisterProp[$SinixNMosCache, FALSE, TRUE], cachePropsProp: PW.RegisterProp[$SinixNMosCacheProps, FALSE, TRUE], flatNameSpace: TRUE, equalProc: Sinix.CompareProps ]]; InterestingLayers: ARRAY [0 .. NbOfInterestingLayers) OF CD.Layer _ [NMos.dif, NMos.pol, NMos.met, NMos.met2, NMos.cut, NMos.cut2, NMos.imp, NMos.imp0, NMos.impWeak, NMos.ovg, NMos.bur]; NbOfInterestingLayers: NAT = 11; lambda: CD.Number = NMos.lambda; <> InstanceLayer: PROC [inst: CD.Instance] RETURNS [Sinix.LayerRange] = { FOR i: NAT IN [0 .. NbOfInterestingLayers) DO IF InterestingLayers[i]=CDLayers.AbstractToPaint[inst.ob.layer] THEN RETURN [[i, i]]; ENDLOOP; RETURN [[0, NbOfInterestingLayers-1]]; }; AddNamesToWire: PROC [wire: Wire, properties: CD.PropList] = { FOR ropes: LIST OF ROPE _ CDSatellites.GetSatelliteRopes[properties], ropes.rest WHILE ropes#NIL DO IF CoreOps.GetShortWireName[wire]#NIL AND ~Rope.Equal[CoreOps.GetShortWireName[wire], ropes.first] THEN ERROR; -- two names for the same wire [] _ CoreOps.SetShortWireName[wire, ropes.first]; ENDLOOP; }; AddRectList: PROC [mode: Sinix.Mode, wire: Wire, list: CDAtomicObjects.DrawList] = { WHILE list#NIL DO instance: CD.Instance _ PWPins.NewInstance[ ob: CDRects.CreateRect[CDBasics.SizeOfRect[list.first.r], list.first.lev], location: CDBasics.BaseOfRect[list.first.r] ]; <> Sinix.AddPinsProp[mode, wire, instance]; list _ list.rest; ENDLOOP; }; MakeAbstract: PROC [abstract, represents: CD.Layer] RETURNS [sameAbstract: CD.Layer] = { CDLayers.MakeAbstract[abstract, represents]; RETURN [abstract]; }; <> ExtractPin: Sinix.ExtractProc ~ { IF obj.layer=CD.commentLayer THEN RETURN [NIL]; [result] _ Sinix.ExtractPin[obj, mode, properties, userData]; AddNamesToWire[NARROW [result], properties]; }; ExtractRect: Sinix.ExtractProc ~ { IF obj.layer=CD.commentLayer THEN RETURN [NIL]; [result] _ Sinix.ExtractWire[obj, mode, properties, userData]; AddNamesToWire[NARROW [result], properties]; }; ExtractCell: Sinix.ExtractProc ~ { [result] _ (IF CDProperties.GetObjectProp[obj, specialcontact]#NIL THEN ExtractContact ELSE Sinix.ExtractCell)[obj, mode, properties, userData]; }; ExtractContact: Sinix.ExtractProc ~ { flatten: REF AtomicFlattenProc _ NARROW [CDProperties.GetProp[from: obj.class, prop: flattenProcProp]]; wire: Wire _ CoreOps.CreateWire[]; AddRectList[mode, wire, flatten[obj]]; AddNamesToWire[wire, properties]; result _ wire; }; TouchContact: Sinix.TouchProc ~ { flatten: REF AtomicFlattenProc _ NARROW [CDProperties.GetProp[from: instance1.ob.class, prop: flattenProcProp]]; FOR rList: CDAtomicObjects.DrawList _ flatten [instance1.ob], rList.rest WHILE rList#NIL DO IF Sinix.TouchRectObject[mode, instance2, CDOrient.MapRect[rList.first.r, instance1.ob.size, instance1.orientation, instance1.location], rList.first.lev] THEN RETURN [TRUE]; ENDLOOP; }; ExtractTransistor: Sinix.ExtractProc ~ { cellType: CellType; gateWire, sourceWire, drainWire: Wire; sList, dList, gList, xList: CDAtomicObjects.DrawList; flatten: REF TransistorFlattenProc _ NARROW [CDProperties.GetProp[from: obj.class, prop: flattenProcProp]]; cellType _ CoreClasses.CreateTransistor[[nE]]; gateWire _ cellType.public[0]; sourceWire _ cellType.public[1]; drainWire _ cellType.public[2]; [sList, dList, gList, xList] _ flatten[obj]; AddRectList[mode, sourceWire, sList]; AddRectList[mode, drainWire, dList]; AddRectList[mode, gateWire, gList]; result _ cellType; }; <> <> DifPolContact: AtomicFlattenProc = { difpolRimWidth: CD.Number = lambda; r: CD.Rect = [x1: 0, y1: 0, x2: obj.size.x, y2: obj.size.y]; rList _ CONS[[r, NMos.met], rList]; rList _ CONS[[r, obj.layer], rList]; rList _ CONS[[CDBasics.Extend[r, -difpolRimWidth], NMos.cut], rList]; }; <> MmContact: AtomicFlattenProc = { cut2min: CD.Number = 3*lambda; mmRimWidth: CD.Number = lambda; mins: CD.Number = cut2min+2*mmRimWidth; -- use old technology for big contacts r: CD.Rect = [x1: 0, y1: 0, x2: obj.size.x, y2: obj.size.y]; rList _ CONS[[r, NMos.met], rList]; rList _ CONS[[r, NMos.met2], rList]; rList _ CONS[[CDBasics.Extend[r, IF obj.size.x>mins THEN -2*lambda ELSE -mmRimWidth], NMos.cut2], rList]; }; <<>> <> BurriedContact: AtomicFlattenProc = { class: NMosContacts.ContactPtr = NARROW[obj.specificRef]; dBur: CD.Number = lambda/2; burAct: CD.Number = lambda*2; diffBur: CD.Position = [ x: IF class.wExt> <> ButtingContact: AtomicFlattenProc = { butConSX: CD.Number = 4*lambda; butConSY: CD.Number = 6*lambda; butContactPolyYS: CD.Number = 3*lambda; butContactDiffY: CD.Number = butContactPolyYS-lambda; butContactRimWidth: CD.Number = lambda; rList _ CONS[[[x1: 0, x2: butConSX, y1: 0, y2: butContactPolyYS], NMos.pol], rList]; rList _ CONS[[[x1: 0, x2: butConSX, y1: butContactDiffY, y2: butConSY], NMos.dif], rList]; rList _ CONS[[[x1: 0, x2: butConSX, y1: 0, y2: butConSY], NMos.met], rList]; rList _ CONS[[[x1: butContactRimWidth, x2: butConSX-butContactRimWidth, y1: butContactRimWidth, y2: butConSY-butContactRimWidth], NMos.cut], rList]; }; <> HandCraftedContact: AtomicFlattenProc = { data: CD.CellPtr _ NARROW [obj.specificRef]; FOR list: CD.InstanceList _ data.contents, list.rest WHILE list#NIL DO IF list.first.ob.class#CDRects.bareRectClass THEN ERROR; rList _ CONS [[CDInstances.InstRectO[list.first], list.first.ob.layer], rList] ENDLOOP; }; <> depletionOverlap: CD.Number = (3*lambda)/2; <> source: CD.Layer _ MakeAbstract[CD.NewLayer[NMos.nmos, $NSource], NMos.dif]; drain: CD.Layer _ MakeAbstract[CD.NewLayer[NMos.nmos, $NDrain], NMos.dif]; <> RegularTransistor: TransistorFlattenProc = { class: NMosTransistors.TransistorPtr = NARROW[obj.specificRef]; sList _ CONS [[[x1: class.wExt, x2: class.wExt+class.width, y1: 0, y2: class.lExt], source], sList]; dList _ CONS [[[x1: class.wExt, x2: class.wExt+class.width, y1: class.lExt+class.length, y2: obj.size.y], drain], dList]; gList _ CONS [[[x1: 0, x2: obj.size.x, y1: class.lExt, y2: class.lExt+class.length], NMos.pol], gList]; IF class.implant>0 THEN xList _ CONS [[ [x1: class.wExt-depletionOverlap, x2: obj.size.x-class.wExt+depletionOverlap, y1: class.lExt-depletionOverlap, y2: obj.size.y-class.lExt+depletionOverlap], SELECT class.implant FROM NMosTransistors.strongDepletion => NMos.imp, NMosTransistors.weakDepletion => NMos.impWeak, NMosTransistors.zeroTresh => NMos.imp0, NMosTransistors.enhancement => CD.errorLayer, ENDCASE => CD.errorLayer ], xList]; }; <> AngleTransistor: TransistorFlattenProc = { class: NMosTransistors.TransistorPtr = NARROW[obj.specificRef]; ele: CD.Number = 2*class.lExt+class.length; <<-- Warning: This code is absurd, but so is NMosTransistorsImpl.DrawMeForATransistors in CDNMos23. It is incorrect if ele+wExt > size (which may make sense).>> <<-- The right code should compute the lowx/highy values for dif and go from there, not assuming the structure of the overlap. The CD graphics are wrong, and anyway it is impossible to stretch angle NMos transistors, so only one size is really available! >> hPoly: CD.Rect = [x1: 0, x2: obj.size.x-class.lExt, y1: class.lExt, y2: class.length+class.lExt]; -- horizontal vPoly: CD.Rect = [x1: obj.size.x-class.length-class.lExt, x2: hPoly.x2, y1: hPoly.y2, y2: obj.size.y]; -- vertical nDrain: CD.Rect = [x1: class.wExt, x2: obj.size.x, y1: 0, y2: hPoly.y1]; -- north eDrain: CD.Rect = [x1: vPoly.x2, x2: nDrain.x2, y1: nDrain.y2, y2: obj.size.y-class.wExt]; -- east wSource: CD.Rect = [x1: obj.size.x-ele, x2: vPoly.x1, y1: vPoly.y1, y2: eDrain.y2]; -- west sSource: CD.Rect = [x1: MIN[nDrain.x1, wSource.x1], x2: wSource.x1, y1: wSource.y1, y2: MIN[ele, wSource.y2]]; -- south gList _ CONS [[hPoly, NMos.pol], gList]; gList _ CONS [[vPoly, NMos.pol], gList]; IF class.lExt>0 THEN BEGIN dList _ CONS [[nDrain, drain], dList]; dList _ CONS [[eDrain, drain], dList]; END; sList _ CONS [[wSource, source], sList]; IF sSource.x1 < sSource.x2 THEN sList _ CONS [[sSource, source], sList]; IF class.implant>0 THEN BEGIN xList _ CONS [ [[x1: nDrain.x1-depletionOverlap, x2: hPoly.x2+depletionOverlap, y1: hPoly.y1-depletionOverlap, y2: hPoly.y2+depletionOverlap], NMos.imp], xList]; xList _ CONS [ [[x1: vPoly.x1-depletionOverlap, x2: vPoly.x2+depletionOverlap, y1: vPoly.y1-depletionOverlap, y2: eDrain.y2+depletionOverlap], NMos.imp], xList]; END; }; <> PullUp: TransistorFlattenProc = { class: NMosTransistors.TransistorPtr = NARROW[obj.specificRef]; middleX: CD.Number = obj.size.x/2; metal: CD.Rect = [x1: middleX-2*lambda, y1: middleX+2*lambda, x2: middleX+2*lambda, y2: obj.size.y]; contact: CD.Rect = [x1: metal.x1+lambda, x2: metal.x2-lambda, y1: metal.y1+lambda, y2: metal.y2-lambda]; hPoly: CD.Rect = [x1: 0, x2: obj.size.x, y1: class.lExt, y2: class.lExt+class.length]; gList _ CONS [[hPoly, NMos.pol], gList]; gList _ CONS [[contact, NMos.cut], gList]; dList _ CONS [[metal, NMos.met], dList]; dList _ CONS [[contact, NMos.cut], dList]; dList _ CONS [[[x1: metal.x1, x2: metal.x2, y1: hPoly.y2, y2: metal.y2], obj.layer], dList]; sList _ CONS [[[x1: class.wExt, x2: class.wExt+class.width, y1: 0, y2: hPoly.y1], obj.layer], sList]; xList _ CONS [[[x1: 0, x2: hPoly.x2, y1: 0, y2: obj.size.y-lambda], NMos.imp], xList]; }; <> InitContact: PROC [className: ATOM, flattenProc: AtomicFlattenProc] = { class: CD.ObjectClass = CD.FetchObjectClass[className, NMos.nmos]; CDProperties.PutProp[class, Sinix.touchProcProp, NEW [Sinix.TouchProc _ TouchContact]]; CDProperties.PutProp[class, extractMode.extractProcProp, $NMosExtractContact]; CDProperties.PutProp[class, flattenProcProp, NEW [AtomicFlattenProc _ flattenProc]]; }; InitTransistor: PROC [className: ATOM, flattenProc: TransistorFlattenProc] = { class: CD.ObjectClass = CD.FetchObjectClass[className, NMos.nmos]; CDProperties.PutProp[class, extractMode.extractProcProp, $NMosExtractTransistor]; CDProperties.PutProp[class, flattenProcProp, NEW [TransistorFlattenProc _ flattenProc]]; }; NMosContextCreator: SinixHighlight.ExtractContextCreator ~ { context _ NEW [SinixHighlight.ExtractContextRec _ [mode: extractMode, userData: NIL]]; }; <> Sinix.RegisterExtractProc[$NMosExtractPin, ExtractPin]; Sinix.RegisterExtractProc[$NMosExtractRect, ExtractRect]; Sinix.RegisterExtractProc[$NMosExtractCell, ExtractCell]; Sinix.RegisterExtractProc[$NMosExtractContact, ExtractContact]; Sinix.RegisterExtractProc[$NMosExtractTransistor, ExtractTransistor]; <> CDProperties.PutProp[CDCells.cellClass, extractMode.extractProcProp, $NMosExtractCell]; CDProperties.PutProp[CDCells.cellClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchCell]]; CDProperties.PutProp[CDCells.cellClass, flattenProcProp, NEW [AtomicFlattenProc _ HandCraftedContact]]; CDProperties.PutProp[PWObjects.abutXClass, extractMode.extractProcProp, $ExtractAbut]; CDProperties.PutProp[PWObjects.abutYClass, extractMode.extractProcProp, $ExtractAbut]; <> CDProperties.PutProp[CDSymbolicObjects.pinClass, extractMode.extractProcProp, $NMosExtractPin]; CDProperties.PutProp[CDSymbolicObjects.pinClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchPin]]; CDProperties.PutProp[CDSymbolicObjects.segmentClass, extractMode.extractProcProp, $NMosExtractPin]; CDProperties.PutProp[CDSymbolicObjects.segmentClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchPin]]; CDProperties.PutProp[CDSymbolicObjects.markClass, extractMode.extractProcProp, $NMosExtractPin]; CDProperties.PutProp[CDSymbolicObjects.markClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchPin]]; <> CDProperties.PutProp[CDRects.bareRectClass, extractMode.extractProcProp, $NMosExtractRect]; CDProperties.PutProp[CDRects.bareRectClass, Sinix.touchProcProp, NEW [Sinix.TouchProc _ Sinix.TouchRect]]; <> InitContact[$NMosContactDifAndPol, DifPolContact]; <> InitContact[$NMosContactBut, ButtingContact]; InitContact[$NMosBurContact, BurriedContact]; InitContact[$NMosMmContact, MmContact]; <> InitTransistor[$NMosTransistor, RegularTransistor]; InitTransistor[$NMosATransistor, AngleTransistor]; InitTransistor[$NMosPullUp, PullUp]; <> CDProperties.PutProp[CDTexts.textClass, extractMode.extractProcProp, $ExtractNull]; <> SinixHighlight.RegisterDefaultLayoutMode[NMos.nmos, NMosContextCreator]; END.