StretchCMosB.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Don Curry May 31, 1989 11:03:35 pm PDT
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];
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 => RouteLayers,
3 => CondLayers,
ENDCASE => NIL;
IF filter=NIL THEN {TerminalIO.PutRope["Stretch Command Aborted \n"]; RETURN};
width ← TerminalIO.RequestInt["Stretch Size: "];
new ← GetStretchedObj[inst.ob, design, width*design.technology.lambda, filter];
[] ← CDOps.PlaceInst[design, new, comm]};
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
$comment,
$pol,
$met, $met2,
$ndif, $pdif,
$wndif, $wpdif,
$nwel, $pwel,
$nwelCont, $pwelCont,
$cut, $cut2,
$wNWellCont, $wPWellCont,
$ovg, $imp,
$bur, $bond => TRUE,
ENDCASE => FALSE ]};
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 []irectory.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[$GarbageMenu,
"Stretch CMosB Object", "Adds tabs on all sides of a cell", NIL, StretchProc, dontQueue];
END.