PadFrameMakerImpl.mesa
Frank Bowers June 19, 1986 11:24:23 am PDT
DIRECTORY
Cabbage,
CD,
CDOrient,
CDProperties,
CDSymbolicObjects,
CMos,
Connections,
Core,
CoreClasses,
CoreOps,
CoreProperties,
PadFrameMaker,
PW,
PWPins,
Rope,
RTBasic,
SCCoreUtil,
CDCells;
PadFrameMakerImpl: CEDAR PROGRAM
IMPORTS Cabbage, CD, CDCells, CMos, CoreOps, CDProperties, Connections, CoreProperties, CDSymbolicObjects, PW, PWPins, Rope, SCCoreUtil
EXPORTS PadFrameMaker
~ BEGIN
ListPadData: TYPE = LIST OF PadData;
PadData: TYPE = REF PadDataRec;
PadDataRec: TYPE = RECORD [
type: Rope.ROPENIL,
cdOb: CD.Object ← NIL,
bindings: LIST OF WirePair];
WirePair: TYPE = RECORD [
formal, actual: Rope.ROPENIL];
CollectBindings: PROC [cellInstance: CoreClasses.CellInstance]
RETURNS[bindings: LIST OF WirePair ← NIL] = {
DoWire: CoreOps.EachWirePairProc = {
wirePair: WirePair ← [];
IF actualWire # NIL AND actualWire.size = 0 AND publicWire # NIL AND publicWire.size = 0 THEN {
wirePair.formal ← NARROW[CoreProperties.GetWireProp[publicWire, CoreOps.nameProp]];
wirePair.actual ← NARROW[CoreProperties.GetWireProp[actualWire, CoreOps.nameProp]];
bindings ← CONS[wirePair, bindings];
};
};
[] ← CoreOps.VisitBinding[cellInstance.actual, cellInstance.type.public, DoWire];
};
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.ROPENARROW[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];
};
GetSignal: PROC [bindings: LIST OF WirePair, formal: Rope.ROPE]
RETURNS [actual: Rope.ROPENIL] = {
FOR bl: LIST OF WirePair ← bindings, bl.rest UNTIL bl = NIL DO
IF Rope.Equal[bl.first.formal, formal] THEN RETURN [bl.first.actual];
ENDLOOP;
};
AddSignalPins: PROC [padCell: CD.Object, padData: LIST OF PadData, layer: CD.Layer] = {
xPos: CD.Number ← 0;
list: LIST OF PadData ← NIL;
MakeSignalPin: PWPins.InstanceEnumerator = {
InstEnumerator: TYPE = PROC [inst: CD.Instance] RETURNS [quit: BOOLFALSE];
pinOb: CD.Object ← CDSymbolicObjects.CreatePin[inst.ob.size];
pinInst: CD.Instance ← NIL;
signal: Rope.ROPE ← GetSignal[list.first.bindings, CDSymbolicObjects.GetName[inst]];
IF Rope.Equal[signal, "unconnected"] THEN RETURN;
pinInst ← PW.IncludeInCell[
padCell, pinOb, [xPos+inst.location.x, inst.location.y]];
CDSymbolicObjects.SetName[pinInst, signal];
CDSymbolicObjects.SetLayer[pinInst, layer];
};
FOR list ← padData, list.rest UNTIL list = NIL DO
[] ← PWPins.EnumerateEdgePins[ob: list.first.cdOb, eachPin: MakeSignalPin];
xPos ← xPos + list.first.cdOb.size.x;
ENDLOOP;
};
IncludeCell: PROC [rowOb: PW.Object, name: Rope.ROPENIL, stopEnumerateDeepPins: BOOLEANTRUE] 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]};
END.