IFUPWLatch:
CEDAR
PROGRAM
IMPORTS
CD, CDCells, CDRects, CMosContacts, CMosTransistors, CMos, IO, IFUPW, PW, PWBasics, Rope
EXPORTS IFUPW =
BEGIN OPEN IFUPW;
IFULatchRow:
PUBLIC
PROC [
design: CD.Design,
enable: PW.ROPE,
top: LIST OF REF,
in: LIST OF REF,
out: LIST OF REF,
bot: LIST OF REF,
seq:
BOOL ←
FALSE ]
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[ Latch[
design: design,
enable: enable,
top: AddGV[ExpandList[byte, index, top]],
in: ExpandList[byte, index, in],
out: ExpandList[byte, index, out],
bot: AddGV[ExpandList[byte, index, bot]]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
Latch:
PROC [
design: CD.Design,
enable: PW.ROPE,
disable: PW.ROPE ← "VBB",
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=NIL THEN NIL ELSE in.first;
outN:
PW.
ROPE ←
IF out=
NIL
THEN
NIL
ELSE out.first;
Metal wires
FOR i:
INT
IN [0..nofVWires)
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[outN, tIO] => {Add[2, 4, 4+topTail, 0]};
Rope.Equal[inN, tIO] => {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[inN, bIO] => {Add[0, 3, 0, botTail]};
Rope.Equal[outN, bIO] => {Add[0, 2, 0, botTail]};
ENDCASE => ERROR; -- bottom not connected anywhere ABORT
ENDLOOP;
Insert Metal Pins
FOR i:
INT
IN [0..nofVWires)
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, 68], level: CMos.pol];
AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 48], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 0], 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, 68], CMos.pol, disable];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, 68], CMos.pol, disable];
PutPin [cell, [4,20], [-leftTail, 48], CMos.met2, "GND"];
PutPin [cell, [4,20], [cellWidth-leftTail-4, 48], CMos.met2, "GND"];
PutPin [cell, [4,20], [-leftTail, 2], CMos.met2, "VDD"];
PutPin [cell, [4,20], [cellWidth-leftTail-4, 2], CMos.met2, "VDD"];
PutPin [cell, [4, 4], [-leftTail, 0], CMos.pol, enable];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, 0], CMos.pol, enable];
Poly connections
FOR i:
INT
IN [0..nofVWires)
DO
loc: Location ← [i * pitch.x, 0];
ioT: PW.ROPE ← ListIndexItem[top, i];
ioB: PW.ROPE ← ListIndexItem[bot, i];
loc.y ← 2*pitch.y;
IF inN#
NIL
THEN
IF Rope.Equal[inN, ioT]
OR Rope.Equal[inN, ioB]
THEN {
[] ← PWBasics.IncludeApplication
[cell, CMosContacts.CreatePolyCon[l: 8], [loc.x, loc.y-2]];
AddRet[cell:cell, size:[(nofVWires-i) * pitch.x, 4], 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 {
[] ← PWBasics.IncludeApplication
[cell, CMosContacts.CreateMmCon[l: 10], [loc.x, loc.y-4]];
AddRet[cell:cell, size:[(nofVWires-i) * pitch.x, 10], loc:loc, level:CMos.met2]};
ENDLOOP;
Cell
IF inN#NIL THEN {
loc: Location ← [(nofVWires-2)*pitch.x, 0];
[] ← PWBasics.IncludeApplication[
cell: cell,
subcell: PWBasics.ObjFromName[design, "GVLatch"],
location: loc];
PWBasics.RepositionCell[design, cell];
RETURN[PWBasics.NameFromObj[cell]]};
IFUMuxRow:
PUBLIC
PROC [
design: CD.Design,
top: LIST OF REF,
ctl: List,
in: LIST OF REF,
out: LIST OF REF,
bot: LIST OF REF,
seq:
BOOL ←
FALSE ]
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[ Mux[
design: design,
ctl: ctl,
in: ExpandList[byte, index, in],
top: ExpandList[byte, index, top],
out: ExpandList[byte, index, out],
bot: ExpandList[byte, index, bot]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
IFUMuxBytesRow:
PUBLIC
PROC [ -- Hack to go around compiler limitation
design: CD.Design,
top: LIST OF REF,
ctl: List,
in: LIST OF REF, -- Nesting order changed to Byte, Wd, Bit
out: LIST OF REF,
bot: LIST OF REF,
seq:
BOOL ←
FALSE ]
RETURNS [cell: PW.ObjName] = {
cells: LIST OF PW.ObjName;
byteIns: ARRAY [0..rngByte) OF LIST OF REF;
byteInLengths: ARRAY [0..rngByte) OF INT ← ALL[0];
FOR byte:
INT
IN [0..rngByte)
DO
list: LIST OF REF;
FOR bb: INT
IN [0..byte)
DO
FOR list ← byteIns[bb], list.rest
WHILE list#
NIL
DO
byteIns[byte] ← CONS[NIL, byteIns[byte]];
byteInLengths[byte] ← byteInLengths[byte] + 1;
ENDLOOP;
ENDLOOP;
FOR list ←
NARROW[LISTIndexItem[in, byte]], list.rest
WHILE list#
NIL
DO
byteIns[byte] ← CONS[NIL, byteIns[byte]];
byteInLengths[byte] ← byteInLengths[byte] + 1;
ENDLOOP;
ENDLOOP;
FOR byte:
INT
DECREASING IN [0..rngByte)
DO
THROUGH [byteInLengths[byte]..byteInLengths[rngByte-1])
DO
byteIns[byte] ← CONS[NIL, byteIns[byte]];
ENDLOOP;
ENDLOOP;
FOR byte:
INT
IN [0..rngByte)
DO
list: LIST OF REF ← byteIns[byte];
byteIns[byte] ← NIL;
FOR list ← list, list.rest
WHILE list#
NIL
DO
byteIns[byte] ← CONS[list.first, byteIns[byte]];
ENDLOOP;
ENDLOOP;
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[ Mux[
design: design,
ctl: ctl,
in: ExpandList[index, 0, byteIns[byte]],
top: ExpandList[byte, index, top],
out: ExpandList[byte, index, out],
bot: ExpandList[byte, index, bot]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
Mux:
PROC [
design: CD.Design,
top: List,
ctl: List,
in: List,
out: List,
bot: List]
RETURNS [PW.ObjName] = {
pitch: Size = [mPitch, pBigPitch];
topTail: INT = 4;
botTail: INT = 2;
muxEvenDn: BOOL = TRUE;
cell: CD.ObPtr ← CDCells.CreateEmptyCell[];
range: Size ← [MAX[ListLength[top],ListLength[bot]], ListLength[ctl]];
outN: PW.ROPE ← IF out=NIL THEN NIL ELSE out.first;
iRect: CD.Rect;
outIndex: INT ← ListItemIndexMin[top, outN];
outIndexBot: INT ← ListItemIndexMin[bot, outN];
IF outIndex # ListItemIndexMax[top, outN]
OR
outIndexBot # ListItemIndexMax[bot, outN] OR
(outIndex#-1
AND outIndexBot#-1
AND outIndex#outIndexBot)
THEN ERROR Error[IO.PutFR["Multiple column output %g- ABORT", IO.rope[outN]]];
IF outIndex = -1 THEN outIndex ← outIndexBot;
Metal wires and their pins
FOR i:
INT
IN [0..range.x)
DO
size: Size ← [6, 0];
loc: Location ← [i*pitch.x, 0];
tIO: PW.ROPE ← ListIndexItem[top, i];
bIO: PW.ROPE ← ListIndexItem[bot, i];
tY: INT ← IF tIO=outN THEN ListNonNILIndexMin[in] ELSE ListItemIndexMin[in,tIO];
bY: INT ← IF bIO=outN THEN ListNonNILIndexMax[in] ELSE ListItemIndexMax[in,bIO];
tY ← tY + ((tY + (IF (tIO=outN)=muxEvenDn THEN 1 ELSE 2)) MOD 2);
bY ← bY + ((bY + (IF (bIO=outN)=muxEvenDn THEN 1 ELSE 2)) MOD 2);
IF tY=-1 AND bY=-1 THEN tY𡤋Y𡤀
IF ~Rope.Equal[tIO, bIO]
AND tY<=bY
AND tIO#
NIL
AND bIO#
NIL
THEN
ERROR Error[
IO.PutFR
["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]];
IF tIO#
NIL
THEN AddRet[cell:cell, level: CMos.met,
size: [6, (range.y-tY) * pitch.y + 8 + topTail ],
loc: [i*pitch.x, tY * pitch.y - 10 ]];
IF bIO#
NIL
THEN AddRet[cell:cell, level: CMos.met,
size: [6, bY * pitch.y + botTail ],
loc: [i*pitch.x, 0 * pitch.y - 10 - botTail ]];
ENDLOOP;
FOR i:
INT
IN [0..range.x)
DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size ← [6, 6];
loc: Location ← [i*pitch.x, range.y*pitch.y-2+topTail-size.y];
IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName];
IF bName #NIL THEN PutPin [cell, size, [loc.x, - 10 - botTail], CMos.met, bName];
ENDLOOP;
Poly wires and their pins
FOR i:
INT
IN [0..range.y)
DO
cName: PW.ROPE ← ListIndexItem[ctl, i];
size: Size ← [cellWidth, 4];
loc: Location ← [-leftTail, i*pitch.y ];
AddRet[cell:cell, size:size, loc:loc, level:CMos.pol];
PutPin [cell, [4, 4], loc, CMos.pol, cName];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName]
ENDLOOP;
Mux connections
FOR ctlIndex:
INT
IN [0..range.y)
DO
AddMux:
PROC [index: Location] = {
OPEN PWB: PWBasics;
xstr: CD.ObPtr ← CMosTransistors.CreateTransistor[w: 8, l: 4, difLev: CMos.ndif];
ctct: CD.ObPtr ← CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif];
dif: CD.ObPtr ← CDRects.CreateRect[[(ABS[outIndex-index.x])*pitch.x+8, 8], CMos.ndif];
half: INT ← IF ((index.y MOD 2)=0)=muxEvenDn THEN pitch.y/2 ELSE -pitch.y/2;
yloc: INT ← index.y*pitch.y-2;
[] ← PWB.IncludeApplication[cell, dif, [MIN[outIndex, index.x]*pitch.x, yloc+half]];
[] ← PWB.IncludeApplication[cell, ctct, [ outIndex *pitch.x, yloc+half]];
[] ← PWB.IncludeApplication[cell, ctct, [ index.x *pitch.x, yloc-half]];
[] ← PWB.IncludeApplication[cell, xstr, [ index.x *pitch.x-4, yloc-2]]};
ioIndex: INT ← -1;
ioItem: PW.ROPE ← ListIndexItem[in, ctlIndex];
IF ioItem = NIL THEN LOOP;
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMax[top, ioItem];
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMax[bot, ioItem];
IF ioIndex < 0 THEN LOOP;
AddMux[index: [ioIndex, ctlIndex]];
ENDLOOP;
PWBasics.RepositionCell[design, cell];
iRect ← CD.InterestRect[cell];
IF outIndex=-1 AND bot=NIL OR ListAllNil[bot] THEN iRect.y1 ← iRect.y1-10-botTail;
iRect.y2 ← iRect.y1 + range.y*pitch.y+botTail+8+topTail;
CDCells.SetInterestRect[cell, iRect];
RETURN[PWBasics.NameFromObj[cell]]};
IFUDecoderRow:
PUBLIC
PROC [
design: CD.Design,
top: LIST OF REF,
ctl: List, -- nof names must be 2*nof significant bits - 1st is MSB TRUE
val: REF ValArray,
out: LIST OF REF,
bot: LIST OF REF,
seq:
BOOL ←
FALSE ]
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[
Decoder[
design: design,
ctl: ctl,
val: val[byte][index],
top: AddGV[ExpandList[byte, index, top]],
out: ExpandList[byte, index, out],
bot: AddGV[ExpandList[byte, index, bot]] ], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
Decoder:
PROC [
design: CD.Design,
top: List,
ctl: List,
val: INT,
out: List,
bot: List]
RETURNS [PW.ObjName] = {
pitch: Size = [mPitch, pBigPitch];
topTail: INT = 4;
botTail: INT = 2;
cell: CD.ObPtr ← CDCells.CreateEmptyCell[];
rangeY: INT ← ListLength[ctl]+1;
outN: PW.ROPE ← IF out=NIL THEN NIL ELSE out.first;
iRect: CD.Rect;
Metal wires and their pins
FOR i:
INT
IN [0..nofVWires)
DO
size: Size ← [6, 0];
loc: Location ← [i*pitch.x, 0];
tIO: PW.ROPE ← ListIndexItem[top, i];
bIO: PW.ROPE ← ListIndexItem[bot, i];
tY: INT ← ListItemIndexMin[ctl,tIO] +1;
bY: INT ← ListItemIndexMax[ctl,bIO] +1;
IF tIO=outN THEN tY𡤀 ELSE IF tY=0 THEN tY←-1;
IF bY=0 AND bIO#outN THEN bY←-1;
IF tY=-1 AND bY=-1 THEN tY𡤋Y𡤀
IF ~Rope.Equal[tIO, bIO]
AND tY<=bY
AND tIO#
NIL
AND bIO#
NIL
THEN
ERROR Error[
IO.PutFR
["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]];
IF tIO#
NIL
THEN AddRet[cell:cell, level: CMos.met,
size: [6, (rangeY-tY) * pitch.y + 8 + topTail ],
loc: [i*pitch.x, tY * pitch.y - 10 ]];
IF bIO#
NIL
THEN AddRet[cell:cell, level: CMos.met,
size: [6, bY * pitch.y + botTail ],
loc: [i*pitch.x, 0 * pitch.y - 10 - botTail ]];
ENDLOOP;
FOR i:
INT
IN [0..nofVWires)
DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size ← [6, 6];
loc: Location ← [i*pitch.x, rangeY*pitch.y-2+topTail-size.y];
IF tName #NIL THEN PutPin [cell, size, loc, CMos.met, tName];
IF bName #NIL THEN PutPin [cell, size, [loc.x, - 10 - botTail], CMos.met, bName];
ENDLOOP;
Out poly wire
FOR xIndex:
INT
IN [0..nofVWires-2)
DO
loc: Location ← [xIndex*pitch.x, 0 ];
IF Rope.Equal[outN, ListIndexItem[top, xIndex]]
OR
Rope.Equal[outN, ListIndexItem[bot, xIndex]]
THEN {
AddRet[cell:cell, size:[(nofVWires-2-xIndex)*pitch.x, 4], loc:loc, level:CMos.pol];
[] ← PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l:8], loc] };
ENDLOOP;
Ctl Poly wires and their pins
FOR cIndex:
INT
IN (0..rangeY)
DO
cName: PW.ROPE ← ListIndexItem[ctl, cIndex-1];
size: Size ← [cellWidth, 4];
loc: Location ← [-leftTail, cIndex*rangeY ];
AddRet[cell:cell, size:size, loc:loc, level:CMos.pol];
PutPin [cell, [4, 4], loc, CMos.pol, cName];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName];
loc.y ← loc.y-2;
FOR xIndex:
INT
IN [0..nofVWires-2)
DO
loc.x ← xIndex*pitch.x;
IF Rope.Equal[cName, ListIndexItem[top, xIndex]]
OR
Rope.Equal[cName, ListIndexItem[bot, xIndex]]
THEN
[] ← PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l:8], loc];
ENDLOOP;
ENDLOOP;
AddRet[cell:cell, level: CMos.met, size:[8, (rangeY-2)*pitch.y], loc: [154, 6]];
AddRet[cell:cell, level: CMos.met, size:[26, (rangeY-1)*pitch.y], loc: [170, 6]];
AddRet[cell:cell, level: CMos.nwel, size:[26, (rangeY+0)*pitch.y+6], loc: [142, -4]];
BEGIN
-- Mux connections
Put: PROC[obj: CD.ObPtr, loc: Location] = {[] ← PWBasics.IncludeApplication[cell, obj, loc]};
currIsXstr, lastIsXstr: BOOL ← FALSE;
nXstr: CD.ObPtr ← CMosTransistors.CreateTransistor[w: 32, l: 4, difLev: CMos.ndif];
pXstr: CD.ObPtr ← CMosTransistors.CreateTransistor[w: 24, l: 4, difLev: CMos.pdif];
nCtct: CD.ObPtr ← CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif];
pCtct: CD.ObPtr ← CMosContacts.CreateDifCon[l: 8, difLev: CMos.pdif];
wCtct: CD.ObPtr ← CMosContacts.CreateDifShortCon[difLev: CMos.ndif];
nDif: CD.ObPtr ← CDRects.CreateRect[[32, 4], CMos.ndif];
pDif: CD.ObPtr ← CDRects.CreateRect[[24, 4], CMos.pdif];
met: CD.ObPtr ← CDRects.CreateRect[[8, 16], CMos.met];
FOR ctlIndex:
INT
IN (0..rangeY)
DO
yloc: INT ← ctlIndex*pitch.y-10;
xloc: INT ← (nofVWires-2)*pitch.x;
currIsXstr ← PW.XthBitOfN[(rangeY+1-ctlIndex)/2, val];
IF (ctlIndex MOD 2) =1 THEN currIsXstr ← NOT currIsXstr;
IF
NOT currIsXstr
THEN {
Put[met, [xloc+28, yloc ]];
IF lastIsXstr
THEN
Put[nCtct, [xloc+28, yloc ]] }
ELSE {
Put[nDif, [xloc+4, yloc+2 ]];
Put[nDif, [xloc+4, yloc+2+16]];
Put[nXstr, [xloc+4, yloc+4 ]];
IF
NOT lastIsXstr
THEN
Put[nCtct, [xloc+28, yloc ]];
Put[pDif, [xloc+62, yloc+2 ]];
Put[pDif, [xloc+62, yloc+2+16]];
Put[pXstr, [xloc+62, yloc+4 ]];
Put[wCtct, [xloc+92, yloc +16]];
IF (ctlIndex MOD 2) =1
THEN {
Put[pCtct, [xloc+62, yloc +16]];
Put[pCtct, [xloc+78, yloc ]] };
};
lastIsXstr ← currIsXstr;
ENDLOOP;
END;
[] ← PWBasics.IncludeApplication[
cell: cell,
subcell: PWBasics.ObjFromName[design, "DecoderTop"],
location: [0,0]];
[] ← PWBasics.IncludeApplication[
cell: cell,
subcell: PWBasics.ObjFromName[design, "DecoderBot"],
location: [0,(rangeY-1)*pitch.y-2]];
PWBasics.RepositionCell[design, cell];
iRect ← CD.InterestRect[cell];
IF outIndex=-1 AND bot=NIL OR ListAllNil[bot] THEN iRect.y1 ← iRect.y1-10-botTail;
iRect.y2 ← iRect.y1 + range.y*pitch.y+botTail+8+topTail;
CDCells.SetInterestRect[cell, iRect];
RETURN[PWBasics.NameFromObj[cell]]};
IFUMuxLatchRow:
PUBLIC
PROC [
design: CD.Design,
enable: PW.ROPE,
top: LIST OF REF,
ctl: List,
in: LIST OF REF,
out: LIST OF REF,
bot: LIST OF REF,
seq:
BOOL ←
FALSE ]
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[ MuxLatch[
design: design,
ctl: ctl,
in: ExpandList[byte, index, in],
enable: enable,
top: ExpandList[byte, index, top],
out: ExpandList[byte, index, out],
bot: ExpandList[byte, index, bot]], cells];
ENDLOOP;
RETURN[PW.AbutListX[cells]]};
ioRestRef: List ← LIST["VDD", "GND"];
MuxLatch:
PROC [
design: CD.Design,
enable: PW.ROPE,
top: List,
ctl: List,
in: List,
out: List,
bot: List]
RETURNS [PW.ObjName] = {
AddMux:
PROC [index: Location] = {
patch: CD.ObPtr ← CDRects.CreateRect[[8,8], CMos.ndif];
dif: CD.ObPtr ← CDRects.CreateRect[[(range.x+ioRestLength-index.x)*pitch.x,8], CMos.ndif];
xstr: CD.ObPtr ← CMosTransistors.CreateTransistor[w: 8, l: 4, difLev: CMos.ndif];
ctct: CD.ObPtr ← CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif];
half: INT ← IF (index.y MOD 2)=0 THEN pitch.y/2 ELSE -pitch.y/2;
loc: Location ← [index.x*pitch.x, (mIBias+index.y)*pitch.y-2];
IF range.y=1
-- noMux Latch
THEN [] ← PWBasics.IncludeApplication[cell, patch, [loc.x, loc.y]]
ELSE [] ← PWBasics.IncludeApplication[cell, xstr, [loc.x-4, loc.y-2]];
[] ← PWBasics.IncludeApplication[cell, dif, [loc.x, loc.y+half]];
[] ← PWBasics.IncludeApplication[cell, ctct, [loc.x, loc.y-half]] };
pitch: Size = [mPitch, pBigPitch];
mIBias: INT = 5;
oIBias: INT = 2;
topTail: INT = 4;
botTail: INT = 2; -- Need tails to prevend pins from appearing on two sides
cell: CD.ObPtr ← CDCells.CreateEmptyCell[];
range: Size ← [MAX[ListLength[top],ListLength[bot]], ListLength[ctl]+mIBias];
ioRest: List ← ioRestRef;
ioRestLength: CARDINAL ← ListLength[ioRest];
noMux: BOOL ← range.y=1;
noIORest: BOOL ← FALSE;
blank: BOOL ← in=NIL OR ListAllNil[in];
FOR ioRest ← ioRest, ioRest.rest
WHILE ioRest#
NIL
DO
-- are VDD or GND used
IF ListItemIndexMax[in, ioRest.first]#-1 THEN EXIT ENDLOOP;
IF ioRest#
NIL
THEN ioRest ← ioRestRef -- at least one is used so do regular case
ELSE noIORest ← TRUE;
IF noIORest THEN {ioRest ← NIL; ioRestLength𡤀}; -- noMux/noIORest latch
Primary Metal wires
FOR i:
INT
IN [0..range.x)
DO
size: Size ← [6, 0];
loc: Location ← [i*pitch.x, 0];
tIO: PW.ROPE ← ListIndexItem[top, i];
bIO: PW.ROPE ← ListIndexItem[bot, i];
bY: INT ← ListItemIndexMax[in, bIO];
tY: INT ← ListItemIndexMin[in, tIO];
bY ←
IF bY#-1
THEN bY+mIBias ELSE IF ListItemIndexMax[out, bIO]#-1 THEN oIBias ELSE -1;
tY ←
IF ListItemIndexMin[out, tIO]#-1
THEN oIBias ELSE IF tY#-1 THEN tY+mIBias ELSE range.y+mIBias;
IF tY >=mIBias THEN tY ← (tY -((tY +1-mIBias) MOD 2));
IF bY >=mIBias THEN bY ← (bY -((bY +1-mIBias) MOD 2));
IF Rope.Equal[tIO, bIO]
THEN tY𡤋Y𡤀
ELSE
IF tY<=bY
THEN
ERROR Error[
IO.PutFR
["2 signals (%g, %g) in same channel - ABORT", IO.rope[tIO], IO.rope[bIO]]];
size.y ← (range.y-tY) *pitch.y - pitch.y/2 + topTail;
loc.y ← tY *pitch.y+6;
IF tIO#NIL THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met];
size.y ← bY *pitch.y+6 + botTail;
loc.y ← - botTail;
IF bIO#NIL THEN AddRet[cell:cell, size:size, loc:loc, level: CMos.met];
ENDLOOP;
IORest metal wires
IF
NOT(noIORest
OR blank)
THEN
FOR ix:
INT
IN [0..ioRestLength)
DO
bY: INT ← ListItemIndexMax[in, ListIndexItem[ioRest, ix]];
IF bY=-1 THEN LOOP;
AddRet[ cell: cell, level: CMos.met,
loc: [(range.x+ix) * pitch.x, mIBias * pitch.y - 2],
size: [8, (bY+(bY MOD 2)) * pitch.y - pitch.y/2 + topTail]];
ENDLOOP;
Collection node metal wire
IF
NOT(noMux
OR blank)
THEN {
bY: INT ← range.y-mIBias-1;
AddRet[ cell: cell, level: CMos.met,
loc: [(range.x+ioRestLength) * pitch.x, (mIBias+1) * pitch.y-2],
size: [8, (bY-(bY MOD 2)) * pitch.y]]};
Insert Metal Pins
FOR i:
INT
IN [0..range.x)
DO
tName: PW.ROPE ← ListIndexItem[top, i];
bName: PW.ROPE ← ListIndexItem[bot, i];
size: Size ← [6, 6];
loc: Location ← [i*pitch.x, range.y*pitch.y-2+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;
Enable and power Wires
AddRet[cell:cell, size:[cellWidth, 8], loc:[-leftTail, 70], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, 42], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth,20], loc:[-leftTail, 0], level: CMos.met2];
AddRet[cell:cell, size:[cellWidth, 4], loc:[-leftTail, 0], level: CMos.pol];
Insert Enable and power Pins
PutPin [cell, [4, 8], [-leftTail, 70], CMos.met2, "VBB"];
PutPin [cell, [4, 8], [cellWidth-leftTail-4, 70], CMos.met2, "VBB"];
PutPin [cell, [4,18], [-leftTail, 42], CMos.met2, "VDD"];
PutPin [cell, [4,18], [cellWidth-leftTail-4, 42], CMos.met2, "VDD"];
PutPin [cell, [4,20], [-leftTail, 0], CMos.met2, "GND"];
PutPin [cell, [4,20], [cellWidth-leftTail-4, 0], CMos.met2, "GND"];
PutPin [cell, [4, 4], [-leftTail, 0], CMos.pol, enable];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, 0], CMos.pol, enable];
Poly wires and latch input node contacts
FOR i:
INT
IN [0..range.y-mIBias)
DO
cName: PW.ROPE ← ListIndexItem[ctl, i];
ctct: CD.ObPtr ← CMosContacts.CreateDifCon[l: 8, difLev: CMos.ndif];
size: Size ← [cellWidth, 4];
loc: Location ← [-leftTail, (mIBias+i)*pitch.y ];
IF
NOT blank
AND (i
MOD 2)=0
THEN [] ← PWBasics.IncludeApplication
[cell, ctct, [(range.x+ioRestLength)*pitch.x, loc.y+6]];
IF noMux THEN EXIT; -- noMux latch
AddRet[cell:cell, size:size, loc:loc, level:CMos.pol];
Insert Pins
IF cName #
NIL
THEN {
PutPin [cell, [4, 4], loc, CMos.pol, cName];
PutPin [cell, [4, 4], [cellWidth-leftTail-4, loc.y], CMos.pol, cName]};
ENDLOOP;
Mux connections
FOR ctlIndex:
INT
IN [0..range.y-mIBias)
DO
ioIndex: INT ← -1;
ioItem: PW.ROPE ← ListIndexItem[in, ctlIndex];
IF ioItem = NIL THEN LOOP;
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMax[top, ioItem];
IF ioIndex < 0 THEN ioIndex ← ListItemIndexMax[bot, ioItem];
IF ioIndex < 0
THEN {
ioIndex ← ListItemIndexMax[ioRest, ioItem];
IF ioIndex < 0 THEN LOOP;
ioIndex ← ioIndex+range.x};
AddMux[index: [ioIndex, ctlIndex]];
ENDLOOP;
Ouput connections
IF
NOT blank
THEN
FOR i:
INT
IN [0..range.x)
DO
IF ListItemIndexMax[out, ListIndexItem[top, i]]#-1
OR ListItemIndexMax[out, ListIndexItem[bot, i]]#-1
THEN {
loc: Location ← [i*pitch.x, oIBias*pitch.y+4];
size: Size ← [(range.x-i+(IF noIORest THEN 0 ELSE 1))*pitch.x, 4];
[] ← PWBasics.IncludeApplication[cell, CMosContacts.CreatePolyCon[l: 8], loc];
AddRet[cell:cell, size:size, loc:[loc.x, loc.y+2], level:CMos.pol]};
ENDLOOP;
Latch Cell
IF ~blank
THEN [] ← PWBasics.IncludeApplication[
cell: cell,
subcell: PWBasics.ObjFromName[design, (
IF noIORest
THEN "SimLatch"
ELSE "MuxLatch")],
location: [range.x*pitch.x, 0]];
PWBasics.RepositionCell[design, cell];
RETURN[PWBasics.NameFromObj[cell]]};
MuxLatch6x6x6: PW.UserProc = { RETURN[ MuxLatch[
design: design,
enable: "PhB",
top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"],
ctl: LIST["Reset", "Hold", "Set", "ASel", "Adv", "RdXBus"],
in: LIST["GND", "Last", "VDD", "Alpa", "In", "XB"],
out: LIST["Out"],
bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"]] ]};
MuxLatch6x7x6:
PW.UserProc = {
mux: PW.ObjName ← Mux[
design: design,
top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"],
ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"],
in: LIST["GND", "Last", "VDD", "Beta", "Alpa", "In", "XB"],
out: LIST["Out"],
bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"] ];
latch: PW.ObjName ← Latch[
design: design,
enable: "PhB",
top: LIST["XB", "Alpa", "Beta", "Pass", "Out", "In"],
in: LIST["GND", "Last", "VDD", "Beta", "Alpa", "In", "XB"],
out: LIST["Out"],
bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", "Last"] ];
RETURN[ PW.AbutY[latch, mux] ]};
Mux6x6:
PW.UserProc = {
RETURN[ Mux[
design: design,
top: LIST["XB", "Alpa", "Beta", "Pass", NIL, "In", "Out2"],
ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"],
in: LIST["XB", "Alpa", "Beta", "Pass", NIL, "Out2", "In"],
out: LIST["Out"],
bot: LIST["XB", "Alpa", "Beta", "Pass", "Out", NIL, "Out2"]] ]};
MuxBlank:
PW.UserProc = {
RETURN[ Mux[
design: design,
top: NIL,
ctl: LIST["Reset", "Hold", "Set", "BSel", "ASel", "Adv", "RdXBus"],
in: NIL,
out: NIL,
bot: NIL ] ]};
PW.Register[MuxLatch6x6x6, "Latch6x6x6"];
PW.Register[MuxLatch6x7x6, "Latch6x7x6"];
PW.Register[Latch6x6, "Latch6x6"];
PW.Register[IFULatchRowTest, "IFULatchRowTest"];
PW.Register[IFULatchRows, "IFULatchRows"];
PW.Register[Latch0, "Latch0"];
PW.Register[Latch1, "Latch1"];
PW.Register[Latch2, "Latch2"];
PW.Register[Latch3, "Latch3"];
PW.Register[MuxBlank, "MuxBlank"];
PW.Register[Mux6x6, "Mux6x6"];
END.