PadFrameImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Louis Monier June 14, 1986 6:32:41 pm PDT
Bertrand Serlet August 26, 1986 2:23:07 am PDT
DIRECTORY
Cabbage, CD, CDBasics, CDCells, CDInstances, CDOrient, CDSimpleRules, CedarProcess, Connections, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, CoreGeometry, PW, PWCore, PadFrame, Rope, RTBasic, Sisyph;
PadFrameImpl: CEDAR PROGRAM
IMPORTS Cabbage, CD, CDBasics, CDCells, CDInstances, CDSimpleRules, CedarProcess, Connections, CoreClasses, CoreCreate, CoreOps, CoreProperties, CoreGeometry, PW, PWCore, Rope, Sisyph
EXPORTS PadFrame =
BEGIN OPEN CoreCreate, PadFrame;
packagePinProp: PUBLIC ATOM ← $PinInPackage;
padFrameParamsProp: PUBLIC ATOM ← $PadFrameParams;
padDesign: PUBLIC CD.Design ← PW.OpenDesign["Pads"];
padCx: Sisyph.Context ← Sisyph.Create[design: padDesign];
AtomToObjName: PROC [atom: ATOM] RETURNS [rope: ROPE] ~ {
rope ← SELECT atom FROM
$Vdd => "VddPad",
$Gnd => "GndPad",
$PadVdd => "PadVddPad",
$PadGnd => "PadGndPad",
$Analog => "AnalogPad",
$In => "InputPad",
$Out => "OutputPad",
$Clk => "ClockPad",
$IOTst => "IOTstPad",
$Corner => "CornerPad",
$Filler => "FillerPad",
$Logo => "LogoPad",
$Copyright => "CopyrightPad",
$Name => "NamePad",
ENDCASE => ERROR;
RETURN [Rope.Cat[rope, ".sch"]];
};
PadExtract: PROC [name: ROPE] RETURNS [cellType: Core.CellType] ~ {
cellType ← Sisyph.ExtractSchematicByName[name: name, cx: padCx];
IF CoreProperties.GetCellTypeProp[cellType, $Layout]=NIL
THEN PWCore.SetGet[cellType, padDesign];
};
AddPad: PUBLIC PROC [iL: CellInstances, pad: WR, type: ATOM, pos: NAT, pa1, pa2, pa3, pa4: PA ← []] RETURNS [newInsts: CellInstances] ~ {
ct: CellType ← PadExtract[AtomToObjName[type]];
inst: CellInstance ← SELECT type FROM
$Vdd, $Gnd, $PadVdd, $PadGnd, $Logo, $Copyright, $Name => Instance[type: ct], -- all bindings are implicit 
ENDCASE => Instance[ct, ["Pad", pad], pa1, pa2, pa3, pa4];
CoreProperties.PutCellInstanceProp[inst, packagePinProp, NEW[NAT ← pos]];
newInsts ← CONS [inst, iL];
};
AddPads: PUBLIC PROC [iL: CellInstances, pad: Wire, type: ATOM, firstPos: NAT, reverse: BOOLFALSE, pa1, pa2, pa3, pa4: PA ← []] RETURNS [newInsts: CellInstances] ~ {
FOR i: NAT IN [firstPos .. firstPos + pad.size) DO
newInsts ← AddPad[iL, pad[IF reverse THEN pad.size-1-i ELSE i], type, i, pa1, pa2, pa3, pa4];
ENDLOOP;
};
PadData: TYPE = RECORD [
instance: CoreClasses.CellInstance ← NIL,
pos: CD.Position ← [0, 0], -- [0, 0] is the lower-left of the cavity
rot: CD.Orientation ← CDOrient.original
];
AllPadsData: TYPE = RECORD [c: SEQUENCE nbOfPads: NAT OF PadData];
rotT: CD.Orientation = CDOrient.original;
rotL: CD.Orientation = CDOrient.rotate90;
rotB: CD.Orientation = CDOrient.rotate180;
rotR: CD.Orientation = CDOrient.rotate270;
fillerPad: CD.Object ← PWCore.Layout[PadExtract[AtomToObjName[$Filler]]];
cornerPad: CD.Object ← PWCore.Layout[PadExtract[AtomToObjName[$Corner]]];
-- measure one pad
padSize: CD.Position ← CD.InterestSize[fillerPad];
Abut: PROC [allPads: REF AllPadsData, start, end: NAT] RETURNS [obj: CD.Object] = {
obj ← PW.CreateEmptyCell[];
FOR i: NAT IN [start .. end) DO
[] ← PW.IncludeInCell[
obj,
IF allPads[i].instance=NIL THEN fillerPad ELSE PWCore.Layout[allPads[i].instance.type],
allPads[i].pos,
allPads[i].rot
];
ENDLOOP;
PW.RepositionCell[obj];
};
Rotate: PROC [allPads: REF AllPadsData, start: NAT] RETURNS [obj: CD.Object] = {
obj ← PW.ChangeOrientation[
IF allPads[start].instance=NIL THEN cornerPad ELSE PWCore.Layout[allPads[start].instance.type],
allPads[start].rot];
};
PadFrame: PWCore.LayoutProc = {
IsCorner: PROC [i: NAT] RETURNS [BOOLFALSE] ~ {
RETURN[i=0 OR i=ny OR i=ny+nx OR i=2*ny+nx];
};
inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left: CD.Object;
pos: CD.Position; -- current pad origin
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
innerInst: CoreClasses.CellInstance ← NIL;
nets: Connections.Table ← Connections.CreateForRefs[];
params: PadFrameParameters ← NARROW [CoreProperties.GetCellTypeProp[cellType, padFrameParamsProp]];
parms: Cabbage.PadRingParams ← NEW [Cabbage.PadRingParamsRec ← [horizLayer: params.horizLayer, vertLayer: params.vertLayer, opt: noIncompletes, signalSinglePinNets: TRUE]];
nx: NAT ← params.nbPadsX;
ny: NAT ← params.nbPadsY;
dx: INT ← padSize.x;
dy: INT ← padSize.y;
nbOfPads: NAT ← nx + ny + nx + ny;
allPads: REF AllPadsData ← NEW [AllPadsData[nbOfPads]];
priority: CedarProcess.Priority ← CedarProcess.GetPriority[];
-- fill allPads[i].instance and inner
FOR i: NAT IN [0 .. data.size) DO
refNat: REF NATNARROW [CoreProperties.GetCellInstanceProp[data[i], packagePinProp]];
SELECT TRUE FROM
refNat=NIL AND innerInst#NIL => ERROR;
refNat=NIL => innerInst ← data[i];
allPads[refNat^].instance#NIL => ERROR;
ENDCASE => allPads[refNat^].instance ← data[i];
ENDLOOP;
-- Left
pos ← [-dy, dx*(ny-1)];
IF allPads[0].instance#NIL THEN ERROR;
allPads[0].pos ← pos; allPads[0].rot ← rotL;        -- ul
FOR i: NAT IN [1..ny) DO
pos.y ← pos.y-dx;
allPads[i].pos ← pos; allPads[i].rot ← rotL;
ENDLOOP;
-- Bottom
pos ← [-dy, -dy];
IF allPads[ny].instance#NIL THEN ERROR;
allPads[ny].pos ← pos; allPads[ny].rot ← rotB;       -- ll
pos.x ← 0;
FOR i: NAT IN [ny+1 .. ny+nx) DO
allPads[i].pos ← pos; allPads[i].rot ← rotB;
pos.x ← pos.x+dx;
ENDLOOP;
-- Right
pos ← [(nx-1)*dx, -dy];
IF allPads[ny+nx].instance#NIL THEN ERROR;
allPads[ny+nx].pos ← pos; allPads[ny+nx].rot ← rotR;     -- lr
pos.y ← pos.y+dy;
FOR i: NAT IN [ny+nx+1 .. ny+nx+ny) DO
allPads[i].pos ← pos; allPads[i].rot ← rotR;
pos.y ← pos.y+dx;
ENDLOOP;
-- Top
pos ← [(nx-1)*dx, dx*(ny-1)];
IF allPads[2*ny+nx].instance#NIL THEN ERROR;
allPads[2*ny+nx].pos ← pos; allPads[2*ny+nx].rot ← rotT;    -- ur
FOR i: NAT IN [2*ny+nx+1 .. 2*ny+nx+nx) DO
pos.x ← pos.x-dx;
allPads[i].pos ← pos; allPads[i].rot ← rotT;
ENDLOOP;
-- Create the objects to pass to the router
inner ← PWCore.Layout[innerInst.type];
bottomLeft ← Rotate[allPads, ny];
bottom ← Abut[allPads, ny+1, ny+nx];
bottomRight ← Rotate[allPads, ny+nx];
right ← Abut[allPads, ny+nx+1, ny+nx+ny];
topRight ← Rotate[allPads, 2*ny+nx];
top ← Abut[allPads, 2*ny+nx+1, 2*ny+nx+nx];
topLeft ← Rotate[allPads, 0];
left ← Abut[allPads, 1, ny];
-- Create the nets for the inner
BEGIN
EachInnerWirePin: CoreGeometry.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[innerInst, wire];
name: ROPE ← CoreOps.GetFullWireNames[data.internal, actual].first;
net: Connections.Net ← Connections.Fetch[nets, actual].net;
innerSide: RTBasic.Side ← SELECT side FROM
top => top, bottom => bottom, left => left, right => right, ENDCASE => ERROR;
IF layer#CDSimpleRules.GetLayer[$cmosB, (IF side=top OR side=bottom THEN params.vertLayer ELSE params.horizLayer)] THEN RETURN;
IF net=NIL THEN {net ← NEW [Connections.NetRec ← [name: name]]; [] ← Connections.Store[nets, actual, net]};
IF min>max THEN ERROR;
net.segments ← CONS [
NEW [Connections.SegmentRec ← [object: inner, range: [min, max], side: innerSide, layer: layer]],
net.segments];
};
[] ← PWCore.InterestRect[innerInst.type]; -- to make sure the cellType is decorated
[] ← CoreGeometry.EnumerateNonOverlappingSides[PWCore.extractMode.decoration, innerInst.type, EachInnerWirePin];
END;
-- Create the nets for the pads
FOR i: NAT IN [0 .. nbOfPads) DO
EachPadWirePin: CoreGeometry.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[allPads[i].instance, wire];
name: ROPE ← CoreOps.GetFullWireNames[data.internal, actual].first;
net: Connections.Net ← Connections.Fetch[nets, actual].net;
pos: CD.Position ← allPads[i].pos;
innerSide: RTBasic.Side;
pt1, pt2: INT;
object: CD.Object;
IF side#bottom THEN RETURN;
IF net=NIL THEN {net ← NEW [Connections.NetRec ← [name: name]]; [] ← Connections.Store[nets, actual, net]};
IF min>max THEN ERROR;
SELECT allPads[i].rot FROM
rotT => {pt1 ← min+pos.x; pt2 ← max+pos.x; innerSide ← bottom; object ← top};
rotB => {pt1 ← pos.x+dx-max; pt2 ← pos.x+dx-min; innerSide ← top; object ← bottom};
rotL => {pt1 ← pos.y+min; pt2 ← pos.y+max; innerSide ← right; object ← left};
rotR => {pt1 ← pos.y+dx-max; pt2 ← pos.y+dx-min; innerSide ← left; object ← right};
ENDCASE => ERROR;
IF layer#CDSimpleRules.GetLayer[$cmosB, (IF innerSide=top OR innerSide=bottom THEN params.vertLayer ELSE params.horizLayer)] THEN RETURN;
IF pt1>pt2 THEN ERROR;
net.segments ← CONS [
NEW [Connections.SegmentRec ← [object: object, range: [pt1, pt2], side: innerSide, layer: layer]],
net.segments];
};
IF NOT IsCorner[i] AND allPads[i].instance#NIL THEN {
[] ← PWCore.InterestRect[allPads[i].instance.type]; -- to make sure the cellType is decorated
[] ← CoreGeometry.EnumerateNonOverlappingSides[PWCore.extractMode.decoration, allPads[i].instance.type, EachPadWirePin];
};
ENDLOOP;
-- Call Cabbage
CedarProcess.CheckAbort[];
CedarProcess.SetPriority[background];
obj ← Cabbage.PadLimitedRoute[inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left, CDBasics.AddPoints[params.centerDisplacement, Cabbage.Center[inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left, parms]], nets, parms, CoreOps.GetCellTypeName[cellType]];
-- we decorate the PadFrame
BEGIN
ir: CD.Rect ← CD.InterestRect[obj];
FOR i: NAT IN [0 .. nbOfPads) DO
EachPair: CoreOps.EachWirePairProc = {
pins: LIST OF CD.Instance ← NIL; -- previous pins of the public
IF NOT CoreOps.RecursiveMember[cellType.public, actualWire] THEN RETURN;
pins ← CoreGeometry.GetPins[PWCore.extractMode.decoration, actualWire];
CoreGeometry.PutTransfWireIRLazyPins[PWCore.extractMode.decoration, actualWire, publicWire, transf, ir];
WHILE pins#NIL DO
CoreGeometry.PutPins[PWCore.extractMode.decoration, actualWire, CONS [pins.first, CoreGeometry.GetPins[PWCore.extractMode.decoration, actualWire]]];
pins ← pins.rest;
ENDLOOP;
};
transf: CD.Instance;
IF IsCorner[i] OR allPads[i].instance=NIL THEN LOOP;
transf ← CDInstances.NewInstI[ob: PWCore.Layout[allPads[i].instance.type], location: allPads[i].pos, orientation: allPads[i].rot];
CDInstances.Translate[transf, [dy, dy]]; -- modifies in place!
[] ← CoreOps.VisitBinding[allPads[i].instance.actual, allPads[i].instance.type.public, EachPair];
ENDLOOP;
CoreGeometry.PutIR[PWCore.extractMode.decoration, cellType, ir];
END;
CedarProcess.SetPriority[priority];
};
NoDecorate: PWCore.DecorateProc = {};
[] ← PWCore.RegisterLayoutAtom[$PadFrame, PadFrame, NoDecorate];
END.