SwitchBox.mesa,
Copyright c 1985 by Xerox Corporation. All rights reserved.
RemoveButton CD; CreateButton L Compile Latch; Run Latch
Last Edited by Curry, April 9, 1985 10:31:00 am PST
DIRECTORY
Basics,
CD,
CDCells USING [CreateEmptyCell],
CDDirectory,
CMos,
CMosContacts,
IFUPW,
PW,
PWBasics,
Rope;
SwitchBox: CEDAR PROGRAM
IMPORTS
CDCells, CMosContacts, CMos, IFUPW, PWBasics, Rope
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
rngByte: INT = 4;
rngBit: INT = 8;
ioRestRef: List ← LIST["VDD", "GND"];
SwitchBoxRow: PUBLIC PROC [ -- Assumes byte interleaving (rngBit cells of rngByte bits)
design:  CD.Design,
topSeq:  BOOL ← FALSE,
topRow:  LIST OF REF,
leftCol:  List,
rightCol:  List,
botRow:  LIST OF REF,
botSeq:  BOOL ← FALSE ]
RETURNS [PW.ObjName] = {
nofRows:  INT ← 0;
nodes:   LIST OF Node ← NIL;
Node:   TYPE = REF NodeRec;
NodeRec:  TYPE = RECORD
[name:PW.ROPE, top,bot:LIST OF INTNIL, row:INT←none, left,right:BOOLFALSE];
Side:   TYPE = {top, bot, left, right};
none:   INT ← -1;
pitch:   Size ← [mPitch, 10];
cell:   CD.ObPtr ← CDCells.CreateEmptyCell[];
cellMinX:  INT ← rngByte*rngBit*cellWidth;
iRect:   CD.Rect;
AddNodes: PROC
[side: Side, list: List, index1, index2, index3: INT ← 0, sequential: BOOL ← FALSE] = {
UpdateNode: PROC[node: Node] RETURNS[Node] = {
coord: INT ← (IF side IN [left..right]
THEN               index3*pitch.y
ELSE (IF sequential
THEN ((index1*rngBit  +index2)*cellWidth + index3*pitch.x)
ELSE ((index2*rngByte +index1)*cellWidth + index3*pitch.x) ) );
SELECT side FROM
left => {node.row ← coord; node.left  ← TRUE; nofRows ← nofRows+1};
right => {node.row ← coord; node.right   ← TRUE; nofRows ← nofRows+1};
top => {node.top ← CONS[coord, node.top]};
bot => {node.bot ← CONS[coord, node.bot]};
ENDCASE => ERROR;
RETURN[node] };
IF list = NIL THEN RETURN;
IF list.rest # NIL THEN AddNodes[side, list.rest, index1, index2, index3+1, sequential];
IF list.first=NIL THEN RETURN;
IF nodes = NIL THEN
{nodes ← CONS[UpdateNode[NEW[NodeRec ← [name: list.first]]], nodes]; RETURN};
SELECT Rope.Compare[nodes.first.name, list.first] FROM
equal => {[ ] ← UpdateNode[nodes.first]; RETURN};
greater =>
{nodes ← CONS[UpdateNode[NEW[NodeRec←[name: list.first]]], nodes]; RETURN};
ENDCASE;
FOR names: LIST OF Node ← nodes, names.rest DO
IF names.rest = NIL THEN {
names.rest ← CONS[UpdateNode[NEW[NodeRec←[name: list.first]]], names.rest];
RETURN };
SELECT Rope.Compare[names.rest.first.name, list.first] FROM
equal => {[ ] ← UpdateNode[names.rest.first]; RETURN};
greater => {
names.rest ← CONS[UpdateNode[NEW[NodeRec←[name: list.first]]], names.rest];
RETURN };
ENDCASE;
ENDLOOP};
AddNodes[left, leftCol];
AddNodes[right, rightCol];
FOR index: INT DECREASING IN [0..rngBit) DO
FOR byte: INT DECREASING IN [0..rngByte) DO
top: List ← ExpandList[byte, index, topRow, ioRestRef];
bot: List ← ExpandList[byte, index, botRow, ioRestRef];
AddNodes[top, top, byte, index, 0, topSeq];
AddNodes[bot, bot, byte, index, 0, botSeq];
ENDLOOP;
ENDLOOP;
Check for internal connections
FOR nodePtr: LIST OF Node ← nodes, nodePtr.rest WHILE nodePtr#NIL DO
IF nodePtr.first.row=none AND
(nodePtr.first.top#NIL AND nodePtr.first.top.rest#NIL) OR
(nodePtr.first.bot#NIL AND nodePtr.first.bot.rest#NIL) OR
(nodePtr.first.top#NIL AND nodePtr.first.bot#NIL AND nodePtr.first.top.first#nodePtr.first.bot.first)
THEN {nodePtr.first.row ← nofRows*pitch.y; nofRows ←nofRows+1};
ENDLOOP;
Draw wires
FOR nodePtr: LIST OF Node ← nodes, nodePtr.rest WHILE nodePtr#NIL DO
name: PW.ROPE ← nodePtr.first.name;
minX: INT ← rngBit*rngByte*cellWidth;
maxX: INT ← 0;
FOR nodeTop: LIST OF INT ← nodePtr.first.top, nodeTop.rest WHILE nodeTop#NIL DO
minX ← MIN[ nodeTop.first, minX];
maxX ← MAX[ nodeTop.first, maxX];
ENDLOOP;
FOR nodeBot: LIST OF INT ← nodePtr.first.bot, nodeBot.rest WHILE nodeBot#NIL DO
minX ← MIN[ nodeBot.first, minX];
maxX ← MAX[ nodeBot.first, maxX];
ENDLOOP;
cellMinX ← MIN[ cellMinX, minX];
IF nodePtr.first.row=none
THEN {
yMax: INT ← nofRows*pitch.y;
AddRet [cell, [6, yMax], [minX, -2],   CMos.met];
PutPin [cell, [6, 6],  [minX, yMax-6-2],  CMos.met, name];
PutPin [cell, [6, 6],  [minX,  -2],   CMos.met, name]}
ELSE {
ctct: CD.ObPtr ← CMosContacts.CreatePolyCon[l: 8];
xEnd: INT ← rngBit*rngByte*cellWidth-leftTail;
yMax: INT ← nofRows*pitch.y;
yMid: INT ← nodePtr.first.row;
AddRet [cell, [maxX-minX, 4], [minX, yMid], CMos.pol];
IF nodePtr.first.left THEN {
cellMinX ← -leftTail;
AddRet [cell, [minX+leftTail, 4], [-leftTail, yMid], CMos.pol];
PutPin [cell, [ 4,     4], [-leftTail, yMid], CMos.pol, name]};
IF nodePtr.first.right THEN {
AddRet [cell, [xEnd-maxX,  4], [maxX,  yMid], CMos.pol];
PutPin [cell, [ 4,     4], [xEnd-4,  yMid], CMos.pol, name]};
FOR nodeTop: LIST OF INT ← nodePtr.first.top, nodeTop.rest WHILE nodeTop#NIL DO
xx: INT ← nodeTop.first;
AddRet [cell, [6, yMax-yMid], [xx, yMid-2], CMos.met];
PutPin [cell, [6, 6],    [xx, yMax-6-2], CMos.met, name];
[] ← PWBasics.IncludeApplication[cell, ctct, [xx, 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],   [xx, -2],  CMos.met];
PutPin [cell, [6, 6],    [xx,  -2],  CMos.met, name];
[] ← PWBasics.IncludeApplication[cell, ctct, [xx, yMid-2]];
ENDLOOP };
ENDLOOP;
PWBasics.RepositionCell[design, cell];
iRect ← PWBasics.GetIRect[cell];
iRect.x1 ← iRect.x1 - (leftTail+cellMinX);
iRect.x2 ← rngByte*rngBit*cellWidth + iRect.x1;
PWBasics.SetIRect[cell, iRect];
RETURN[PWBasics.NameFromObj[cell]]};
GenMetalPinRow: PUBLIC PROC [
design:  CD.Design,
signals:  LIST OF REF,
sequential: BOOLFALSE ]
RETURNS [cell: PW.ObjName] = {
obj: CD.ObPtr ← CDCells.CreateEmptyCell[];
iRect: CD.Rect;
FOR ii: INT IN [0..rngByte*rngBit) DO
index:  INT ← IF sequential THEN ii MOD rngBit ELSE ii / rngByte;
byte:  INT ← IF sequential THEN ii / rngBit ELSE ii MOD rngByte;
names: List ← ExpandList[byte, index, signals, ioRestRef];
sigIndex: INT ← -1;
FOR names ← names, names.rest WHILE names#NIL DO
sigIndex ← sigIndex+1;
IF names.first=NIL THEN LOOP;
AddRet [obj, [6, 6], [ii*cellWidth+sigIndex*mPitch, 0], CMos.met];
PutPin [obj, [6, 6], [ii*cellWidth+sigIndex*mPitch, 0], CMos.met, names.first];
ENDLOOP;
ENDLOOP;
PWBasics.RepositionCell[design, obj];
iRect ← PWBasics.GetIRect[obj];
iRect.x1 ← iRect.x1 - leftTail;
iRect.x2 ← rngByte*rngBit*cellWidth + iRect.x1;
PWBasics.SetIRect[obj, iRect];
cell ← PWBasics.NameFromObj[obj] };
SwitchBoxRowTest: PW.UserProc = { RETURN[ SwitchBoxRow[
design:  design,
topRow: LIST["PBus." ],
rightCol:  LIST
["Alpha.0", "Alpha.1", "Alpha.2", "Alpha.3", "Alpha.4", "Alpha.5", "Alpha.6", "Alpha.7"],
leftCol: NIL,
botRow: LIST["PBus.", LIST["Alpha.", NIL, NIL, NIL] ] ] ] };
BusXForm: PW.UserProc = {
signals: LIST OF REFLIST["IPBus.", "PCBus."];
topName: PW.ObjName ← GenMetalPinRow[design, signals, TRUE];
botName: PW.ObjName ← GenMetalPinRow[design, signals];
RETURN[PW.AbutY[botName,topName]]};
PW.Register [BusXForm,     "BusXForm"];
PW.Register [SwitchBoxRowTest,  "SwitchBoxRowTest"];
END.