NewPadFrameImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Louis Monier June 14, 1986 6:32:41 pm PDT
Bertrand Serlet March 14, 1987 1:50:05 am PST
Last Edited by: Louis Monier April 28, 1987 1:38:11 pm PDT
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
Common types
ROPE: TYPE = Core.ROPE;
Wire: TYPE = Core.Wire;
WireSeq: TYPE = Core.WireSeq;
CellType: TYPE = Core.CellType;
CellInstance: TYPE = CoreCreate.CellInstance;
Utilities
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];
};
Layout Proc
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]].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];
};
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: ROPEIF prop=NIL OR prop=$Metal2 THEN "metal2" ELSE "metal";
-- default: metal2
horizLayer: ROPEIF 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}
];
};
Decorate Proc
DecoratePadframe: PWCore.DecorateProc = {
CoreGeometry.PutRecordLazyPins[PWCore.extractMode.decoration, cellType, CD.InterestRect[obj]];
};
Initialization
[] ← PWCore.RegisterLayoutAtom[$NewPadFrame, LayoutPadFrame, DecoratePadframe, AttributePadFrame];
END.