BondingPadsImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Don Curry June 7, 1988 9:46:55 am PDT
DIRECTORY
BondingPads, BrineIO, CD, CDBasics, CDRects, CMosB, Core, CoreGeometry, CoreGeometryBackdoor, CoreIO, CoreOps, CoreProperties, IO, PWCore, RefTab;
BondingPadsImpl: CEDAR PROGRAM
IMPORTS
BrineIO, CD, CDBasics, CDRects, CMosB, CoreGeometry, CoreGeometryBackdoor, CoreIO, CoreOps, CoreProperties, PWCore, RefTab
EXPORTS BondingPads
~ BEGIN
Types
PadArray: TYPE = BondingPads.PadArray;
Side:   TYPE = CoreGeometry.Side;
SidePads:  TYPE = BondingPads.SidePads;
Pads:   TYPE = BondingPads.Pads;
Pad:   TYPE = BondingPads.Pad;
tech:   CD.Technology ← CMosB.cmosB;
Mark Bonding Pads
MarkBondingPads: PUBLIC PROC[cell: Core.CellType] ~ {
overGlass:   CD.Layer  ← CD.FetchLayer[tech, $ovg];
cut2:     CD.Layer  ← CD.FetchLayer[tech, $cut2];
layDeco:    CoreGeometry.Decoration ← PWCore.extractMode.decoration;
ect:     Core.CellType;
extractedToSource: RefTab.Ref;
layout:    CD.Object;
bondingFrameSize: REF CD.Position;
fourteen:    INT ← tech.lambda*14;
IsBig: PROC[ob: CD.Object] RETURNS[isBig: BOOL] = {
Ref [Cherry]<MPCCIF>7.0>XrVTI4x>CDMEBESCMOSB16Nov87.load:
oxidePad ← ((met2-10) AND (ovg OR cut2))-4
IF met2 always covers cut2 THEN (min dimension of cut2 > 14) => ovg
size: CD.Position ← CD.InterestSize[ob];
RETURN[size.x > fourteen AND size.y > fourteen]};
EachAtomic: PROC[wire: Core.Wire] ~ {
sourceWire: Core.Wire ← NARROW[RefTab.Fetch[extractedToSource, wire].val];
instances:  LIST OF CoreGeometry.Instance;
EachInst: CoreGeometry.EachInstanceProc ~ { -- instance RETURNS quit
IF ~CDRects.IsBareRect[instance.obj]
THEN [] ← CoreGeometry.FlattenInstance[instance, EachInst]
ELSE {
IF instance.obj.layer=overGlass OR
(instance.obj.layer=cut2 AND IsBig[instance.obj]) THEN
instances ← CONS[instance, instances]}};
name: IO.ROPE;
IF sourceWire=NIL THEN RETURN;
instances ← NARROW[CoreProperties.GetWireProp[sourceWire, $BondingPads]];
name ← CoreOps.GetFullWireName[cell.public, sourceWire];
[] ← CoreGeometry.EnumerateAllGeometry[layDeco, ect, wire, EachInst];
IF instances=NIL THEN TerminalIO.PutF["No pad for: %g\n",IO.rope[name]];
instances ← MergeSort[instances];
CoreProperties.PutWireProp[sourceWire, $BondingPads, instances]};
IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]#NIL THEN RETURN;
[] ← PWCore.Layout[cell];
IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]#NIL THEN RETURN;
[layout, ect, extractedToSource, ] ← PWCore.LayoutInfo[cell];
CoreOps.VisitRootAtomics[ect.public, EachAtomic];
bondingFrameSize ← NEW[CD.Position ← CD.InterestSize[layout]];
CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, bondingFrameSize]};
EnsureBondingPads: PUBLIC PROC[cell: Core.CellType] = {
IF CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]=NIL THEN
IF cell.class.recast=NIL THEN MarkBondingPads[cell] ELSE {
recast:   Core.CellType ← CoreOps.Recast[cell];
size:   REF CD.Position;
EachPair: PROC[actualWire, publicWire: Core.Wire]
RETURNS [subWires: BOOLTRUE, quit: BOOLFALSE]= {
origWire:  Core.Wire ← actualWire;
recastWire: Core.Wire ← publicWire;
origInsts:   LIST OF CoreGeometry.Instance ←
NARROW[CoreProperties.GetWireProp[origWire, $BondingPads]];
recastInsts:  LIST OF CoreGeometry.Instance ←
NARROW[CoreProperties.GetWireProp[recastWire, $BondingPads]];
IF origInsts#NIL
THEN RETURN -- recasted and original publics identical => this wire done
ELSE FOR recastInsts ← recastInsts, recastInsts.rest WHILE recastInsts#NIL DO
origInsts ← CONS[recastInsts.first, origInsts] ENDLOOP;
CoreProperties.PutWireProp[origWire, $BondingPads, origInsts]};
EnsureBondingPads[recast];
[]𡤌oreOps.VisitBindingSeq[cell.public, recast.public, EachPair];
size ← NARROW[CoreProperties.GetCellTypeProp[recast, $BondingFrameSize]];
CoreProperties.PutCellTypeProp[cell, $BondingFrameSize, NEW[CD.Position ← size^]] } };
GetSize: PUBLIC PROC[cell: Core.CellType] RETURNS[size: CD.Position] = {
refSize: REF CD.Position
NARROW[CoreProperties.GetCellTypeProp[cell, $BondingFrameSize]];
RETURN[refSize^]};
GetPads: PUBLIC PROC[cell: Core.CellType] RETURNS[padArray: PadArray] = {
size: CD.Position ← GetSize[cell];
cRect: CD.Rect  ← [0, 0, size.x, size.y];
eachPublic: PROC[wire: Core.Wire] = {
instances: LIST OF CoreGeometry.Instance ←
NARROW[CoreProperties.GetWireProp[wire, $BondingPads]];
FOR instances ← instances, instances.rest WHILE instances#NIL DO
ir:  CD.Rect  ← CoreGeometry.BBox[instances.first];
side: Side   ← NearestSide[ir, cRect];
offSet: CD.Position ← OffSet[ir, cRect, side];
pad: Pad   ← [wire, offSet];
padArray[side].pads ← CONS[pad, padArray[side].pads] ENDLOOP };
Collect pads
[]𡤌oreOps.VisitRootAtomics[cell.public, eachPublic];
FOR side: Side IN Side DO
offSets: LIST OF INTNIL;
Find (and check) offsets
FOR pads: Pads ← padArray[side].pads, pads.rest WHILE pads#NIL DO
offSets ← CONS[pads.first.pos.x, offSets];
FOR oSets: LIST OF INT ← offSets, oSets.rest WHILE oSets#NIL AND oSets.rest#NIL DO
TwoInts: TYPE = RECORD[i0, i1: INT];
IF oSets.first < oSets.rest.first THEN EXIT;
IF oSets.first = oSets.rest.first THEN {oSets.rest ← oSets.rest.rest; EXIT};
[oSets.first, oSets.rest.first] ← TwoInts[oSets.rest.first, oSets.first] ENDLOOP;
ENDLOOP;
padArray[side].offSets ← offSets;
IF offSets=NIL THEN LOOP;
IF offSets.rest#NIL THEN{
IF offSets.rest.rest#NIL THEN ERROR;
IF offSets.rest.first-offSets.first<100*tech.lambda THEN ERROR};
Sort by y then x
DO
done: BOOLTRUE;
FOR pads: Pads ← padArray[side].pads, pads.rest WHILE pads#NIL AND pads.rest#NIL DO
TwoPads: TYPE = RECORD[p0, p1: Pad];
IF pads.first.pos.y < pads.rest.first.pos.y THEN {
--IF (pads.rest.first.pos.y-pads.first.pos.y) < 100*tech.lambda THEN ERROR-- LOOP};
IF pads.first.pos.y > pads.rest.first.pos.y OR pads.first.pos.x > pads.rest.first.pos.x THEN
{[pads.first, pads.rest.first] ← TwoPads[pads.rest.first, pads.first]; done ← FALSE}
ENDLOOP;
IF done THEN EXIT ENDLOOP;
ENDLOOP};
CompareRectBottomLeft: PROC [rect1: CD.Rect, rect2: CD.Rect] RETURNS [BOOL] = {
overlappingInY: BOOL ← rect1.y1<rect2.y2 AND rect2.y1<rect1.y2;
RETURN[IF overlappingInY
THEN rect1.x1 < rect2.x1
ELSE rect1.y1 < rect2.y1]};
MergeSort: PROC[instances: LIST OF CoreGeometry.Instance]
RETURNS[LIST OF CoreGeometry.Instance] = {
TwoInstances: TYPE = RECORD[i1, i2: CoreGeometry.Instance];
DO
done: BOOLTRUE;
list: LIST OF CoreGeometry.Instance ← instances;
FOR list ← list, list.rest WHILE list#NIL AND list.rest#NIL DO
ir1:  CD.Rect ← CoreGeometry.BBox[list.first];
ir2:  CD.Rect ← CoreGeometry.BBox[list.rest.first];
xr:   CD.Rect ← CDBasics.Intersection[ir1, ir2];
touch:  BOOL  ← (xr.x2 >= xr.x1) AND (xr.y2 >= xr.y1);
IF touch
THEN {
union: CD.Rect  ← CDBasics.Surround[ir1, ir2];
size:   CD.Position ← CDBasics.SizeOfRect[union];
pos:   CD.Position ← CDBasics.BaseOfRect[union];
newObj:  CD.Object  ← CDRects.CreateRect[size, list.first.obj.layer];
list.rest ← list.rest.rest;
list.first ← [newObj, [pos]];
done  ← FALSE}
ELSE {
IF ~CompareRectBottomLeft[ir1, ir2]
THEN {[list.first, list.rest.first]←TwoInstances[list.rest.first, list.first]; done←FALSE}};
ENDLOOP;
IF done THEN EXIT ENDLOOP;
RETURN[instances]};
NearestSide: PROC[sml, lrg: CD.Rect] RETURNS[side: Side ← left] ~ {
dist: INT ← ABS[lrg.x1 - sml.x1];
test: INT ← ABS[lrg.x2 - sml.x2]; IF test < dist THEN {dist ← test; side ← right};
test  ← ABS[lrg.y1 - sml.y1]; IF test < dist THEN {dist ← test; side ← bottom};
test  ← ABS[lrg.y2 - sml.y2]; IF test < dist THEN {dist ← test; side ← top}};
OffSet: PROC[sml, lrg: CD.Rect, side: Side] RETURNS[offSet: CD.Position] ~ {
The offSet when building a left side normalized set of pads. X is the distance in and y is the distance up.
offSet ← SELECT side FROM
left  => [(sml.x1+sml.x2)/2 - lrg.x1,  (sml.y1+sml.y2)/2],
right  => [lrg.x2 - (sml.x1+sml.x2)/2,  (sml.y1+sml.y2)/2],
bottom => [(sml.y1+sml.y2)/2 - lrg.y1, (sml.x1+sml.x2)/2],
top  => [lrg.y2 - (sml.y1+sml.y2)/2, (sml.x1+sml.x2)/2],
ENDCASE => ERROR };
Initialization
PropWriteInstances: CoreIO.PropWriteProc =
{CoreGeometryBackdoor.WriteInstances[stream, NARROW[value]]};
PropReadInstances: CoreIO.PropReadProc =
{value ← CoreGeometryBackdoor.ReadInstances[stream]};
PropWriteSize: CoreIO.PropWriteProc = {
pos: REF CD.Position ← NARROW[value];
BrineIO.WriteInt[stream, pos.x];
BrineIO.WriteInt[stream, pos.y]};
PropReadSize: CoreIO.PropReadProc = {
pos: REF CD.Position ← NEW[CD.Position ← [0,0]];
pos.x ← BrineIO.ReadInt[stream];
pos.y ← BrineIO.ReadInt[stream];
value ← pos};
[]𡤌oreIO.RegisterProperty[$BondingPads, PropWriteInstances, PropReadInstances];
[]𡤌oreIO.RegisterProperty[$BondingFrameSize, PropWriteSize, PropReadSize];
END.