<> <> 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.ROPE _ NIL, cdOb: CD.Object _ NIL, bindings: LIST OF WirePair]; WirePair: TYPE = RECORD [ formal, actual: Rope.ROPE _ NIL]; 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"]; <> <> <> <> <> <> <<>> 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, >> <> <> 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.ROPE _ NIL] = { 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 = { <> 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.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]]; <> 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.