<> <> <> <> <> DIRECTORY Cabbage, CD, CDBasics, CDSimpleRules, Connections, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, CoreGeometry, PWCore, PWRoute, Rope, Route, RTBasic, Sisyph, SymTab, TerminalIO; NewPadFrameImpl: CEDAR PROGRAM IMPORTS Cabbage, CD, CDBasics, CDSimpleRules, Connections, CoreClasses, CoreOps, CoreProperties, CoreGeometry, PWCore, Route, Sisyph, SymTab, TerminalIO = BEGIN <> ROPE: TYPE = Core.ROPE; Wire: TYPE = Core.Wire; WireSeq: TYPE = Core.WireSeq; CellType: TYPE = Core.CellType; CellInstance: TYPE = CoreCreate.CellInstance; <> GetCTPropBool: PROC [ct: CellType, prop: ATOM, default: BOOL] RETURNS [val: BOOL] ~ { ref: REF _ CoreProperties.GetCellTypeProp[ct, prop]; val _ IF ref=NIL THEN default ELSE NARROW[ref, REF BOOL]^; }; GetCTPropInt: PROC [ct: CellType, prop: ATOM, default: INT] RETURNS [val: INT] ~ { ref: REF _ CoreProperties.GetCellTypeProp[ct, prop]; val _ IF ref=NIL THEN default ELSE NARROW[ref, REF INT]^; }; GetCTPropRope: PROC [ct: CellType, prop: ATOM, default: ROPE] RETURNS [val: ROPE] ~ { ref: REF _ CoreProperties.GetCellTypeProp[ct, prop]; val _ IF ref=NIL THEN default ELSE NARROW[ref, ROPE]; }; SideToSide: PROC [side: CoreGeometry.Side] RETURNS [RTBasic.Side] = { RETURN [SELECT side FROM top => top, bottom => bottom, left => left, right => right, ENDCASE => ERROR ]; }; AddConnection: PROC [nets: Connections.Table, internal: WireSeq, actual: Wire, object: CD.Object, min, max: INT, side: CoreGeometry.Side, layer: CD.Layer] = { name: ROPE _ CoreOps.GetFullWireNames[internal, actual].first; net: Connections.Net _ Connections.Fetch[nets, actual].net; IF net=NIL THEN { net _ NEW [Connections.NetRec _ [name: name]]; [] _ Connections.Store[nets, actual, net]; }; net.segments _ CONS [ NEW [Connections.SegmentRec _ [object: object, range: [min, max], side: SideToSide[side], layer: layer]], net.segments]; }; <> BBox: PROC [inst: CellInstance] RETURNS [CD.Rect] ~ { RETURN[CDBasics.MapRect[CD.InterestRect[CoreGeometry.GetObject[Sisyph.mode.decoration, inst.type]], CoreGeometry.GetTrans[Sisyph.mode.decoration, inst]]] }; AttributePadFrame: PWCore.AttributesProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; minX, minY: INT _ LAST[INT]; maxX, maxY: INT _ FIRST[INT]; left, right, top, bottom: CellInstance _ NIL; IF data.size#5 THEN ERROR; -- 4 sides and inner FOR i: NAT IN [0..data.size) DO IF BBox[data[i]].x1maxX THEN {right _ data[i]; maxX _ BBox[data[i]].x2}; IF BBox[data[i]].y1maxY THEN {top _ data[i]; maxY _ BBox[data[i]].y2}; ENDLOOP; CoreProperties.PutCellInstanceProp[left, $PadFrameSide, $Left]; CoreProperties.PutCellInstanceProp[bottom, $PadFrameSide, $Bottom]; CoreProperties.PutCellInstanceProp[right, $PadFrameSide, $Right]; CoreProperties.PutCellInstanceProp[top, $PadFrameSide, $Top]; }; technologyKey: ATOM = $cmosB; wireWidthProp: ATOM = $w; lambda: INT _ CDSimpleRules.GetTechnology[technologyKey].lambda; SpecifiedWidthProc: PWRoute.WireWidthProc = { widthTab: SymTab.Ref _ NARROW[context]; ref: REF _ SymTab.Fetch[widthTab, netName].val; wireWidth _ IF ref=NIL THEN CDSimpleRules.MinWidth[CDSimpleRules.GetLayer[technologyKey, "metal2"]] ELSE lambda*NARROW[ref, REF INT]^; }; LayoutPadFrame: PWCore.LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; left, right, top, bottom, inner: CellInstance _ NIL; prop: REF _ CoreProperties.GetCellTypeProp[cellType, $VerticalMetal]; vertLayer: ROPE _ IF prop=NIL OR prop=$Metal2 THEN "metal2" ELSE "metal"; -- default: metal2 horizLayer: ROPE _ IF prop=NIL OR prop=$Metal2 THEN "metal" ELSE "metal2"; <<-- default: metal1>> outerChanWidth: INT _ GetCTPropInt[cellType, $outerWidth, 40]*lambda; --45 powerCellWidth: INT _ GetCTPropInt[cellType, $powerWidth, 270]*lambda; --220 hLayer: CD.Layer _ CDSimpleRules.GetLayer[technologyKey, horizLayer]; vLayer: CD.Layer _ CDSimpleRules.GetLayer[technologyKey, vertLayer]; params: Cabbage.PadRingParams _ NEW [Cabbage.PadRingParamsRec _ [ horizLayer: horizLayer, vertLayer: vertLayer, technologyKey: technologyKey, -- $cmosB wireWidthProc: SpecifiedWidthProc, outerChanWidth: outerChanWidth, -- enough for xxx tracks powerCellWidth : powerCellWidth, -- xxx lambda power busses opt: noIncompletes, signalIncomplete: TRUE, signalSinglePinNets: TRUE]]; nets: Connections.Table _ Connections.CreateForRefs[]; innerPos: CD.Position; leftSize, rightSize, topSize, bottomSize: CD.Position; IF data.size#5 THEN ERROR; -- 4 sides and inner FOR i: NAT IN [0..data.size) DO SELECT CoreProperties.GetCellInstanceProp[data[i], $PadFrameSide] FROM $Left => left _ data[i]; $Right => right _ data[i]; $Top => top _ data[i]; $Bottom => bottom _ data[i]; NIL => inner _ data[i]; ENDCASE => ERROR; ENDLOOP; IF left=NIL OR right=NIL OR top=NIL OR bottom=NIL OR inner=NIL THEN ERROR; leftSize _ CD.InterestSize[PWCore.Layout[left.type]]; rightSize _ CD.InterestSize[PWCore.Layout[right.type]]; topSize _ CD.InterestSize[PWCore.Layout[top.type]]; bottomSize _ CD.InterestSize[PWCore.Layout[bottom.type]]; IF NOT(bottomSize.x=topSize.x AND leftSize.y=rightSize.y) THEN ERROR; FOR i: NAT IN [0..data.size) DO EachWirePin: CoreGeometry.EachWirePinProc ~ { actual: Wire _ CoreClasses.CorrespondingActual[data[i], wire]; name: ROPE _ CoreOps.GetFullWireName[data.internal, actual]; <<-- warning: the new Cabbage changes layer from inner to pads, so pads on the left will use their pins in vertLayer!!!>> SELECT data[i] FROM left => IF side#right OR layer#vLayer THEN RETURN; right => IF side#left OR layer#vLayer THEN RETURN; top => IF side#bottom OR layer#hLayer THEN RETURN; bottom => IF side#top OR layer#hLayer THEN RETURN; inner => IF NOT (layer=(IF side=top OR side=bottom THEN vLayer ELSE hLayer)) THEN RETURN; ENDCASE => ERROR; IF min>max THEN ERROR; AddConnection[nets, data.internal, actual, PWCore.Layout[data[i].type], min, max, side, layer]; }; [] _ PWCore.Layout[data[i].type]; [] _ CoreGeometry.EnumerateNonOverlappingSides[PWCore.extractMode.decoration, data[i].type, EachWirePin]; ENDLOOP; <<>> <<-- Call Cabbage>> innerPos _ CDBasics.AddPoints[[0, 70*lambda], Cabbage.Center[ PWCore.Layout[inner.type], NIL, PWCore.Layout[bottom.type], NIL, PWCore.Layout[right.type], NIL, PWCore.Layout[top.type], NIL, PWCore.Layout[left.type], params]]; CoreGeometry.PutTrans[PWCore.extractMode.decoration, inner, [innerPos]]; CoreGeometry.PutTrans[PWCore.extractMode.decoration, bottom, [[leftSize.x, 0]]]; CoreGeometry.PutTrans[PWCore.extractMode.decoration, right, [[leftSize.x+bottomSize.x, bottomSize.y]]]; CoreGeometry.PutTrans[PWCore.extractMode.decoration, top, [[leftSize.x, bottomSize.y+leftSize.y]]]; CoreGeometry.PutTrans[PWCore.extractMode.decoration, left, [[0, bottomSize.y]]]; obj _ Cabbage.PadLimitedRoute[ inner: PWCore.Layout[inner.type], bottom: PWCore.Layout[bottom.type], right: PWCore.Layout[right.type], top: PWCore.Layout[top.type], left: PWCore.Layout[left.type], bottomLeft: NIL, bottomRight: NIL, topRight: NIL, topLeft: NIL, innerPos: innerPos, connections: nets, parms: params, name: CoreOps.GetCellTypeName[cellType] ! Cabbage.Signal => {TerminalIO.PutRopes["Cabbage message: ", explanation, "\n"]; RESUME}; Route.Signal => {TerminalIO.PutRopes["Route message: ", explanation, "\n"]; RESUME} ]; }; <> DecoratePadframe: PWCore.DecorateProc = { CoreGeometry.PutRecordLazyPins[PWCore.extractMode.decoration, cellType, CD.InterestRect[obj]]; }; <> [] _ PWCore.RegisterLayoutAtom[$NewPadFrame, LayoutPadFrame, DecoratePadframe, AttributePadFrame]; <<>> END. <<>>