PadFrameImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Louis Monier April 29, 1986 1:16:26 pm PDT
Bertrand Serlet May 8, 1986 10:37:45 pm PDT
DIRECTORY
CD, CDBasics, CDCells, CDOrient, CDProperties, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, HashTable, OnionCore, OnionCoreArc, PW, PWCore, PadFrame, Rope, Sinix, Sisyph;
PadFrameImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDProperties, CoreClasses, CoreCreate, CoreOps, CoreProperties, HashTable, OnionCore, PW, PWCore, Rope, Sisyph
EXPORTS PadFrame =
BEGIN OPEN CoreCreate, PadFrame;
ROPE: TYPE = PW.ROPE;
packagePinProp: PUBLIC ATOM ← $PinInPackage;
padFrameParamsProp: PUBLIC ATOM ← $PadFrameParams;
padDesign: PUBLIC CD.Design;
padCx: Sisyph.Context;
AtomToObjName: PROC [atom: ATOM] RETURNS [rope: ROPE] ~ {
rope ← SELECT atom FROM
$Vdd => "VddPad",
$Gnd => "GndPad",
$PadVdd => "PadVddPad",
$PadGnd => "PadGndPad",
$In => "InputPad",
$Out => "OutputPad",
$Clk => "ClockPad",
$IOTst => "IOTstPad",
$Corner => "CornerPad",
$Filler => "FillerPad",
ENDCASE => ERROR;
RETURN[Rope.Cat[rope, ".sch"]];
};
PadExtract: PROC [name: ROPE] RETURNS [cellType: Core.CellType] ~ {
cellType ← Sisyph.ExtractSchematicByName[name: name, cx: padCx];
PWCore.SetGet[cellType, padDesign];
};
AddPad: PUBLIC PROC [iL: CellInstances, pad: WR, type: ATOM, pos: NAT, pa1, pa2, pa3, pa4: PA ← []] RETURNS [newInsts: CellInstances] ~ {
ct: CellType ← PadExtract[AtomToObjName[type]];
inst: CellInstance ← SELECT type FROM
$Vdd, $Gnd, $PadVdd, $PadGnd => Instance[type: ct], -- all bindings are implicit 
ENDCASE => Instance[type: ct, pa1: ["Pad", pad], pa2: pa1, pa3: pa2, pa4: pa3, pa5: pa4];
CoreProperties.PutCellInstanceProp[inst, packagePinProp, NEW[NAT ← pos]];
newInsts ← CONS[inst, iL];
};
-- posL should have same length as pad.size
AddPads: PUBLIC PROC [iL: CellInstances, pad: Wire, type: ATOM, posL: LIST OF NAT, pa1, pa2, pa3, pa4: PA ← []] RETURNS [newInsts: CellInstances] ~ {
i: NAT ← 0;
FOR positionL: LIST OF NAT ← posL, positionL.rest WHILE positionL#NIL DO
newInsts ← AddPad[iL, pad[i], type, positionL.first, pa1, pa2, pa3, pa4];
i←i+1;
ENDLOOP;
};
Segment: PUBLIC PROC [first, size: NAT] RETURNS [list: LIST OF NATNIL] ~ {
FOR i: NAT IN [0..size) DO
list ← CONS[first+i, list];
ENDLOOP;
};
LayoutDontFlatten: PROC [cellType: CellType] RETURNS [obj: CD.Object] = {
obj ← PWCore.Layout[cellType];
CDProperties.PutObjectProp[obj, $DontFlatten, $DontFlatten];
};
PadData: TYPE = RECORD [
instance: CoreClasses.CellInstance ← NIL,
pos: CD.Position ← [0, 0],
rot: CD.Orientation ← CDOrient.original
];
AllPadsData: TYPE = RECORD [c: SEQUENCE nbOfPads: NAT OF PadData];
PadFrame: PUBLIC PWCore.LayoutProc = {
IsCorner: PROC [i: NAT] RETURNS [BOOLFALSE] ~ {
RETURN[i=0 OR i=ny OR i=ny+nx OR i=2*ny+nx];
};
rotT: CD.Orientation = CDOrient.original;
rotL: CD.Orientation = CDOrient.rotate90;
rotB: CD.Orientation = CDOrient.rotate180;
rotR: CD.Orientation = CDOrient.rotate270;
pos: CD.Position; -- current pad origin
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
inner: CoreClasses.CellInstance ← NIL;
nets: HashTable.Table ← HashTable.Create[];
-- measure one pad
cornerPad: CD.Object ← PWCore.Layout[PadExtract[AtomToObjName[$Corner]]];
fillerPad: CD.Object ← PWCore.Layout[PadExtract[AtomToObjName[$Filler]]];
padSize: CD.Position ← CD.InterestSize[fillerPad];
params: PadFrameParameters ← NARROW[CoreProperties.GetCellTypeProp[cellType, padFrameParamsProp]];
nx: NAT ← params.nbPadsX;
ny: NAT ← params.nbPadsY;
dx: INT ← padSize.x;
dy: INT ← padSize.y;
nbOfPads: NAT ← nx + ny + nx + ny;
allPads: REF AllPadsData ← NEW [AllPadsData[nbOfPads]];
outerSize: CD.Position ← [(nx-1)*dx, (ny-1)*dx];
innerSize: CD.Position;
-- fill allPads[i].instance and inner
FOR i: NAT IN [0 .. data.size) DO
refNat: REF NATNARROW [CoreProperties.GetCellInstanceProp[data[i], packagePinProp]];
SELECT TRUE FROM
refNat=NIL AND inner#NIL => ERROR;
refNat=NIL => inner ← data[i];
allPads[refNat^].instance#NIL => ERROR;
ENDCASE => allPads[refNat^].instance ← data[i];
ENDLOOP;
-- Left
pos ← [-dy, dx*(ny-1)];
IF allPads[0].instance#NIL THEN ERROR;
allPads[0].pos ← pos; allPads[0].rot ← rotT;        -- ul
FOR i: NAT IN [1..ny) DO
pos.y ← pos.y-dx;
allPads[i].pos ← pos; allPads[i].rot ← rotL;
ENDLOOP;
-- Bottom
pos ← [-dy, -dy];
IF allPads[ny].instance#NIL THEN ERROR;
allPads[ny].pos ← pos; allPads[ny].rot ← rotL;       -- ll
pos.x ← 0;
FOR i: NAT IN [ny+1 .. ny+nx) DO
allPads[i].pos ← pos; allPads[i].rot ← rotB;
pos.x ← pos.x+dx;
ENDLOOP;
-- Right
pos ← [(nx-1)*dx, -dy];
IF allPads[ny+nx].instance#NIL THEN ERROR;
allPads[ny+nx].pos ← pos; allPads[ny+nx].rot ← rotB;     -- lr
pos.y ← pos.y+dy;
FOR i: NAT IN [ny+nx+1 .. ny+nx+ny) DO
allPads[i].pos ← pos; allPads[i].rot ← rotR;
pos.y ← pos.y+dx;
ENDLOOP;
-- Top
pos ← [(nx-1)*dx, dx*(ny-1)];
IF allPads[2*ny+nx].instance#NIL THEN ERROR;
allPads[2*ny+nx].pos ← pos; allPads[2*ny+nx].rot ← rotR;    -- ur
FOR i: NAT IN [2*ny+nx+1 .. 2*ny+nx+nx) DO
pos.x ← pos.x-dx;
allPads[i].pos ← pos; allPads[i].rot ← rotT;
ENDLOOP;
-- Start with an empty cell
obj ← PW.CreateEmptyCell[];
-- Position the inner
innerSize ← CD.InterestSize[PWCore.Layout[inner.type]];
IF params.innerPos=[0, 0] THEN {
params.innerPos ← CDBasics.SubPoints[outerSize, innerSize];
params.innerPos ← [params.innerPos.x/2, params.innerPos.y/2];
};
[] ← PW.IncludeInCell[obj, LayoutDontFlatten[inner.type], params.innerPos];
-- Include all the pads in obj
FOR i: NAT IN [0 .. nbOfPads) DO
[] ← PW.IncludeInCell[
obj,
IF allPads[i].instance=NIL
THEN IF IsCorner[i] THEN cornerPad ELSE fillerPad
ELSE LayoutDontFlatten[allPads[i].instance.type],
allPads[i].pos,
allPads[i].rot
];
ENDLOOP;
-- Create the nets for the inner
BEGIN
EachInnerWirePin: PWCore.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[inner, wire];
name: ROPE ← CoreOps.GetFullWireName[data.internal, actual];
net: OnionCore.Net ← NARROW [HashTable.Fetch[nets, actual].value];
IF layer#params.radialLayer THEN RETURN;
IF net=NIL THEN {net ← NEW [OnionCore.NetRec ← [name: name]]; [] ← HashTable.Store[nets, actual, net]};
IF min>max THEN ERROR;
min ← min+(IF side=left OR side=right THEN params.innerPos.y ELSE params.innerPos.x);
max ← max+(IF side=left OR side=right THEN params.innerPos.y ELSE params.innerPos.x);
IF min>max THEN ERROR;
IF side=top OR side=left THEN {w: INT ← min; min ← max; max ← w};
net.innerSegs ← CONS [
NEW [OnionCoreArc.SegRec ← [min, max, side, side]],
net.innerSegs];
};
[] ← PWCore.EnumerateWirePins[inner.type, EachInnerWirePin];
END;
-- Create the nets for the pads
FOR i: NAT IN [0 .. nbOfPads) DO
EachPadWirePin: PWCore.EachWirePinProc ~ {
actual: Wire ← CoreClasses.CorrespondingActual[allPads[i].instance, wire];
name: ROPE ← CoreOps.GetFullWireName[data.internal, actual];
net: OnionCore.Net ← NARROW [HashTable.Fetch[nets, actual].value];
pos: CD.Position ← allPads[i].pos;
innerSide: PWCore.Side;
pt1, pt2: INT;
IF layer#params.radialLayer THEN RETURN;
IF side#bottom THEN RETURN;
IF net=NIL THEN {net ← NEW [OnionCore.NetRec ← [name: name]]; [] ← HashTable.Store[nets, actual, net]};
IF min>max THEN ERROR;
SELECT allPads[i].rot FROM
rotT => {pt1 ← min+pos.x; pt2 ← max+pos.x; innerSide ← top};
rotB => {pt1 ← pos.x+dx-max; pt2 ← pos.x+dx-min; innerSide ← bottom};
rotL => {pt1 ← pos.y+min; pt2 ← pos.y+max; innerSide ← left};
rotR => {pt1 ← pos.y+dx-max; pt2 ← pos.y+dx-min; innerSide ← right};
ENDCASE => ERROR;
IF pt1>pt2 THEN ERROR;
IF innerSide=top OR innerSide=left THEN {w: INT ← pt1; pt1 ← pt2; pt2 ← w};
net.outerSegs ← CONS [
NEW [OnionCoreArc.SegRec ← [pt1, pt2, innerSide, innerSide]],
net.outerSegs];
};
IF allPads[i].instance#NIL THEN [] ← PWCore.EnumerateWirePins[allPads[i].instance.type, EachPadWirePin];
ENDLOOP;
PW.SetInterestRect[obj, outerSize];
-- Call Onion
IF NOT OnionCore.IncludeInOuter[obj, nets, params.innerPos, innerSize, outerSize, params.radialLayer, params.ringLayer] THEN ERROR;
PW.RepositionCell[obj];
obj ← PW.Flatten[obj];
};
DecoratePadFrame: PWCore.DecorateProc = {
Who cares?
};
Init: PROC ~ {
defaultGlobalNames: LIST OF ROPECONS["PadGnd", CONS["PadVdd", Sisyph.defaultGlobalNames]];
IF padDesign=NIL THEN { -- not yet read
padDesign ← PW.OpenDesign["Pads"];
padCx ← Sisyph.Create[design: padDesign, globalNames: defaultGlobalNames];
};
};
[] ← PWCore.RegisterLayoutAtom[$PadFrame, PadFrame, DecoratePadFrame];
Init[];
END.