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]].x1<minX THEN {left ← data[i]; minX ← BBox[data[i]].x1};
IF BBox[data[i]].x2>maxX THEN {right ← data[i]; maxX ← BBox[data[i]].x2};
IF BBox[data[i]].y1<minY THEN {bottom ← data[i]; minY ← BBox[data[i]].y1};
IF BBox[data[i]].y2>maxY 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];
};
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}
];
};