LayoutPadFrame: PWCore.LayoutProc = {
parameters: PadFrameParameters ← NARROW [CoreProperties.GetCellTypeProp[cellType, padFrameParamsProp]];
padsData: REF PadsData ← parameters.padsData;
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
innerInstance: CellInstance ← data[0];
inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left: CD.Object;
nets: Connections.Table ← Connections.CreateForRefs[];
params: Cabbage.PadRingParams ← NEW [Cabbage.PadRingParamsRec ← [horizLayer: parameters.horizLayer, vertLayer: parameters.vertLayer, opt: noIncompletes, signalSinglePinNets: TRUE]];
dx: INT ← CD.InterestSize[PWCore.Layout[PadExtract[parameters, $Filler]]].x;
dy: INT ← CD.InterestSize[PWCore.Layout[PadExtract[parameters, $Filler]]].y;
nx: NAT ← parameters.nbPadsX;
ny: NAT ← parameters.nbPadsY;
priority: CedarProcess.Priority ← CedarProcess.GetPriority[];
innerPos: CD.Position;
-- Adds the nets for the inner
EachInnerWirePin: CoreGeometry.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[innerInstance, wire];
name: ROPE ← CoreOps.GetFullWireNames[data.internal, actual].first;
IF NOT IsRoutable[parameters, side, layer] THEN RETURN;
IF min>max THEN ERROR;
AddConnection[nets, data.internal, actual, inner, min, max, side, layer];
};
-- Create the objects to pass to the router
inner ← PWCore.Layout[innerInstance.type];
bottomLeft ← Rotate[padsData[ny]];
bottom ← Abut[parameters, ny+1, ny+nx];
bottomRight ← Rotate[padsData[ny+nx]];
right ← Abut[parameters, ny+nx+1, ny+nx+ny];
topRight ← Rotate[padsData[2*ny+nx]];
top ← Abut[parameters, 2*ny+nx+1, 2*ny+nx+nx];
topLeft ← Rotate[padsData[0]];
left ← Abut[parameters, 1, ny];
-- Create the nets for the inner
[] ← PWCore.Layout[innerInstance.type]; -- to make sure the cellType is decorated
[] ← CoreGeometry.EnumerateNonOverlappingSides[PWCore.extractMode.decoration, innerInstance.type, EachInnerWirePin];
-- Create the nets for the pads
FOR i:
NAT
IN [0 .. padsData.nbOfPads)
DO
EachPadWirePin: CoreGeometry.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[padsData[i].instance, wire];
pos: CD.Position ← padsData[i].trans.off;
pt1, pt2: INT;
object: CD.Object;
IF side#bottom THEN RETURN;
IF min>max THEN ERROR;
SELECT padsData[i].trans.orient
FROM
original => {pt1 ← min+pos.x; pt2 ← max+pos.x; side ← bottom; object ← top};
rotate180 => {pt1 ← pos.x+dx-max; pt2 ← pos.x+dx-min; side ← top; object ← bottom};
rotate90 => {pt1 ← pos.y+min; pt2 ← pos.y+max; side ← right; object ← left};
rotate270 => {pt1 ← pos.y+dx-max; pt2 ← pos.y+dx-min; side ← left; object ← right};
ENDCASE => ERROR;
IF NOT IsRoutable[parameters, side, layer] THEN RETURN;
IF pt1>pt2 THEN ERROR;
AddConnection[nets, data.internal, actual, object, pt1, pt2, side, layer];
};
[] ← PWCore.Layout[padsData[i].instance.type]; -- to make sure the cellType is decorated
[] ← CoreGeometry.EnumerateNonOverlappingSides[PWCore.extractMode.decoration, padsData[i].instance.type, EachPadWirePin];
ENDLOOP;
-- Call Cabbage
innerPos ← CDBasics.AddPoints[parameters.centerDisplacement, Cabbage.Center[inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left, params]];
CoreGeometry.PutTrans[PWCore.extractMode.decoration, innerInstance, [[innerPos.x+dy, innerPos.y+dy]]];
CedarProcess.CheckAbort[];
CedarProcess.SetPriority[background];
obj ← Cabbage.PadLimitedRoute[inner, bottomLeft, bottom, bottomRight, right, topRight, top, topLeft, left, innerPos, nets, params, CoreOps.GetCellTypeName[cellType]];
CedarProcess.SetPriority[priority];
};