DIRECTORY CDInstances, CDBasics, CDTexts, CDAtomicObjects, CD, CDCells, CDCommandOps, CDDirectory, CDOps, CDRects, CDSequencer, IO, Rope, TerminalIO; StretchCMosB: CEDAR PROGRAM IMPORTS CDInstances, CDBasics, CDTexts, CDAtomicObjects, CD, CDCells, CDCommandOps, CDDirectory, CDOps, CDRects, Rope, TerminalIO = BEGIN MenuHeader: Rope.ROPE _ "Layers to be stretched"; AllLayersItem: Rope.ROPE _ "All Layers"; CondLayersItem: Rope.ROPE _ "Conductive Layers Only"; RoutLayersItem: Rope.ROPE _ "Routing Layers Only"; MenuSelections: LIST OF Rope.ROPE _ LIST[AllLayersItem, CondLayersItem, RoutLayersItem]; LayerKeyFilter: TYPE = PROC[key: ATOM] RETURNS[ok: BOOL]; AllLayers: LayerKeyFilter = {RETURN[TRUE]}; RouteLayers: LayerKeyFilter = {RETURN[ SELECT key FROM $pol, $met, $met2 => TRUE, ENDCASE => FALSE ]}; CondLayers: LayerKeyFilter = {RETURN[ SELECT key FROM $pol, $met, $met2, $ndif, $pdif, $nwel, $pwel, $nwelCont, $pwelCont => TRUE ENDCASE => FALSE]}; ExpliciteLayers: LayerKeyFilter = {RETURN[ SELECT key FROM $pol, $met, $met2, $ndif, $pdif, $wndif, $wpdif, $nwel, $pwel, $nwelCont, $pwelCont, $cut, $cut2, $wNWellCont, $wPWellCont, $ovg, $imp, $bur, $bond => TRUE, ENDCASE => FALSE ]}; StretchProc: PROC [comm: CDSequencer.Command] = { design: CD.Design _ comm.design; pos: CD.Position _ comm.pos; new: CD.Object; inst: CD.Instance _ CDOps.TheInstance[design]; filter: LayerKeyFilter; width: INT; TerminalIO.PutRope["Stretch Selected CMosB Object \n"]; IF inst=NIL THEN {TerminalIO.PutRope["Must select exactly one object for stretching \n"]; RETURN}; filter _ SELECT TerminalIO.RequestSelection[MenuHeader, MenuSelections] FROM 1 => AllLayers, 2 => CondLayers, 3 => RouteLayers, ENDCASE => NIL; IF filter=NIL THEN {TerminalIO.PutRope["Stretch Command Aborted \n"]; RETURN}; width _ TerminalIO.RequestInt["Stretch Size (Lambda): "]; new _ GetStretchedObj[inst.ob, design, width*design.technology.lambda, filter]; [] _ CDOps.PlaceInst[design, new, comm]}; GetStretchedObj: PROC [ref: CD.Object, design: CD.Design, width: INT, layerKeyFilter: LayerKeyFilter _ AllLayers] RETURNS[new: CD.Object _ NIL] = { name: IO.ROPE _ CDDirectory.Name[ref, design]; left: CD.InstanceList _ NIL; right: CD.InstanceList _ NIL; btm: CD.InstanceList _ NIL; top: CD.InstanceList _ NIL; insts: CD.InstanceList _ NIL; irr: CD.Rect _ CD.InterestRect[ref]; irrSz: CD.Position _ CD.InterestSize[ref]; rectProc: EachItemProc = { IF CDRects.IsBareRect[obj] THEN { Add: PROC[list: CD.InstanceList, iPos, iSize: CD.Position] RETURNS[newLst: CD.InstanceList] = { rectObj: CD.Object _ CDRects.CreateRect[iSize, obj.layer]; newLst _ CONS [CDInstances.NewInst[ob: rectObj, trans: [iPos]], list]}; key: ATOM _ CD.LayerKey[obj.layer]; IF layerKeyFilter[key] THEN { ir: CD.Rect _ CDBasics.MapRect[CD.InterestRect[obj], trans]; size: CD.Position; ir _ CDBasics.Intersection[ir, irr]; size _ CDBasics.SizeOfRect[ir]; IF size#[0,0] THEN { IF ir.x1=irr.x1 THEN left _ Add[left, [0, ir.y1-irr.y1], [width, size.y]]; IF ir.x2=irr.x2 THEN right _ Add[right, [0, ir.y1-irr.y1], [width, size.y]]; IF ir.y1=irr.y1 THEN btm _ Add[btm, [ir.x1-irr.x1, 0], [size.x, width]]; IF ir.y2=irr.y2 THEN top _ Add[top, [ir.x1-irr.x1, 0], [size.x, width]] }}} }; AddSide: PROC[list: CD.InstanceList, sSz, sPos: CD.Position] = { sideObj: CD.Object _ CDCells.CreateCell[il: list, ir: [0, 0, sSz.x, sSz.y]]; CDCells.ToSequenceMode[sideObj]; insts _ CONS [CDInstances.NewInst[ob: sideObj, trans: [sPos]], insts] }; EnumerateObject[ref, rectProc]; AddSide[left, [width, irrSz.y], [0, width]]; AddSide[right, [width, irrSz.y], [irrSz.x+width, width]]; AddSide[top, [irrSz.x, width], [width, irrSz.y+width]]; AddSide[btm, [irrSz.x, width], [width, 0]]; insts _ CONS [CDInstances.NewInst[ob: ref, trans: [[width-irr.x1, width-irr.y1]]], insts] ; new _ CDCells.CreateCell[il: insts, ir: [0, 0, irrSz.x+2*width, irrSz.y+2*width]]; CDCells.ToSequenceMode[new]; IF name.Length[]#0 THEN []_CDDirectory.Include[design, new, name.Cat["X"]]}; EachItemProc: TYPE = PROC[obj: CD.Object, trans: CD.Transformation]; EnumerateObject: PROC[obj: CD.Object, eachItem: EachItemProc, trans: CD.Transformation _ []] ={ IF obj=NIL THEN RETURN; SELECT TRUE FROM CDRects.IsBareRect[obj] => {eachItem[obj, trans]}; CDCells.IsCell[obj] => { doInst: PROC[inst: CD.Instance] RETURNS[quit: BOOL _ FALSE] = { EnumerateObject[inst.ob, eachItem, CDBasics.ComposeTransform[inst.trans, trans]]}; [] _ CDCells.EnumerateInstances[obj, doInst]}; CDTexts.IsText[obj] => {}; -- throw away CDAtomicObjects.IsAtomicOb[obj] => { geom: CDAtomicObjects.DrawList _ NARROW[obj.specific, CDAtomicObjects.AtomicObsSpecific].rList; FOR geom _ geom, geom.rest WHILE geom # NIL DO size: CD.Position _ CDBasics.SizeOfRect[geom.first.r]; pos: CD.Position _ CDBasics.BaseOfRect[geom.first.r]; rect: CD.Object _ CDRects.CreateRect[size, geom.first.layer]; xfrm: CD.Transformation _ CDBasics.ComposeTransform[[pos], trans]; eachItem[rect, xfrm]; ENDLOOP}; ENDCASE => { obj _ CDDirectory.Expand1[obj, NIL, NIL].new; EnumerateObject[obj, eachItem, trans]}}; CDCommandOps.RegisterWithMenu[$SpecialMenu, "Stretch CMosB Object", "Adds tabs on all sides of a cell", NIL, StretchProc, dontQueue]; END. ˆStretchCMosB.mesa Copyright Ó 1988 by Xerox Corporation. All rights reserved. Don Curry May 31, 1989 11:03:35 pm PDT $comment, ÊO˜šœ™J™—šœœœ˜.Jšœœ0˜8Jšœœ0˜7Jšœœ8˜@Jšœœ:˜BJšœ˜Jšœ˜ ——šœ˜ Jšœœœ˜-Jšœ(˜(——J˜—šœ+˜+Jšœ<œ˜Y—J˜Jšœ˜—…—¶