MakePadRows: 
PUBLIC 
PROC [
libDesign, resultDesign: CD.Design, padFrameCell: Core.CellType, inner: CD.Object]
RETURNS [chip: CD.Object] = {
pads: ARRAY RTBasic.Side OF PW.ListOb ← ALL[NIL];
padData: ARRAY RTBasic.Side OF ListPadData ← ALL[NIL];
padCells: ARRAY RTBasic.Side OF CD.Object ← ALL[NIL];
side: RTBasic.Side ← RTBasic.Side.FIRST;
sideName: ARRAY RTBasic.Side OF Rope.ROPE ← ["bottom", "top", "left", "right"];
orientation: ARRAY RTBasic.Side OF CD.Orientation ← [CDOrient.rotate180, CDOrient.original, CDOrient.rotate90, CDOrient.rotate270];
connections: Connections.Table;
routerParams: Cabbage.PadRingParams ← NEW[Cabbage.PadRingParamsRec ← ["metal", "metal2", resultDesign.technology.key]];
innerPos: CD.Position ← [0,0];
layers: ARRAY RTBasic.Side OF CD.Layer ← [CMos.met2, CMos.met2, CMos.met, CMos.met];
bottomLeft: CD.Object ← PW.Get[libDesign, "C2LB37V"];
topLeft: CD.Object ← PW.Get[libDesign, "C2LT37G"];
topRight: CD.Object ← PW.Get[libDesign, "C2RT37V"];
bottomRight: CD.Object ← PW.Get[libDesign, "C2RB37G"];
Get  layout for standard cell pads from padFrameCell  ob ← PW.Get[libDesign, objectName];
divide pads into 4 groups: top left bottom and right  PW.ListOb for each group
create cells from each group by abutting PW.AbutListX
create signal pins on top level cell for each group
must keep Core celltype and CellInstance for actual-formal signal mapping
perhaps attach core to CD cellinstance
 
ProcessInstance: SCCoreUtil.EachInstanceProc = {
[cellInstance: CoreClasses.CellInstance]
name: Rope.ROPE ← NARROW[CoreProperties.GetCellTypeProp[cellInstance.type, CoreOps.nameProp]];
IF Rope.Match["C2*", name, 
FALSE] 
THEN  {
ob: CD.Object ← PW.Get[libDesign, name];
bindings: LIST OF WirePair ← NIL;
pads[side] ← CONS[ob, pads[side]];
bindings ← CollectBindings[cellInstance];
padData[side] ← CONS[NEW[PadDataRec ← [name, ob, bindings]], padData[side]];
}
 
ELSE {
ChangeToSignalPin: PWPins.RenameProc = {
RETURN[GetSignal[bindings, oldRope]];
};
 
bindings: LIST OF WirePair ← CollectBindings[cellInstance];
inner ← PWPins.RenamePins[ob: inner, renameProc: ChangeToSignalPin];
};
 
IF side = RTBasic.Side.LAST THEN side ← RTBasic.Side.FIRST ELSE side ← SUCC[side];
};
 
[] ← SCCoreUtil.EnumerateInstances[padFrameCell, ProcessInstance];
FOR side 
IN RTBasic.Side 
DO
abutOb: CD.Object ← PW.AbutListX[pads[side]];
padCells[side] ← IncludeCell[abutOb, sideName[side]];
AddSignalPins[padCells[side], padData[side], layers[side]];
padCells[side] ← PW.ChangeOrientation[padCells[side], orientation[side]];
[] ← CDCells.IncludeOb[design: resultDesign, 
cell: NIL, ob: padCell, position: [0, 0], orientation: orientation[side], 
cellCSystem: interrestCoords, obCSystem: interrestCoords, mode: dontPropagate];
 
ENDLOOP;
 
innerPos ← Cabbage.Center[inner, bottomLeft, padCells[bottom], bottomRight, padCells[right], topRight, padCells[top], topLeft, padCells[left], routerParams];
connections ← GetConnections[inner, padCells[bottom], padCells[right], padCells[top], padCells[left]];
chip ← Cabbage.PadRoute[inner, bottomLeft, padCells[bottom], bottomRight, padCells[right], topRight, padCells[top], topLeft, padCells[left], [innerPos.x-30, innerPos.y], connections, routerParams];
[] ← CDCells.IncludeOb[design: resultDesign, 
cell: NIL, ob: chip, position: [0, 0], orientation: CDOrient.original, 
cellCSystem: interrestCoords, obCSystem: interrestCoords, mode: dontPropagate];
PW.CleanUp[resultDesign];
};
 
GetConnections: 
PROC [inner, bottom, right, top, left: Cabbage.Object] 
RETURNS [connections: Connections.Table] ~ {
UseAll: Connections.PinFilterProc ~ {keepIt ← TRUE};
UseTop: Connections.PinFilterProc ~ {keepIt ← PWPins.GetSide[obj, inst].side=top};
UseLeft: Connections.PinFilterProc ~ {keepIt ← PWPins.GetSide[obj, inst].side=left};
UseBottom: Connections.PinFilterProc ~ {keepIt ← PWPins.GetSide[obj, inst].side=bottom};
UseRight: Connections.PinFilterProc ~ {keepIt ← PWPins.GetSide[obj, inst].side=right};
connections ← Connections.CreateForRopes[];
Connections.InsertPins[connections, inner, UseAll];
Connections.InsertPins[connections, bottom, UseTop];
Connections.InsertPins[connections, right, UseLeft];
Connections.InsertPins[connections, top, UseBottom];
Connections.InsertPins[connections, left, UseRight];
};
 
IncludeCell: 
PROC [rowOb: 
PW.Object, name: Rope.
ROPE ← 
NIL, stopEnumerateDeepPins: 
BOOLEAN ← 
TRUE] 
RETURNS [rCell: 
CD.Object] = {
rCellPtr: CD.CellPtr;
inst: CD.Instance;
rCell ← PW.CreateEmptyCell[];
rCellPtr ← NARROW [rCell.specificRef];
inst ← NEW [CD.InstanceRep ← [ob: rowOb]];
CDProperties.PutInstanceProp[inst, $InstanceName, name];
IF stopEnumerateDeepPins 
THEN
CDProperties.PutProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
 
rCellPtr.contents ← CONS [inst, rCellPtr.contents];
rCellPtr.name ← name;
CDCells.SetInterestRect[rCell, CD.InterestRect[rowOb]];
[] ← PW.RepositionCell[rCell]};