PadFrameImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Bertrand Serlet September 10, 1987 11:17:02 pm PDT
Louis Monier October 7, 1987 12:52:31 pm PDT
Don Curry May 18, 1988 10:30:43 am PDT
Implements the Layout atom $PadFrame
Corners may be used.
Correctly deals with the case of multiple possible routing layers on the inner.
Decorates using CoreRoute.DecorateRoutedArea.
Derived from BicPadFrame
DIRECTORY
BondingPads, Cabbage, CD, CDBasics, CDProperties, CDSimpleRules, CMosBExtras, Connections, Core, CoreClasses, CoreCreate, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PadFrame, PWCore, Rope, Route, RTBasic, Sinix, TerminalIO;
PadFrameImpl: CEDAR PROGRAM
IMPORTS BondingPads, Cabbage, CD, CDBasics, CDProperties, CDSimpleRules, CMosBExtras, Connections, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, Rope, Route, TerminalIO
EXPORTS PadFrame = BEGIN
Common types
ROPE:     TYPE = Core.ROPE;
Wire:     TYPE = Core.Wire;
WireSeq:    TYPE = Core.WireSeq;
CellType:    TYPE = Core.CellType;
CellInstance:   TYPE = CoreCreate.CellInstance;
technologyKey: ATOM = $cmosB;
wireWidthProp: ATOM = $w;
lambda:   INT ← CDSimpleRules.GetTechnology[technologyKey].lambda;
Attribute, Layout and Decorate Procs
AttributePadFrame: PWCore.AttributesProc = {
ia: CoreRoute.InstanceArray ← CoreRoute.SortedInstanceArray[cellType]; -- reorders instances
name: IO.ROPE ← CoreOps.GetCellTypeName[cellType];
TerminalIO.PutF["PadFrame Layout: %g.\n", IO.rope[name]];
CoreRoute.ShowInstanceArray[ia];
IF ia.size#3 OR ia[0].size#3 THEN ERROR;
CoreProperties.PutCellTypeProp[cellType, $PadFrameInstanceArray, ia]};
LayoutPadFrame: PWCore.LayoutProc = {
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
ia:  CoreRoute.InstanceArray  ← NARROW[CoreProperties.GetCellTypeProp
[cellType, $PadFrameInstanceArray]];
cornersOK:  BOOL  ← ConstructCorners[ia];
innerDX:   INT  ← GetCTPropInt[cellType, $innerDX,  0];
innerDY:   INT  ← GetCTPropInt[cellType, $innerDY,  0];
outerChanWidth: INT  ← GetCTPropInt[cellType, $outerWidth,  90];
powerCellWidth: INT  ← GetCTPropInt[cellType, $powerWidth, 200];
leftSize:  CD.Position ← CD.InterestSize[PWCore.Layout[ia[1][0].type]];
rightSize:  CD.Position ← CD.InterestSize[PWCore.Layout[ia[1][2].type]];
topSize:  CD.Position ← CD.InterestSize[PWCore.Layout[ia[2][1].type]];
bottomSize: CD.Position ← CD.InterestSize[PWCore.Layout[ia[0][1].type]];
innerPos:  CD.Position;
bottomLeftInst: CellInstance ← ia[0][0];
bottomInst:  CellInstance ← ia[0][1];
bottomRightInst: CellInstance ← ia[0][2];
leftInst:   CellInstance ← ia[1][0];
innerInst:   CellInstance ← ia[1][1];
rightInst:   CellInstance ← ia[1][2];
topLeftInst:  CellInstance ← ia[2][0];
topInst:   CellInstance ← ia[2][1];
topRightInst:  CellInstance ← ia[2][2];
params:   Cabbage.PadRingParams;
metalLayer:  CD.Layer    ← CDSimpleRules.GetLayer[technologyKey, "Metal"];
vLayer:   CD.Layer;
hLayer:   CD.Layer;
nets:    Connections.Table ← Connections.CreateForRopes[];
[vLayer, hLayer] ← CoreRoute.GetCellTypePropLayer[cellType, $VerticalMetal, $met2];
params ← NEW [Cabbage.PadRingParamsRec ← [
horizLayer:    IF hLayer=metalLayer THEN "Metal" ELSE "Metal2",
vertLayer:    IF vLayer=metalLayer THEN "Metal" ELSE "Metal2",
technologyKey:   technologyKey,  -- $cmosB
outerBTChanWidth:  outerChanWidth, -- enough for xxx tracks
outerLRChanWidth:  outerChanWidth, -- enough for xxx tracks
powerBTCellWidth:  powerCellWidth,  -- xxx lambda power busses
powerLRCellWidth:  powerCellWidth,  -- xxx lambda power busses
opt:      noIncompletes,
signalSinglePinNets:  TRUE ]];
IF NOT(bottomSize.x=topSize.x AND leftSize.y=rightSize.y) THEN ERROR;
Layer changes from inner to pads; vLayer is vertical for inner and horizontal for pads.
ConnectionsFromList[data, nets, leftInst,  right,  vLayer];
ConnectionsFromList[data, nets, rightInst, left,  vLayer];
ConnectionsFromList[data, nets, topInst,  bottom, hLayer];
ConnectionsFromList[data, nets, bottomInst, top,  hLayer];
ConnectionsFromList[data, nets, innerInst, right,  hLayer];
ConnectionsFromList[data, nets, innerInst, left,  hLayer];
ConnectionsFromList[data, nets, innerInst,  bottom, vLayer];
ConnectionsFromList[data, nets, innerInst, top,  vLayer];
innerPos ← CDBasics.AddPoints[
[innerDX*lambda, innerDY*lambda],
Cabbage.Center[
inner:   InstLayout[innerInst],
bottomLeft: InstLayout[bottomLeftInst],
bottom:  InstLayout[bottomInst],
bottomRight: InstLayout[bottomRightInst],
right:   InstLayout[rightInst],
topRight:  InstLayout[topRightInst],
top:   InstLayout[topInst],
topLeft:  InstLayout[topLeftInst],
left:   InstLayout[leftInst],
parms:  params] ];
PutInstTrans[innerInst,    innerPos];
PutInstTrans[bottomLeftInst, [0,        0]];
PutInstTrans[bottomInst,  [leftSize.x,     0]];
PutInstTrans[bottomRightInst, [leftSize.x+bottomSize.x, 0]];
PutInstTrans[rightInst,   [leftSize.x+bottomSize.x, bottomSize.y]];
PutInstTrans[topLeftInst,  [0,        bottomSize.y+leftSize.y]];
PutInstTrans[topInst,   [leftSize.x,     bottomSize.y+leftSize.y]];
PutInstTrans[topRightInst,  [leftSize.x+bottomSize.x, bottomSize.y+leftSize.y]];
PutInstTrans[leftInst,    [0,        bottomSize.y]];
obj ← Cabbage.PadLimitedRoute[
inner:   InstLayout[innerInst],
bottomLeft: InstLayout[bottomLeftInst],
bottom:  InstLayout[bottomInst],
bottomRight: InstLayout[bottomRightInst],
right:   InstLayout[rightInst],
topRight:  InstLayout[topRightInst],
top:   InstLayout[topInst],
topLeft:  InstLayout[topLeftInst],
left:   InstLayout[leftInst],
innerPos:  innerPos,
connections: nets,
parms:  params,
name:   CoreOps.GetCellTypeName[cellType] ] };
DecoratePadFrame: PWCore.DecorateProc = {
WireToLabels: PROC [wire: Core.Wire] RETURNS [labels: LIST OF IO.ROPENIL] =
{RETURN[LIST[CoreRoute.LabelInternal[data.internal, wire]]]};
name: IO.ROPE ← CoreOps.GetCellTypeName[cellType];
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
size: REF CD.Position ← NEW[CD.Position ← CD.InterestSize[obj]];
ia:  CoreRoute.InstanceArray ← NARROW[CoreProperties.GetCellTypeProp
[cellType, $PadFrameInstanceArray]];
markBondingPads: REF BOOLNARROW[CoreProperties.GetCellTypeProp
[cellType, $MarkBondingPads]];
CoreRoute.DecorateRoutedArea[cellType, obj, WireToLabels, CoreRoute.CompareXorYStack];
MarkBondingPads
IF markBondingPads=NIL OR ~markBondingPads^ THEN RETURN;
IF markBondingPads#NIL AND ~markBondingPads^ THEN RETURN;
TerminalIO.PutF["Marking Bonding Pads: %g.\n", IO.rope[name]];
CoreProperties.PutCellTypeProp[cellType, $BondingFrameSize, size];
FOR row: INT IN [0..3) DO
FOR col: INT IN [0..3) DO
eachPair: CoreOps.EachWirePairProc = {
aList: LIST OF CoreGeometry.Instance ←
NARROW[CoreProperties.GetWireProp[actualWire, $BondingPads]];
pList: LIST OF CoreGeometry.Instance ←
NARROW[CoreProperties.GetWireProp[publicWire, $BondingPads]];
trans: CoreGeometry.Transformation
← CoreGeometry.GetTrans[PWCore.extractMode.decoration, ia[row][col]];
FOR pList ← pList, pList.rest WHILE pList#NIL DO
inst: CoreGeometry.Instance ← pList.first;
inst.trans ← CDBasics.ComposeTransform[pList.first.trans, trans];
aList ← CONS[inst, aList] ENDLOOP;
CoreProperties.PutWireProp[actualWire, $BondingPads, aList]};
IF row=1 AND col=1 THEN LOOP;
IF ia[row][col]=NIL THEN LOOP;
name ← CoreOps.GetCellTypeName[ia[row][col].type];
TerminalIO.PutF[" Mark Pads: [%g, %g] %g.\n",
IO.int[row], IO.int[col], IO.rope[name]];
BondingPads.MarkBondingPads[ia[row][col].type];
[]𡤌oreOps.VisitBinding[ia[row][col].actual, ia[row][col].type.public, eachPair];
ENDLOOP;
ENDLOOP};
Utilities
ShowInstances: PROC[list: LIST OF CoreGeometry.Instance] =
{FOR list ← list, list.rest WHILE list#NIL DO ShowInstance[list.first] ENDLOOP};
ShowInstance: PROC[inst: CoreGeometry.Instance] = {
TerminalIO.PutRope["Layer: "]; ShowLayer[inst.obj.layer];
TerminalIO.PutRope[" IR: "];  ShowIR[CD.InterestRect[inst.obj]];
TerminalIO.PutRope[" Trans: "]; ShowTrans[inst.trans];
TerminalIO.PutRope["\n"]};
ShowLayer: PROC[layer: CD.Layer] = {TerminalIO.PutF["%g", IO.atom[CD.LayerKey[layer]]]};
ShowIR:  PROC[ir: CD.Rect] = {TerminalIO.PutF["[%g, %g, %g, %g]",
IO.int[ir.x1], IO.int[ir.y1], IO.int[ir.x2], IO.int[ir.y2]]};
ShowTrans:   PROC[trans: CD.Transformation] = {
TerminalIO.PutF["[[%g, %g] %g]",
IO.int[trans.off.x], IO.int[trans.off.y], IO.rope[orientRope[trans.orient]]]};
orientRope: ARRAY CD.Orientation OF IO.ROPE ← [
original: "original",
mirrorX: "mirrorX",
rotate90: "rotate90",
rotate90X: "rotate90X",
rotate180: "rotate180",
rotate180X: "rotate180X",
rotate270: "rotate270",
rotate270X: "rotate270X"];
InstLayout: PROC[inst: CellInstance] RETURNS[obj: CD.Object] =
{RETURN[IF inst=NIL THEN NIL ELSE PWCore.Layout[inst.type]]};
PutInstTrans: PROC[inst: CellInstance, off: CD.Position] = {
IF inst#NIL THEN {
irBase: CD.Position ← CDBasics.BaseOfRect[CD.InterestRect[PWCore.Layout[inst.type]]];
tranOff: CD.Position ← CDBasics.SubPoints[off, irBase];
CoreGeometry.PutTrans[PWCore.extractMode.decoration, inst, [tranOff]]}};
ConnectionsFromList: PROC
[data: CoreClasses.RecordCellType, nets: Connections.Table, inst: CellInstance, side: CoreGeometry.Side, layer: CD.Layer] ~ {
FOR l: CoreRoute.WirePins ← CoreRoute.FilteredInstanceLayoutPins[inst, side], l.rest
WHILE l#NIL DO
actual:  Wire ← l.first.wire;
name:   ROPE ← CoreRoute.LabelInternal[data.internal, actual];
widthVal: REF ← CoreProperties.GetWireProp[actual, wireWidthProp];
width:  INT ← IF widthVal = NIL THEN 0 ELSE NARROW[widthVal, REF INT]^;
net: Connections.Net ← Connections.Fetch[nets, name].net;
IF layer#l.first.layer THEN LOOP;
IF l.first.min > l.first.max THEN ERROR;
IF net=NIL THEN net ← NEW [Connections.NetRec ← [name: name, width: width]];
[] ← Connections.Store[nets, name, net];
net.segments ← CONS [
NEW [ Connections.SegmentRec ← [
object: PWCore.Layout[inst.type],
range:  [l.first.min, l.first.max],
side:  side,
layer:  l.first.layer]],
net.segments ];
ENDLOOP};
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]};
AddConnection: PROC [nets: Connections.Table, internal: WireSeq, actual: Wire, object: CD.Object, min, max: INT, side: CoreGeometry.Side, layer: CD.Layer] = {
name: ROPE ← CoreRoute.LabelInternal[internal, actual];
net: Connections.Net ← Connections.Fetch[nets, name].net;
widthVal: REF ANY ← CoreProperties.GetWireProp[actual, wireWidthProp];
width: INTIF widthVal = NIL THEN 0 ELSE NARROW[widthVal, REF INT]^;
IF net=NIL THEN {
net ← NEW [Connections.NetRec ← [name: name, width: width]];
[] ← Connections.Store[nets, name, net]};
net.segments ← CONS [ NEW [Connections.SegmentRec ←
[object: object, range: [min, max], side: side, layer: layer]],
net.segments]};
Name Extracted Pads
NameExtractedPads: PUBLIC PROC[source, extracted: Core.CellType] = {
CDProperties.PutLayerProp[CMosBExtras.bond, $RoutingLayer, $RoutingLayer];
[] ← PWCore.Layout[source]; -- make sure it's decorated
FOR side: CoreGeometry.Side IN CoreGeometry.Side DO
srcPins: CoreRoute.WirePins ← CoreRoute.LayPins[source,  side];
extPins: CoreRoute.WirePins ← CoreRoute.LayPins[extracted, side];
DO
FOR srcPins ← srcPins, srcPins.rest WHILE srcPins#NIL DO
IF srcPins.first.layer=CMosBExtras.bond THEN EXIT ENDLOOP;
FOR extPins ← extPins, extPins.rest WHILE extPins#NIL DO
IF extPins.first.layer=CMosBExtras.bond THEN EXIT ENDLOOP;
IF (srcPins=NIL)#(extPins=NIL) THEN ERROR;
IF srcPins=NIL THEN EXIT ELSE {
eNm: IO.ROPE ← CoreOps.GetShortWireName[extPins.first.wire];
sNm: IO.ROPE ← CoreRoute.LabelInternal[source.public, srcPins.first.wire];
IF eNm.Length[]=0 THEN eNm ← "-";
TerminalIO.PutF["Naming public: %20g ← %20g\n", IO.rope[sNm], IO.rope[eNm]];
[]𡤌oreOps.SetShortWireName[extPins.first.wire, sNm];
extPins ← extPins.rest;
srcPins ← srcPins.rest};
ENDLOOP;
ENDLOOP;
CoreOps.FlushNameCaches[extracted.public];
CoreRoute.FlushLayPinCache[source];
CoreRoute.FlushLayPinCache[extracted];
CDProperties.PutLayerProp[CMosBExtras.bond, $RoutingLayer, $RoutingLayer]};
LayoutWithOutRouteSignals
LayoutWithOutRouteSignals: PUBLIC PWCore.LayoutProc = {
TerminalIO.PutF["\nBEGIN: LayoutWithOutCabbageSignals: %g\n", IO.time[]];
obj ← PWCore.Layout[cellType !
Cabbage.Signal =>
{TerminalIO.PutF["*** Cabbage Signal: %g\n", IO.rope[explanation]]; RESUME};
Route.Signal  =>
{TerminalIO.PutF["*** Route Signal: %g\n", IO.rope[explanation]]; RESUME} ];
TerminalIO.PutF["\nEND: LayoutWithOutCabbageSignals: %g\n", IO.time[]]};
Initialization
[] ← PWCore.RegisterLayoutAtom
[$PadFrame, LayoutPadFrame, DecoratePadFrame, AttributePadFrame];
END.