<> <> <> <> <<>> <<>> 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: 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[ 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=NIL THEN NIL ELSE in.first; outN: PW.ROPE _ IF out=NIL THEN NIL ELSE out.first; <> 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; <> 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; <> 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]; <> 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]; <> 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; <> 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: 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[ 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; <> 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; <> 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; <> AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, 22], level: CMos.met2]; AddRet[cell:cell, size:[cellWidth,18], loc:[-leftTail, -4], level: CMos.met2]; <> 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"]; <> 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; <> 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. <<>>