IFUPWSwitchBox.mesa,
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, November 26, 1985 7:26:40 pm PST
DIRECTORY
Basics,
CD,
CDCells USING [CreateEmptyCell, SetInterestRect],
CDDirectory,
IFUPW,
IO,
PW,
Rope,
SymTab;
IFUPWSwitchBox: CEDAR PROGRAM
IMPORTS CD, CDCells, IFUPW, IO, PW, Rope, SymTab
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
Node:   TYPE = REF NodeRec;
NodeRec:  TYPE = RECORD[
name: Rope.ROPE,
row: INT ← rowNotAssigned,
minX: INT,
maxX: INT ← 0,
top: LIST OF INTNIL,
bot: LIST OF INTNIL ];
rowNotAssigned:  INT = -1;
LeftEdge: PROC RETURNS[INT] =
{RETURN[- leftTail]};
RightEdge: PROC[rp: RowParams] RETURNS[INT] =
{RETURN[LeftEdge[] + rp.rngBit*rp.rngByte*cellWidth]};
SwitchBoxRow: PUBLIC PROC [
design: CD.Design,
name:  PW.ROPE,
rowType: CD.Layer,
topRP:  RowParams ← IFUDataColNSeq,
top:  LIST OF REF,
left:  List,
right:  List,
bot:  LIST OF REF,
botRP:  RowParams ← IFUDataColNSeq,
m2Pitch: BOOLFALSE ]
RETURNS [cell: CD.Object] = {
rowWW:  INTIF rowType = cmosPoly THEN polW ELSE met2W;
xTweak:  INT ← (cnctSize-metW)/2;
pFrng:  INT ← (pwrW-metW)/2;
pitch:   Size ← [metPitch,
(IF rowType#cmosPoly OR m2Pitch THEN met2Pitch ELSE polPitch)];
ctct:   CD.Object ← IFUPW.Contact[rowType];
nofRows:  INT ← 0;
nodes:   LIST OF Node ← NIL;
ltEdge:  LIST OF Node ← NIL;
rtEdge:  LIST OF Node ← NIL;
pass:   LIST OF Node ← NIL;
conn:   LIST OF Node ← NIL;
assigned:  LIST OF Node ← NIL;
temps:   LIST OF Node ← NIL;
cellMinX:  INT ← RightEdge[topRP];
yMax:   INT ← 0;
yMin:   INT ← 0;
iRect:   CD.Rect;
symTab:  SymTab.Ref ← SymTab.Create[];
SortNodes: SymTab.EachPairAction = {
node: Node ← NARROW[val];
SELECT TRUE FROM
node.minX = LeftEdge[ ]   => ltEdge ← UpdateNotAssigned[ltEdge, node];
node.maxX = RightEdge[topRP] => rtEdge ← UpdateNotAssigned[rtEdge, node];
node.maxX - node.minX = 0  => pass  ← UpdateNotAssigned[pass,  node];
ENDCASE        => conn  ← UpdateNotAssigned[conn, node];
RETURN[FALSE] };
cell  ← CDCells.CreateEmptyCell[];
left ← DelGVFromList[left];
right ← DelGVFromList[right];
UpdateSymTabWithList[topRP, symTab, left,  left, pitch];
UpdateSymTabWithList[topRP, symTab, right, right, pitch];
FOR index: INT DECREASING IN [0..topRP.rngBit ) DO
FOR byte: INT DECREASING IN [0..topRP.rngByte) DO
topl: List ← ExpandList[byte, index, top];
botl: List ← ExpandList[byte, index, bot];
topl ← DelGVFromList[topl]; -- won't delete indexed versions (ie. "GND.23")
botl ← DelGVFromList[botl]; -- won't delete indexed versions (ie. "GND.23")
UpdateSymTabWithList[topRP, symTab, topl, top,   pitch, byte, index];
UpdateSymTabWithList[botRP, symTab, botl, bottom,  pitch, byte, index];
ENDLOOP;
ENDLOOP;
Check for internal connections
[ ] ← SymTab.Pairs[symTab, SortNodes];
FOR nodePtr: LIST OF Node ← ltEdge, nodePtr.rest WHILE nodePtr#NIL DO
assigned ← AddUnassignedNodeToAssigned
[nodePtr.first, assigned, pitch, rowType, topRP];
ENDLOOP;
FOR nodePtr: LIST OF Node ← rtEdge, nodePtr.rest WHILE nodePtr#NIL DO
assigned ← AddUnassignedNodeToAssigned
[nodePtr.first, assigned, pitch, rowType, topRP];
ENDLOOP;
FOR nodePtr: LIST OF Node ← conn, nodePtr.rest WHILE nodePtr#NIL DO
assigned ← AddUnassignedNodeToAssigned
[nodePtr.first, assigned, pitch, rowType, topRP];
ENDLOOP;
Draw wires
yMax ← 0;
FOR nodePtr: LIST OF Node ← assigned, nodePtr.rest WHILE nodePtr#NIL DO
yMax ← MAX[yMax, nodePtr.first.row] ENDLOOP;
yMax ← yMax + cnctSize/2 + topTail;
yMin ←  0  - cnctSize/2  - botTail - lambda;
FOR ii: INT IN [0..topRP.rngBit*topRP.rngByte) DO FOR jj: INT IN [6..7] DO-- GND VDD
name: Rope.ROPE ← (IF jj=6 THEN GND ELSE VDD);
xx:  INT   ← ii*cellWidth + jj*pitch.x;
cellMinX    ← MIN[ cellMinX, xx-pFrng];
PutPin [cell, [metW,  metW],   [xx,  yMax-metW], cmosMet, name];
PutPin [cell, [metW,  metW],   [xx,   yMin],  cmosMet, name];
AddRet [cell, [pwrW, yMax-yMin], [xx-pFrng, yMin],  cmosMet];
ENDLOOP ENDLOOP;
FOR nodePtr: LIST OF Node ← pass, nodePtr.rest WHILE nodePtr#NIL DO-- pass
name:  Rope.ROPE ← nodePtr.first.name;
vgNode: BOOL   ← Rope.Find[name,"GND"]#-1 OR Rope.Find[name,"VDD"]#-1;
xx:   INT   ← nodePtr.first.minX;
xxx:  INT   ← xx;
wireW: INT   ← metW;
IF vgNode THEN {wireW ← pwrW; xxx ← xx-pFrng};
IF nodePtr.first.top=NIL OR nodePtr.first.bot=NIL THEN ERROR Error[ IO.PutFR[
"Signal %g is not connected anywhere", IO.rope[nodePtr.first.name]]];
cellMinX ← MIN[ cellMinX, xx];
PutPin [cell, [wireW, metW],    [xx,  yMax-metW], cmosMet, name];
PutPin [cell, [wireW, metW],    [xx,  yMin],   cmosMet, name];
AddRet [cell, [wireW, yMax-yMin],  [xxx, yMin],   cmosMet];
ENDLOOP;
FOR nodePtr: LIST OF Node ← assigned, nodePtr.rest WHILE nodePtr#NIL DO -- top bot
name:  Rope.ROPE ← nodePtr.first.name;
vgNode: BOOL   ← Rope.Find[name,"GND"]#-1 OR Rope.Find[name,"VDD"]#-1;
yMid:  INT   ← nodePtr.first.row;
minX:  INT   ← nodePtr.first.minX;
maxX:  INT   ← nodePtr.first.maxX;
cellMinX     ← MIN[ cellMinX, minX];
IF minX=LeftEdge[] THEN {
PutPin[cell, [rowWW, rowWW], [minX,    yMid-rowWW/2], rowType, name]};
IF maxX=RightEdge[topRP] THEN {
PutPin[cell, [rowWW, rowWW], [maxX-rowWW, yMid-rowWW/2], rowType, name]};
AddRet [cell, [maxX-minX, rowWW], [minX, yMid-rowWW/2], rowType];
FOR nodeTop: LIST OF INT ← nodePtr.first.top, nodeTop.rest WHILE nodeTop#NIL DO
xx:  INT ← nodeTop.first;
IF vgNode
THEN AddRet[cell, [pwrW, yMax-yMid],  [xx-pFrng, yMin], cmosMet]
ELSE AddRet[cell, [metW, yMax-yMid],  [xx,   yMid], cmosMet];
PutPin [cell, [metW, metW],      [xx, yMax-metW], cmosMet, name];
cellMinX ← MIN[ cellMinX, xx-xTweak];
[] ← PW.IncludeInCell[cell, ctct, [xx-xTweak, yMid-cnctSize/2]];
ENDLOOP;
FOR nodeBot: LIST OF INT ← nodePtr.first.bot, nodeBot.rest WHILE nodeBot#NIL DO
xx:  INT ← nodeBot.first;
IF vgNode
THEN AddRet[cell, [pwrW, yMid-yMin], [xx-pFrng, yMin], cmosMet]
ELSE AddRet[cell, [metW, yMid-yMin], [xx,   yMin], cmosMet];
PutPin [cell, [metW, metW],      [xx,  yMin], cmosMet, name];
cellMinX ← MIN[ cellMinX, xx-xTweak];
[] ← PW.IncludeInCell[cell, ctct, [xx-xTweak, yMid-cnctSize/2]];
ENDLOOP ;
ENDLOOP;
PW.IncludeInDirectory[design, cell];
iRect ← CD.InterestRect[cell];
iRect.x1 ← iRect.x1 -  (cellMinX-LeftEdge[ ]);
iRect.x2 ← iRect.x1 + (RightEdge[topRP]-LeftEdge[ ]);
CDCells.SetInterestRect[cell, iRect];
PW.RenameObject[design, cell, name];
RETURN[cell]};
UpdateSymTabWithList: PROC
[rp: RowParams, symTab: SymTab.Ref, names: List, side:Side, pitch: Size, idx1, idx2: INT 𡤀]={
FOR index: INT ← 0, index+1 WHILE names#NIL DO
node:  Node;
found: BOOL;
val:  REF;
coord:  INT;
IF names.first # NIL THEN {
[found, val] ← SymTab.Fetch[symTab, names.first];
IF found
THEN node ← NARROW[val]
ELSE {
node ← NEW[NodeRec ← [name: names.first, minX: RightEdge[rp]]];
[ ] ← SymTab.Store[symTab, names.first, node] };
coord ← IFUPW.ByteBitToIndex[idx1, idx2, rp]*cellWidth + index*pitch.x;
SELECT side FROM
left => {node.minX ← LeftEdge[ ]};
right => {node.maxX ← RightEdge[rp]};
top => {
node.top  ← CONS [coord, node.top];
node.minX ← MIN [coord, node.minX];
node.maxX ← MAX [coord, node.maxX] };
bottom => {
node.bot  ← CONS [coord, node.bot];
node.minX ← MIN [coord, node.minX];
node.maxX ← MAX [coord, node.maxX] };
ENDCASE => ERROR };
names ← names.rest;
ENDLOOP};
UpdateNotAssigned: PROC[list: LIST OF Node, node: Node] RETURNS [LIST OF Node] = {
test: INT;
IF list = NIL THEN RETURN[CONS[node, list]];
test ← (list.first.maxX-list.first.minX)-(node.maxX-node.minX);
IF test = 0 THEN test ← (node.minX)-(list.first.minX);
IF test < 0
THENRETURN[CONS[node, list]]
ELSE {list.rest ← UpdateNotAssigned[list.rest, node]; RETURN[list]}};
AddUnassignedNodeToAssigned: PROC
[node: Node, orig: LIST OF Node, pitch: Size, rowType: CD.Layer, rp: RowParams]
RETURNS [list: LIST OF Node] = {
padX: INTIF rowType=cmosMet2 THEN pitch.x ELSE 0; -- met2 => can't be adjacent
list ← orig;
IF list=NIL THEN {node.row ← 0; RETURN[CONS[node, list]]};
IF node.maxX < list.first.minX-padX
THEN {node.row ← list.first.row; RETURN[CONS[node, list] ]};
FOR sList: LIST OF Node ← list, sList.rest DO
nextMinX, nextRow: INT;
IF sList.rest#NIL
THEN {nextMinX ← sList.rest.first.minX; nextRow ← sList.rest.first.row}
ELSE {nextMinX ← RightEdge[rp]+padX+1; nextRow ← sList.first.row+pitch.y};
IF sList.first.row#nextRow
THEN {
IF sList.first.maxX+padX >= node.minX
AND node.maxX+padX >= nextMinX THEN LOOP;
IF sList.first.maxX+padX < node.minX
THEN node.row ← sList.first.row
ELSE node.row ← nextRow;
sList.rest ← CONS[node, sList.rest];
EXIT}
ELSE {
IF sList.first.maxX+padX >= node.minX OR node.maxX+padX >= nextMinX THEN LOOP;
node.row ← sList.first.row;
sList.rest ← CONS[node, sList.rest];
EXIT}
ENDLOOP;
RETURN[list]};
GenMetalPinRow: PUBLIC PROC [
design:  CD.Design,
name:   Rope.ROPE,
height:  INT ← 6,
top:   LIST OF REF,
rp:    RowParams ← IFUDataColNSeq ]
RETURNS [cellName: CD.Object] = {
obj: CD.Object ← CDCells.CreateEmptyCell[];
iRect: CD.Rect;
FOR ii: INT IN [0..rp.rngByte*rp.rngBit) DO
names:  List;
byte, index: INT;
sigIndex:  INT ← -1;
[byte, index] ← IFUPW.ByteBitFromIndex[ii, rp];
names   ← ExpandList[byte, index, top];
names ← FixGVInList[names];
FOR names ← names, names.rest WHILE names#NIL DO
sigIndex ← sigIndex+1;
IF names.first=NIL THEN LOOP;
AddRet [obj, [6, height], [ii*cellWidth+sigIndex*metPitch, 0], cmosMet];
PutPin [obj, [6, 6],   [ii*cellWidth+sigIndex*metPitch, 0], cmosMet, names.first];
ENDLOOP;
ENDLOOP;
PW.IncludeInDirectory[design, obj];
iRect ← CD.InterestRect[obj];
iRect.x1 ← iRect.x1 - leftTail;
iRect.x2 ← rp.rngByte*rp.rngBit*cellWidth + iRect.x1;
CDCells.SetInterestRect[obj, iRect];
cellName ← PWBasics.NameFromObj[obj];
cellName ← PW.ReName[cellName, name];
RETURN[cellName]};
SwitchBoxRowTest: IFUPW.UserProc = { RETURN[ SwitchBoxRow[
design:  design,
rowType: cmosMet2,
top:  LIST[NIL, "PBus." ],
right:  LIST
["Alpha.0", "Alpha.1", "Alpha.2", "Alpha.3", "Alpha.4", "Alpha.5", "Alpha.6", "Alpha.7"],
left: NIL,
bot: LIST[LIST["Alpha.", NIL, NIL, NIL], "PBus." ] ] ] };
PW.Register [SwitchBoxRowTest,  "SwitchBoxRowTest"];
END.