IFUPWSwitchBoxOld.mesa,
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, June 6, 1985 0:50:51 am PDT
DIRECTORY
Basics,
CD,
CDCells USING [CreateEmptyCell, SetInterestRect],
CDDirectory,
CMos,
CMosContacts,
IFUPW,
IO,
PW,
PWBasics,
SymTab;
IFUPWSwitchBox: CEDAR PROGRAM
IMPORTS
CD, CDCells, CMosContacts, CMos, IFUPW, IO, PW, PWBasics, SymTab
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
Node:   TYPE = REF NodeRec;
NodeRec:  TYPE = RECORD[
name: PW.ROPE,
row: INT ← rowNotAssigned,
minX: INT ← rightEdge,
maxX: INT ← 0,
top: LIST OF INTNIL,
bot: LIST OF INTNIL ];
rightEdge: INT = rngBit*rngByte*cellWidth-leftTail;
leftEdge:  INT = - leftTail;
rowNotAssigned:  INT = -1;
SwitchBoxRow: PUBLIC PROC [ -- Assumes byte interleaving (rngBit cells of rngByte bits)
design: CD.Design,
name:  PW.ROPE,
rowType: CD.Layer,
topSeq: BOOLFALSE,
top:  LIST OF REF,
left:  List,
right:  List,
bot:  LIST OF REF,
botSeq: BOOLFALSE,
fixGV: BOOLTRUE ]
RETURNS [cellName: PW.ObjName] = {
colType:  CD.Layer ← CMos.met;
pitch:   Size ← [metPitch, (IF rowType=CMos.pol THEN polPitch ELSE met2Pitch)];
cntctW:  INTIF rowType = CMos.pol THEN 8 ELSE 10;
cntctBotTail: INTIF rowType = CMos.pol THEN 2 ELSE 2;
colWW:  INT ← (pitch.x-2)/2; -- 14=>6
rowWW:  INT ← (pitch.y-2)/2; -- 10=>4, 18=>8
ctct:   CD.ObPtr ← (SELECT rowType FROM
CMos.pol  => CMosContacts.CreatePolyCon [l: cntctW],
CMos.met2  => CMosContacts.CreateMmCon [l: cntctW],
ENDCASE  => ERROR);
nofRows:  INT ← 0;
nodes:   LIST OF Node ← NIL;
assigned:  LIST OF Node ← NIL;
nAsigned: LIST OF Node ← NIL;
straightPass: LIST OF Node ← NIL;
tempNodes: LIST OF Node ← NIL;
cell:   CD.ObPtr ← CDCells.CreateEmptyCell[];
cellMinX:  INT ← rightEdge;
topTail:  INT ← 4;
botTail:  INTSELECT rowType FROM CMos.pol=>2, CMos.met2=>4, ENDCASE=>ERROR;
yMax:   INT ← 0;
yMin:   INT ← 0;
iRect:   CD.Rect;
symTab:  SymTab.Ref ← SymTab.Create[];
SortNodes: SymTab.EachPairAction = {
node: Node ← NARROW[val];
IF node.row#rowNotAssigned
THEN assigned ← AddAssignedNodeToAssigned[node, assigned] -- Unique rows
ELSEIF node.minX=node.maxX
THEN straightPass ← UpdateNotAssigned[straightPass, node] -- Biggest first
ELSE nAsigned  ← UpdateNotAssigned[nAsigned, node]; -- Biggest first
RETURN[FALSE] };
IF fixGV THEN {
left ← DelGVFromList[left];
right ← DelGVFromList[right];
top ← AddGVToLIST[top, IF topSeq=botSeq THEN TRUE ELSE FALSE];
bot ← AddGVToLIST[bot, IF topSeq=botSeq THEN TRUE ELSE FALSE] };
nofRows ← UpdateSymTabWithList[symTab, left, left, pitch, nofRows];
nofRows ← UpdateSymTabWithList[symTab, right, right, pitch, nofRows];
FOR index: INT DECREASING IN [0..rngBit) DO
FOR byte: INT DECREASING IN [0..rngByte) DO
topl: List ← ExpandList[byte, index, top];
botl: List ← ExpandList[byte, index, bot];
IF fixGV THEN {
topl ← DelGVFromList[topl]; -- won't delete indexed versions (ie. "GND.23")
botl ← DelGVFromList[botl]}; -- won't delete indexed versions (ie. "GND.23")
[ ] ← UpdateSymTabWithList[symTab, topl, top,  pitch, 0, byte, index, topSeq];
[ ] ← UpdateSymTabWithList[symTab, botl, bottom, pitch, 0, byte, index, botSeq];
ENDLOOP;
ENDLOOP;
Check for internal connections
[ ] ← SymTab.Pairs[symTab, SortNodes];
FOR nodePtr: LIST OF Node ← nAsigned, nodePtr.rest WHILE nodePtr#NIL DO
assigned ← AddUnassignedNodeToAssigned
[nodePtr.first, assigned, nofRows, pitch, rowType];
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 - cntctBotTail + cntctW + topTail;
yMin ← 0  - cntctBotTail     - botTail;
FOR nodePtr: LIST OF Node ← straightPass, nodePtr.rest WHILE nodePtr#NIL DO
name:  PW.ROPE ← nodePtr.first.name;
minX:  INT  ← nodePtr.first.minX;
maxX:  INT  ← nodePtr.first.maxX;
cellMinX    ← MIN[ cellMinX, minX];
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]]];
AddRet [cell, [colWW, yMax-yMin], [minX, yMin],   colType];
PutPin [cell, [colWW, colWW],  [minX,  yMax-colWW], colType, name];
PutPin [cell, [colWW, colWW],  [minX,  yMin],   colType, name];
ENDLOOP;
FOR nodePtr: LIST OF Node ← assigned, nodePtr.rest WHILE nodePtr#NIL DO
yMid:  INT  ← nodePtr.first.row;
name:  PW.ROPE ← nodePtr.first.name;
minX:  INT  ← nodePtr.first.minX;
maxX:  INT  ← nodePtr.first.maxX;
cellMinX    ← MIN[ cellMinX, minX];
IF minX=leftEdge THEN {
PutPin [cell, [rowWW, rowWW], [minX,   yMid], rowType, name]};
IF maxX=rightEdge THEN {
PutPin [cell, [rowWW, rowWW], [maxX-rowWW, yMid], rowType, name]};
AddRet [cell, [maxX-minX, rowWW], [minX, yMid], rowType];
FOR nodeTop: LIST OF INT ← nodePtr.first.top, nodeTop.rest WHILE nodeTop#NIL DO
xx: INT ← nodeTop.first;
AddRet [cell, [colWW, yMax-yMid], [xx, yMid],   colType];
PutPin [cell, [colWW, colWW],  [xx, yMax-colWW], colType, name];
cellMinX ← MIN[ cellMinX,      xx-2]; -- -2 for left contact overhang
[] ← PWBasics.IncludeApplication[cell, ctct, [xx-2, yMid-2]];
ENDLOOP;
FOR nodeBot: LIST OF INT ← nodePtr.first.bot, nodeBot.rest WHILE nodeBot#NIL DO
xx: INT ← nodeBot.first;
AddRet [cell, [6, yMid-yMin], [xx, yMin],  colType];
PutPin [cell, [6, 6],    [xx,  yMin],  colType, name];
cellMinX ← MIN[ cellMinX,      xx-2]; -- -2 for left contact overhang
[] ← PWBasics.IncludeApplication[cell, ctct, [xx-2, yMid-2]];
ENDLOOP ;
ENDLOOP;
PWBasics.RepositionCell[design, cell];
iRect ← CD.InterestRect[cell];
iRect.x1 ← iRect.x1 -  (cellMinX-leftEdge);
iRect.x2 ← iRect.x1 + (rightEdge-leftEdge);
CDCells.SetInterestRect[cell, iRect];
cellName ← PWBasics.NameFromObj[cell];
cellName ← PW.ReName[cellName, name];
RETURN[cellName]};
UpdateSymTabWithList: PROC
[symTab: SymTab.Ref, names: List, side:Side, pitch: Size, startRows, idx1, idx2: INT ← 0, seq: BOOLFALSE] RETURNS[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]];
[ ] ← SymTab.Store[symTab, names.first, node] };
IF side IN [right..left]
THEN {coord ← startRows*pitch.y; startRows ← startRows+1}
ELSE coord ←
IFUPW.ByteBitToIndex[idx1, idx2, seq]*cellWidth + index*pitch.x;
SELECT side FROM
left => {node.row ← coord; node.minX ← leftEdge};
right => {node.row ← coord; node.maxX ← rightEdge};
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;
RETURN[startRows]};
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]}};
AddAssignedNodeToAssigned: PROC-- Assume rows are unique
[node: Node, orig: LIST OF Node] RETURNS [list: LIST OF Node] = {
list ← orig;
IF list=NIL OR node.row < list.first.row THEN {RETURN[ CONS[node, list] ]};
FOR sList: LIST OF Node ← list, sList.rest DO
IF sList.rest=NIL OR node.row < sList.rest.first.row
THEN {sList.rest ← CONS[node, sList.rest]; EXIT} ENDLOOP;
RETURN[list]};
AddUnassignedNodeToAssigned: PROC
[node: Node, orig: LIST OF Node, startRows: INT, pitch: Size, rowType: CD.Layer]
RETURNS [list: LIST OF Node] = {
padX: INTIF rowType=CMos.met2 THEN pitch.x ELSE 0; -- met2 => can't be adjacent
list ← orig;
IF list=NIL THEN
{node.row ← startRows*pitch.y; 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+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:   PW.ROPE,
height:  INT ← 6,
top:   LIST OF REF,
seq:   BOOLFALSE,
fixGV:  BOOLTRUE ]
RETURNS [cellName: PW.ObjName] = {
obj: CD.ObPtr ← CDCells.CreateEmptyCell[];
iRect: CD.Rect;
FOR ii: INT IN [0..rngByte*rngBit) DO
names:  List;
byte, index: INT;
sigIndex:  INT ← -1;
[byte, index] ← IFUPW.ByteBitFromIndex[ii, seq];
names   ← ExpandList[byte, index, top];
IF fixGV THEN 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], CMos.met];
PutPin [obj, [6, 6],   [ii*cellWidth+sigIndex*metPitch, 0], CMos.met, names.first];
ENDLOOP;
ENDLOOP;
PWBasics.RepositionCell[design, obj];
iRect ← CD.InterestRect[obj];
iRect.x1 ← iRect.x1 - leftTail;
iRect.x2 ← rngByte*rngBit*cellWidth + iRect.x1;
CDCells.SetInterestRect[obj, iRect];
cellName ← PWBasics.NameFromObj[obj];
cellName ← PW.ReName[cellName, name];
RETURN[cellName]};
SwitchBoxRowTest: PW.UserProc = { RETURN[ SwitchBoxRow[
design:  design,
rowType: CMos.met2,
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.