<> <> <> <> <> <<>> DIRECTORY CD, CDAtomicObjects, CDBasics, CDCells, CDCommandOps, CDDirectory, CDLayers, CDOps, CDProperties, CDRects, CDSequencer, CDSymbolicObjects, CDTexts, CMosB, Core, CoreClasses, CoreOps, CoreProperties, CoreGeometry, CoreGeometryBackdoor, PWObjects, Rope, Sinix, SinixOps; SinixCMosB: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDLayers, CDOps, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CoreClasses, CoreGeometry, CoreGeometryBackdoor, CoreOps, CoreProperties, PWObjects, Rope, Sinix, SinixOps SHARES CDCells, CDLayers, CDRects, CDSymbolicObjects, CDTexts = BEGIN <> CellType: TYPE = Core.CellType; Wire: TYPE = Core.Wire; Object: TYPE = CD.Object; Properties: TYPE = Core.Properties; Instance: TYPE = CoreGeometry.Instance; ROPE: TYPE = Core.ROPE; ROPES: TYPE = LIST OF ROPE; <> mode: Sinix.Mode _ NEW [Sinix.ModeRec _ [ extractProcProp: PWObjects.RegisterProp[$CMosBExtractProc, TRUE], decoration: CoreGeometry.CreateDecoration["CMosB"], nbOfLayers: nbOfInterestingLayers, instanceLayer: InstanceLayer, touchProc: CoreGeometry.Touch, equalProc: Sinix.CompareProps ]]; nbOfInterestingLayers: NAT = 10; defaultLayerRange: Sinix.LayerRange = [min: 0, max: nbOfInterestingLayers-1]; InterestingLayersArray: TYPE = PACKED ARRAY CD.Layer OF Sinix.LayerRange _ ALL [defaultLayerRange]; interestingLayers: REF InterestingLayersArray; InstanceLayer: PROC [inst: Instance] RETURNS [layerRange: Sinix.LayerRange] = { EachInstance: CoreGeometry.EachInstanceProc = { thisLayerRange: Sinix.LayerRange _ InstanceLayer[instance]; layerRange _ [min: MIN [thisLayerRange.min, layerRange.min], max: MAX [thisLayerRange.max, layerRange.max]]; IF layerRange=defaultLayerRange THEN quit _ TRUE; }; SELECT TRUE FROM inst.obj.class=CDRects.bareRectClass => layerRange _ interestingLayers[CDLayers.AbstractToPaint[inst.obj.layer]]; CDSymbolicObjects.IsSymbolicOb[inst.obj] => layerRange _ interestingLayers[CDLayers.AbstractToPaint[CDSymbolicObjects.GetLayer[CoreGeometry.CoreGeometryPinToCDPin[inst]]]]; ENDCASE => { layerRange _ [nbOfInterestingLayers-1, 0]; [] _ CoreGeometry.FlattenInstance[inst, EachInstance]; IF layerRange.min>layerRange.max THEN layerRange _ defaultLayerRange; }; }; ExtractRect: Sinix.ExtractProc = { RETURN (IF obj.layer=CMosB.pwell OR obj.layer=CMosB.nwell THEN Sinix.ExtractNull ELSE Sinix.ExtractRect)[obj, mode, properties, userData]; }; AddRect: PROC [mode: Sinix.Mode, wire: Wire, rect: CD.Rect, layer: CD.Layer] = { instance: Instance _ [ CDRects.CreateRect[CDBasics.SizeOfRect[rect], layer], [CDBasics.BaseOfRect[rect]] ]; CoreGeometry.PutPins[mode.decoration, wire, CONS [instance, CoreGeometry.GetPins[mode.decoration, wire]]]; }; <> PropsFromSatellites: PROC [obj: Object, properties: CD.PropList] RETURNS [props: Core.Properties _ NIL] = { name: ROPE _ NIL; FOR ropes: ROPES _ NARROW [CDProperties.GetListProp[properties, Sinix.satellitesProp]], ropes.rest WHILE ropes#NIL DO IF name#NIL AND NOT Rope.Equal[ropes.first, name] THEN SIGNAL Sinix.FusionPropMismatch[CDDirectory.Name[obj], CoreOps.nameProp, name, ropes.first]; name _ ropes.first; ENDLOOP; IF name#NIL THEN props _ CoreProperties.Props[[CoreOps.nameProp, name]]; }; MakeAbstract: PROC [abstract, represents: CD.Layer] RETURNS [sameAbstract: CD.Layer] = { CDLayers.MakeAbstract[abstract, represents]; RETURN [abstract]; }; <> nsource: CD.Layer _ MakeAbstract[CD.NewLayer[CMosB.cmosB, $CNSource], CMosB.ndif]; ndrain: CD.Layer _ MakeAbstract[CD.NewLayer[CMosB.cmosB, $CNDrain], CMosB.ndif]; psource: CD.Layer _ MakeAbstract[CD.NewLayer[CMosB.cmosB, $CPSource], CMosB.pdif]; pdrain: CD.Layer _ MakeAbstract[CD.NewLayer[CMosB.cmosB, $CPDrain], CMosB.pdif]; ExtractTransistor: Sinix.ExtractProc = { size: CD.Position = CDBasics.SizeOfRect[obj.bbox]; cellType: CellType; lambda: CD.Number = CMosB.lambda; ext: CD.Number = 2*lambda; wellSurr: CD.Number _ 0; innerX: CD.Number _ 0; dif: CD.Layer _ IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.pdif THEN CMosB.pdif ELSE CMosB.ndif; gateWire, sourceWire, drainWire: Wire; IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.wndif THEN { wellSurr _ CMosB.wellSurround; innerX _ CMosB.wellSurround-ext; }; cellType _ CoreClasses.CreateTransistor[[ type: IF dif=CMosB.pdif THEN pE ELSE nE, length: (size.y-2*ext-2*wellSurr)/lambda-2, width: (size.x-2*ext-2*innerX)/lambda]]; props _ PropsFromSatellites[obj, properties]; gateWire _ cellType.public[0]; sourceWire _ cellType.public[1]; drainWire _ cellType.public[2]; IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.wndif THEN { AddRect[mode, sourceWire, [x1: ext, x2: size.x-2*CMosB.wellSurround+ext, y1: 0, y2: ext], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, drainWire, [x1: ext, x2: size.x-2*CMosB.wellSurround+ext, y1: size.y-2*CMosB.wellSurround-ext, y2: size.y-2*CMosB.wellSurround], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; } ELSE { AddRect[mode, sourceWire, [x1: ext, x2: size.x-ext, y1: 0, y2: ext], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, drainWire, [x1: ext, x2: size.x-ext, y1: size.y-ext, y2: size.y], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; }; FOR rList: CDAtomicObjects.DrawList _ NARROW [obj.specific, CDAtomicObjects.AtomicObsSpecific].rList, rList.rest WHILE rList#NIL DO rect: CD.Rect _ rList.first.r; layer: CD.Layer _ rList.first.layer; SELECT layer FROM CMosB.ndif => {}; CMosB.pdif => {}; CMosB.pol => AddRect[mode, gateWire, rect, CMosB.pol]; CMosB.nwell, CMosB.pwell => {}; ENDCASE => ERROR; ENDLOOP; CoreGeometry.PutObject[mode.decoration, cellType, obj]; result _ cellType; }; ExtractTransistorL: Sinix.ExtractProc = { size: CD.Position = CDBasics.SizeOfRect[obj.bbox]; cellType: CellType; lambda: CD.Number = CMosB.lambda; wellSurround: CD.Number = CMosB.wellSurround; ext: CD.Number = 2*lambda; wellSurr: CD.Number _ 0; innerX: CD.Number _ 0; gateWire, sourceWire, drainWire: Wire; dif: CD.Layer _ IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.pdif THEN CMosB.pdif ELSE CMosB.ndif; IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.wndif THEN { wellSurr _ wellSurround; innerX _ wellSurround-ext; }; cellType _ CoreClasses.CreateTransistor[[ type: IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.pdif THEN pE ELSE nE, length: 2, width: (size.x+size.y-2*innerX-2*wellSurr)/lambda - 12]]; props _ PropsFromSatellites[obj, properties]; gateWire _ cellType.public[0]; sourceWire _ cellType.public[1]; drainWire _ cellType.public[2]; <> IF obj.layer=CMosB.wpdif OR obj.layer=CMosB.wndif THEN { AddRect[mode, sourceWire, [x1: ext, x2: size.x-wellSurr-9*lambda, y1: 6*lambda, y2: 8*lambda], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, sourceWire, [x1: size.x-wellSurr-11*lambda, x2: size.x-wellSurr-9*lambda, y1: 6*lambda, y2: size.y-innerX-ext-wellSurr], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, drainWire, [x1: ext, x2: size.x-wellSurr-3*lambda, y1: 0, y2: 2*lambda], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; AddRect[mode, drainWire, [x1: size.x-wellSurr-5*lambda, x2: size.x-wellSurr-3*lambda, y1: 0, y2: size.y-innerX-ext-wellSurr], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; } ELSE { AddRect[mode, sourceWire, [x1: innerX+ext, x2: size.x-wellSurr-6*lambda, y1: wellSurr+6*lambda, y2: wellSurr+8*lambda], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, sourceWire, [x1: size.x-wellSurr-8*lambda, x2: size.x-wellSurr-6*lambda, y1: wellSurr+6*lambda, y2: size.y-innerX-ext], IF dif=CMosB.pdif THEN psource ELSE nsource]; AddRect[mode, drainWire, [x1: innerX+ext, x2: size.x-wellSurr, y1: wellSurr, y2: wellSurr+2*lambda], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; AddRect[mode, drainWire, [x1: size.x-wellSurr-2*lambda, x2: size.x-wellSurr, y1: wellSurr, y2: size.y-innerX-ext], IF dif=CMosB.pdif THEN pdrain ELSE ndrain]; }; FOR rList: CDAtomicObjects.DrawList _ NARROW [obj.specific, CDAtomicObjects.AtomicObsSpecific].rList, rList.rest WHILE rList#NIL DO rect: CD.Rect _ rList.first.r; layer: CD.Layer _ rList.first.layer; SELECT layer FROM CMosB.pol => AddRect[mode, gateWire, rect, CMosB.pol]; CMosB.ndif => {}; CMosB.pdif => {}; CMosB.nwell, CMosB.pwell => {}; ENDCASE => ERROR; ENDLOOP; CoreGeometry.PutObject[mode.decoration, cellType, obj]; result _ cellType; }; <> Atomic: PROC [className: ATOM] = { class: CD.ObjectClass = CD.FetchObjectClass[className, CMosB.cmosB]; CDProperties.PutProp[class, mode.extractProcProp, $ExtractAtomic]; }; MakeCMosBShell: PROC [comm: CDSequencer.Command] = { inst: CD.Instance = CDOps.TheInstance[comm.design, "*** Select one instance!\n"]; IF inst=NIL THEN RETURN; CDOps.IncludeObjectI[comm.design, CoreGeometry.CreateShell[mode.decoration, NARROW [SinixOps.ExtractCDInstance[inst, comm.design, mode].result], TRUE], comm.pos]; }; <> <> interestingLayers _ NEW [InterestingLayersArray]; interestingLayers[CMosB.met2] _ [0, 0]; interestingLayers[CMosB.met] _ [1, 1]; interestingLayers[CMosB.pol] _ [2, 2]; interestingLayers[CMosB.pdif] _ [3, 3]; interestingLayers[CMosB.ndif] _ [4, 4]; interestingLayers[CMosB.pwell] _ [5, 5]; interestingLayers[CMosB.nwell] _ [6, 6]; interestingLayers[CMosB.ovg] _ [7, 7]; interestingLayers[CMosB.pwellCont] _ [8, 8]; interestingLayers[CMosB.nwellCont] _ [9, 9]; interestingLayers[CMosB.cut2] _ [0, 1]; interestingLayers[CMosB.cut] _ [1, 4]; <> CDCommandOps.RegisterWithMenu[$Debug, "Make CMosB shell", "Make a shell from the extracted object", $MakeCMosBShell, MakeCMosBShell, doQueue]; <> CDProperties.PutLayerProp[CMosB.pwell, $Well, $PWell]; CDProperties.PutLayerProp[CMosB.nwell, $Well, $NWell]; CDProperties.PutLayerProp[CMosB.ndif, $RoutingLayer, $RoutingLayer]; CDProperties.PutLayerProp[CMosB.pdif, $RoutingLayer, $RoutingLayer]; CDProperties.PutLayerProp[CMosB.pol, $RoutingLayer, $RoutingLayer]; CDProperties.PutLayerProp[CMosB.met, $RoutingLayer, $RoutingLayer]; CDProperties.PutLayerProp[CMosB.met2, $RoutingLayer, $RoutingLayer]; CDProperties.PutLayerProp[CMosB.ovg, $RoutingLayer, $RoutingLayer]; <> SinixOps.RegisterDefaultLayoutMode[mode, CMosB.cmosB]; <> <> Sinix.RegisterExtractProc[$CMosBExtractRect, ExtractRect]; Sinix.RegisterExtractProc[$CMosBExtractTransistor, ExtractTransistor]; Sinix.RegisterExtractProc[$CMosBExtractTransistorL, ExtractTransistorL]; <> CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $ExtractCell]; CDProperties.PutProp[PWObjects.abutXClass, mode.extractProcProp, $ExtractAbut]; CDProperties.PutProp[PWObjects.abutYClass, mode.extractProcProp, $ExtractAbut]; CDProperties.PutProp[PWObjects.routingClass, mode.extractProcProp, $ExtractRouting]; <> CDProperties.PutProp[CDSymbolicObjects.pinClass, mode.extractProcProp, $ExtractPin]; CDProperties.PutProp[CDSymbolicObjects.segmentClass, mode.extractProcProp, $ExtractPin]; CDProperties.PutProp[CDSymbolicObjects.markClass, mode.extractProcProp, $ExtractPin]; <> CDProperties.PutProp[CDRects.bareRectClass, mode.extractProcProp, $CMosBExtractRect]; <> Atomic[className: $C2SimpleCon]; Atomic[className: $C2WellSimpleCon]; Atomic[className: $C2LargeSimpleCon]; Atomic[className: $C2LargeWellSimpleCon]; Atomic[className: $C2DifShortCon]; Atomic[className: $C2WellDifShortCon]; Atomic[className: $C2Via]; Atomic[className: $C2LargeVia]; <> Atomic[className: $C2PDifRect]; Atomic[className: $C2NDifRect]; <> CDProperties.PutProp[CD.FetchObjectClass[$C2Trans, CMosB.cmosB], mode.extractProcProp, $CMosBExtractTransistor]; CDProperties.PutProp[CD.FetchObjectClass[$C2WellTrans, CMosB.cmosB], mode.extractProcProp, $CMosBExtractTransistor]; <> CDProperties.PutProp[CD.FetchObjectClass[$C2LTrans, CMosB.cmosB], mode.extractProcProp, $CMosBExtractTransistorL]; CDProperties.PutProp[CD.FetchObjectClass[$C2LWellTrans, CMosB.cmosB], mode.extractProcProp, $CMosBExtractTransistorL]; <> CDProperties.PutProp[CDTexts.rigidTextClass, mode.extractProcProp, $ExtractNull]; CDProperties.PutProp[CDTexts.flipTextClass, mode.extractProcProp, $ExtractNull]; CoreGeometryBackdoor.RegisterDecorationIO[mode.decoration]; END.