IFUPWDriverGate.mesa,
Copyright c 1985 by Xerox Corporation. All rights reserved.
RemoveButton CD; CreateButton L Compile Latch; Run Latch
Last Edited by Curry, April 29, 1985 1:55:50 pm PDT
DIRECTORY
Basics,
CD,
CDCells USING [CreateEmptyCell],
CDDirectory,
CMos,
CMosContacts,
IFUPW,
PW,
PWBasics,
Rope;
IFUPWDriverGate: CEDAR PROGRAM
IMPORTS
CDCells, CMosContacts, CMos, IFUPW, PW, PWBasics, Rope
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
rngByte: INT = 4;
rngBit: INT = 8;
IFUTriDriverRow: PUBLIC PROC [
design: CD.Design,
enable: PW.ROPE,
disable: PW.ROPE,
top:  LIST OF REF,
in:   LIST OF REF,
out:  LIST OF REF,
bot:  LIST OF REF,
seq:  BOOLFALSE ]
RETURNS [cell: PW.ObjName] = {
in, top, out and bot share a common format.
IF a top level item is a rope then a byte and bit index are appended to each rope.
IF a top level item is a List of rope then a bit index is appended to each rope.
IF a top level item is a List of List of rope then each rope is used as is.
cells: LIST OF PW.ObjName;
FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO
index: INT ← IF seq THEN ii MOD rngBit ELSE ii / rngByte;
byte: INT ← IF seq THEN ii / rngBit ELSE ii MOD rngByte;
cells ← CONS[ TriDriver[
design: design,
top:  ExpandList[byte, index, top],
in:   ExpandList[byte, index, in],
enable: enable,
disable: disable,
out:  ExpandList[byte, index, out],
bot:  ExpandList[byte, index, bot]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
TriDriver: PROC [
design: CD.Design,
enable: PW.ROPE,
disable: PW.ROPE,
top:  List,
in:   List,
out:  List,
bot:  List ]
RETURNS [PW.ObjName] = {
topTail: INT  = 4;
botTail: INT  = 2;
pitch:  Size  = [mPitch, pBigPitch];
cell:  CD.ObPtr ← CDCells.CreateEmptyCell[];
rangeX: INT  ← nofVWires;
inN:  PW.ROPE ← IF in=NILTHEN NIL ELSE in.first;
outN:  PW.ROPE ← IF out=NILTHEN NIL ELSE out.first;
Metal wires
FOR i: INT IN [0..rangeX) DO
Add: PROC[bindex, tindex, toptail, bottail: INT] = {
loc.y ← bindex*pitch.y - bottail;
size.y ← (tindex-bindex)*pitch.y + toptail + bottail;
IF size.y>0 THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met]};
size: Size  ← [6, 0];
loc: Location ← [i*pitch.x, 0];
tIO: PW.ROPE ← ListIndexItem[top,  i];
bIO: PW.ROPE ← ListIndexItem[bot,  i];
IF tIO#NIL THEN SELECT TRUE FROM
Rope.Equal[tIO, bIO] => {Add[0, 4, 4+topTail, botTail]};
Rope.Equal[tIO, outN] => {Add[1, 4, 4+topTail, 0]};
Rope.Equal[tIO, inN] => {Add[3, 4, 4+topTail, 0]}
ENDCASE     => ERROR; -- top not connected anywhere ABORT;
IF bIO#NIL THEN SELECT TRUE FROM
Rope.Equal[bIO, tIO] => LOOP;
Rope.Equal[bIO, inN] => {Add[0, 3, 0, botTail]};
Rope.Equal[bIO, outN] => {Add[0, 1, 0, botTail]};
ENDCASE     => ERROR; -- bottom not connected anywhere ABORT
ENDLOOP;
Insert Metal Pins
FOR i: INT IN [0..rangeX) DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size  ← [6, 6];
loc: Location ← [i*pitch.x, 4*pitch.y+4+topTail-size.y];
IF tName #NIL THEN PutPin [cell, size, loc,    CMos.met, tName];
IF bName #NIL THEN PutPin [cell, size, [loc.x, -botTail], CMos.met, bName];
ENDLOOP;
Enables and power Wires
AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 64], level: CMos.pol];
AddRet[cell:cell, size:[cellWidth,16], loc:[-leftTail, 48], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth,16], loc:[-leftTail, 12], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 0],  level: CMos.pol];
Insert Enable and power Pins
PutPin [cell,  [4, 4],  [-leftTail,    64], CMos.pol,  enable];
PutPin [cell,  [4, 4],  [cellWidth-leftTail-4, 64], CMos.pol,  enable];
PutPin [cell,  [4,16],  [-leftTail,    48], CMos.met2, "VDD"];
PutPin [cell,  [4,16],  [cellWidth-leftTail-4, 48], CMos.met2, "VDD"];
PutPin [cell,  [4,16],  [-leftTail,    12], CMos.met2, "GND"];
PutPin [cell,  [4,16],  [cellWidth-leftTail-4, 12], CMos.met2, "GND"];
PutPin [cell,  [4, 4],  [-leftTail,     0], CMos.pol,  disable];
PutPin [cell,  [4, 4],  [cellWidth-leftTail-4,  0], CMos.pol,  disable];
Poly connections
FOR i: INT IN [0..rangeX) DO
AddPCnt: PROC = {[] ← PWBasics.IncludeApplication
[cell, CMosContacts.CreatePolyCon[l: 8], [loc.x, loc.y-2]]};
loc: Location ← [i * pitch.x, 0];
size: Size  ← [(rangeX-i) * pitch.x, 4];
ioT: PW.ROPE ← ListIndexItem[top, i];
ioB: PW.ROPE ← ListIndexItem[bot, i];
loc.y ← 3*pitch.y;
IF inN#NIL THEN IF Rope.Equal[inN, ioT] OR Rope.Equal[inN, ioB]
THEN {AddPCnt[]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]};
loc.y ← 1*pitch.y;
IF outN#NIL THEN IF Rope.Equal[outN, ioT] OR Rope.Equal[outN, ioB]
THEN {AddPCnt[]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]};
ENDLOOP;
Cell
IF NOT inN=NIL THEN [] ← PWBasics.IncludeApplication[
cell:  cell,
subcell: PWBasics.ObjFromName[design, "GVTriStateDriver"],
location: [rangeX*pitch.x, 0]];
PWBasics.RepositionCell[design, cell];
RETURN[PWBasics.NameFromObj[cell]]};
IFUGateRow: PUBLIC PROC [
design: CD.Design,
top:  LIST OF REF,
type:  LIST OF REF,
in1:  LIST OF REF,
in2:  LIST OF REF,
out:  LIST OF REF,
bot:  LIST OF REF,
seq:  BOOLFALSE ]
RETURNS [cell: PW.ObjName] = {
cells: LIST OF PW.ObjName;
FOR ii: INT DECREASING IN [0..rngByte*rngBit) DO
index: INT ← IF seq THEN ii MOD rngBit ELSE ii / rngByte;
byte: INT ← IF seq THEN ii / rngBit ELSE ii MOD rngByte;
cells ← CONS[ Gate[
design: design,
type:  ExpandList[byte, index, type],
top:  ExpandList[byte, index, top],
in1:  ExpandList[byte, index, in1],
in2:  ExpandList[byte, index, in2],
out:  ExpandList[byte, index, out],
bot:  ExpandList[byte, index, bot]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
Gate: PROC [
design: CD.Design,
top:  List,
type:  List,
in1:  List,
in2:  List,
out:  List,
bot:  List ]
RETURNS [PW.ObjName] = {
topTail:  INT  = 4;
botTail:  INT  = 2;
pitch:   Size  = [mPitch, pBigPitch];
cell:   CD.ObPtr ← CDCells.CreateEmptyCell[];
rangeX:  INT  ← MAX[ListLength[top], ListLength[bot]];
in1N:   PW.ROPE ← IF in1=NIL THEN NIL ELSE in1.first;
in2N:   PW.ROPE ← IF in2=NIL THEN NIL ELSE in2.first;
outN:   PW.ROPE ← IF out=NIL THEN NIL ELSE out.first;
Metal wires
FOR i: INT IN [0..rangeX) DO
Add: PROC[bindex, tindex, toptail, bottail: INT] = {
loc.y ← bindex*pitch.y - bottail;
size.y ← (tindex-bindex)*pitch.y + toptail + bottail;
IF size.y>0 THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met]};
size: Size  ← [6, 0];
loc: Location ← [i*pitch.x, 0];
tIO: PW.ROPE ← ListIndexItem[top,  i];
bIO: PW.ROPE ← ListIndexItem[bot,  i];
IF tIO#NIL THEN SELECT TRUE FROM
Rope.Equal[tIO, bIO] => {Add[0, 2, 4+topTail, botTail]};
Rope.Equal[in2N, tIO] => {Add[0, 2, 4+topTail, 0]};
Rope.Equal[outN, tIO] => {Add[1, 2, 4+topTail, 0]};
Rope.Equal[in1N, tIO] => {Add[2, 2, 4+topTail, 0]};
ENDCASE     => ERROR; -- top not connected anywhere ABORT;
IF bIO#NIL THEN SELECT TRUE FROM
Rope.Equal[bIO, tIO] => LOOP;
Rope.Equal[in1N, bIO] => {Add[0, 2, 0, botTail]};
Rope.Equal[outN, bIO] => {Add[0, 1, 0, botTail]};
Rope.Equal[in2N, bIO] => {Add[0, 0, 0, botTail]};
ENDCASE     => ERROR; -- bottom not connected anywhere ABORT
ENDLOOP;
Insert Metal Pins
FOR i: INT IN [0..rangeX) DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size  ← [6, 6];
loc: Location ← [i*pitch.x, 2*pitch.y+4+topTail-size.y];
IF tName #NIL THEN PutPin [cell, size, loc,    CMos.met, tName];
IF bName #NIL THEN PutPin [cell, size, [loc.x, -botTail], CMos.met, bName];
ENDLOOP;
Enables and power Wires
AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, 22], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, -4], level: CMos.met2];
Insert Enable and power Pins
PutPin [cell,  [4,18],  [-leftTail,    22], CMos.met2, "VDD"];
PutPin [cell,  [4,18],  [cellWidth-leftTail-4, 22], CMos.met2, "VDD"];
PutPin [cell,  [4,18],  [-leftTail,    -4], CMos.met2, "GND"];
PutPin [cell,  [4,18],  [cellWidth-leftTail-4, -4], CMos.met2, "GND"];
Poly connections
FOR i: INT IN [0..rangeX) DO
AddPCnt: PROC = {[] ← PWBasics.IncludeApplication
[cell, CMosContacts.CreatePolyCon[l: 8], [loc.x, loc.y-2]]};
loc: Location ← [  i  * pitch.x, 0];
size: Size  ← [(rangeX-i) * pitch.x, 4];
ioT: PW.ROPE ← ListIndexItem[top, i];
ioB: PW.ROPE ← ListIndexItem[bot, i];
loc.y ← 2*pitch.y;
IF in1N#NIL THEN IF Rope.Equal[in1N, ioT] OR Rope.Equal[in1N, ioB]
THEN {AddPCnt[]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]};
loc.y ← 1*pitch.y;
IF outN#NIL THEN IF Rope.Equal[outN, ioT] OR Rope.Equal[outN, ioB]
THEN {AddPCnt[]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]};
loc.y ← 0*pitch.y;
IF in2N#NIL THEN IF Rope.Equal[in2N, ioT] OR Rope.Equal[in2N, ioB]
THEN {AddPCnt[]; AddRet[cell:cell, size:size, loc:loc, level:CMos.pol]};
ENDLOOP;
Cell
IF type#NIL THEN {
inv: BOOL ← Rope.Find[s1: type.first, s2: "INV", case: FALSE]#-1;
nor: BOOL ← Rope.Find[s1: type.first, s2: "NOR", case: FALSE]#-1;
nand: BOOL ← Rope.Find[s1: type.first, s2: "NAND", case: FALSE]#-1;
[] ← PWBasics.IncludeApplication[
cell:  cell,
subcell: PWBasics.ObjFromName[design, (SELECT TRUE FROM
nor => "BasicNOR", nand => "BasicNAND", ENDCASE => "BasicINV")],
location: [rangeX*pitch.x, -4]] };
PWBasics.RepositionCell[design, cell];
RETURN[PWBasics.NameFromObj[cell]]};
TDrive: PW.UserProc = { RETURN[ TriDriver[
design:  design,
enable: "PhB",
disable: "PhB'",
top:  LIST["XB", "Alpa", "Beta", "Pass",  "In"],
in:   LIST["In"],
out:  LIST["XB"],
bot:  LIST["XB", "Alpa", "Beta", "Pass"]] ]};
GateNor: PW.UserProc = { RETURN[ Gate[
design: design,
top:  LIST["XBus.00", "Match.0",  "Comp.0",  "Match.1"],
type:  LIST["NOR"],
in1:  LIST["Match.0"],
in2:  LIST["Match.1"],
out:  LIST["Comp.0"],
bot:  LIST["XBus.00", "Match.0",  "Comp.0",  "Match.1"] ] ]};
GateNand: PW.UserProc = { RETURN[ Gate[
design: design,
top:  LIST["XBus.00", "Match.0",  "Comp.0",  "Match.1"],
type:  LIST["NAND"],
in1:  LIST["Match.0"],
in2:  LIST["Match.1"],
out:  LIST["Comp.0"],
bot:  LIST["XBus.00", "Match.0",  "Comp.0",  "Match.1"] ] ]};
GateInv: PW.UserProc = { RETURN[ Gate[
design: design,
top:  LIST["XBus.00", "Match.0",  "nMatch.0"],
type:  LIST["INV"],
in1:  LIST["Match.0"],
in2:  NIL,
out:  LIST["nMatch.0"],
bot:  LIST["XBus.00", "Match.0",  "nMatch.0"] ] ]};
PW.Register[GateNor,    "GateNor"];
PW.Register[GateNand,    "GateNand"];
PW.Register[GateInv,    "GateInv"];
PW.Register[TDrive,     "TDrive"];
END.