Imports IO, RoseTypes; Directory Basics; Library SSI, Transistors; CELLTYPE "BasicPad" PORTS [Vdd, Gnd < BOOL, Pad = BOOL, nDataOut > BOOL] EvalSimple nDataOut _ NOT Pad; Expand invert: Inverter[Input: Pad, Output: nDataOut] ENDCELLTYPE; CELLTYPE "InputPad" PORTS [Vdd, Gnd, Pad < BOOL, DataOut > BOOL] EvalSimple DataOut _ Pad; Expand nbasicDataOut: BOOL; inputBasic: BasicPad[nDataOut: nbasicDataOut]; invert: Inverter[Input: nbasicDataOut, Output: DataOut] ENDCELLTYPE; CELLTYPE "DifferentialInputPad" PORTS [Vdd, Gnd, Pad < BOOL, DataOut, nDataOut > BOOL] EvalSimple DataOut _ Pad; nDataOut _ NOT Pad; Expand basicDataOut, nbasicDataOut: BOOL; inputBasic: BasicPad[nDataOut: nbasicDataOut]; invert1: Inverter[Input: nbasicDataOut, Output: DataOut]; invert2: Inverter[Input: nbasicDataOut, Output: basicDataOut]; invert3: Inverter[Input: basicDataOut, Output: nDataOut] ENDCELLTYPE; CELLTYPE "BidirectionalPad" PORTS [Vdd, Gnd, Read, nRead, Write, nWrite < BOOL, Pad, Data = BOOL] EvalSimple IF (Read AND nRead) OR (NOT Read AND NOT nRead) OR (Write AND nWrite) OR (NOT Write AND NOT nWrite) OR (Read AND Write) THEN RoseTypes.Stop["Bad control signals in bidirectional pad", $FailedAssertion]; IF Read THEN Pad _ Data; IF Write THEN Data _ Pad; Expand nor, nand, nbasicDataOut: BOOL; drivep: Nand2[Input1: Read, Input2: Data, Output: nand]; driven: Nor2[Input1: nRead, Input2: Data, Output: nor]; p: pE[gate: nand, ch1: Vdd, ch2: Pad]; n: nE[gate: nor, ch1: Pad, ch2: Gnd]; inputBasic: BasicPad[nDataOut: nbasicDataOut]; buffer: TristateBuffer[nDataIn: nbasicDataOut, Drive: Write, nDrive: nWrite, Output: Data] ENDCELLTYPE; BidirectionalPadSequence: LAMBDA [count: |NAT|] RETURN CELLTYPE NameMaker name _ IO.PutFR["BidirectionalPad%g", IO.int[count]] PortsProc portNumber: CARDINAL _ 0; InitPort: PROC[name: ROPE, input: BOOL _ TRUE, output: BOOL _ FALSE, type: NodeType _ NumTypes.boolType ] = { compilerBugBypass: Field _ [0, 0, 0]; ports[portNumber] _ [ simple: compilerBugBypass, switch: compilerBugBypass, name: name, type: type, input: input, output: output]; portNumber _ portNumber + 1; }; IF count<1 THEN ERROR; ports _ NEW [PortsRep[8]]; InitPort["Vdd"]; InitPort["Gnd"]; InitPort["Read"]; InitPort["nRead"]; InitPort["Write"]; InitPort["nWrite"]; InitPort[name: "Pads", output: TRUE, type: NumTypes.NumType[count]]; InitPort[name: "Data", output: TRUE, type: NumTypes.NumType[count]]; Expand Cedar padSubNodes: RoseTypes.UnnamedConsNE _ NEW[RoseTypes.NodeExpressionRep.unnamedCons _ [unnamedCons [elts: NIL]]]; dataSubNodes: RoseTypes.UnnamedConsNE _ NEW[RoseTypes.NodeExpressionRep.unnamedCons _ [unnamedCons [elts: NIL]]]; FOR ip: CARDINAL DECREASING IN [0..count) DO padSubNodes.elts _ CONS[NEW[ NodeExpressionRep.primary _ [primary[ node: to.class.NodeInstance[erInstance: to.instance, name: IO.PutFR["Pad%g", IO.int[ip]], type: NumTypes.boolType], selector: [whole [ ]]]]], padSubNodes.elts]; dataSubNodes.elts _ CONS[NEW[ NodeExpressionRep.primary _ [primary[ node: to.class.NodeInstance[erInstance: to.instance, name: IO.PutFR["Data%g", IO.int[ip]], type: NumTypes.boolType], selector: [whole [ ]]]]], dataSubNodes.elts]; [] _ to.class.CellInstance[erInstance: to.instance, instanceName: IO.PutFR["BidirPad%g", IO.int[ip]], typeName: "BidirectionalPad", interfaceNodes: IO.PutFR["Pad:Pad%g, Data:Data%g", IO.int[ip], IO.int[ip]]]; ENDLOOP; to.class.Equivalence[erInstance: to.instance, a: NEW[NodeExpressionRep.primary _ [primary [node: RoseCreate.LookupNode[from: thisCell, path: LIST["Pads"]], selector: [whole [ ]]]]], b: padSubNodes]; to.class.Equivalence[erInstance: to.instance, a: NEW[NodeExpressionRep.primary _ [primary [node: RoseCreate.LookupNode[from: thisCell, path: LIST["Data"]], selector: [whole [ ]]]]], b: dataSubNodes] ENDCELLTYPE; CEDAR bpw: NAT = Basics.bitsPerWord; InputPadSeqSimpleIORef: TYPE = REF InputPadSeqSimpleIORec; InputPadSeqSimpleIORec: TYPE = MACHINE DEPENDENT RECORD [ Fill0(0: 0..14): [0..32768), Vdd(0: 15..15): BOOL, Fill1(1: 0..14): [0..32768), Gnd(1: 15..15): BOOL, Pad(2: 0..15): CARDINAL, DataOut(3: 0..15): CARDINAL ]; InputPadSeqSwitchIORef: TYPE = REF InputPadSeqSwitchIORec; InputPadSeqSwitchIORec: TYPE = MACHINE DEPENDENT RECORD [ Vdd(0): SwitchTypes.SwitchVal, Gnd(1): SwitchTypes.SwitchVal, ports(2): SEQUENCE COMPUTED CARDINAL OF SwitchTypes.SwitchVal]; InputPadSeqDriveRec: TYPE = RECORD [tag: DriveTagType, drive: PACKED ARRAY InputPadSeqPort OF DriveLevel]; InputPadSeqPort: TYPE = {Vdd, Gnd, Pad, DataOut}; ; InputPadSequence: LAMBDA [count: |NAT|] RETURN CELLTYPE NameMaker name _ IO.PutFR["InputPad%g", IO.int[count]] PortsProc IF count<1 OR count>bpw THEN ERROR; -- doesn't handle wide buses yet ports _ NEW [PortsRep[4]]; ports[0] _ [ simple: [0, bpw-1, 1], switch: [0, 0, bpw], name: "Vdd", type: NumTypes.boolType, input: TRUE]; ports[1] _ [ simple: [1, bpw-1, 1], switch: [1, 0, bpw], name: "Gnd", type: NumTypes.boolType, input: TRUE]; ports[2] _ [ simple: [2, bpw-count, count], switch: [2, 0, count*bpw], name: "Pad", type: NumTypes.NumType[count], input: TRUE]; ports[3] _ [ simple: [3, bpw-count, count], switch: [2+count, 0, count*bpw], name: "DataOut", type: NumTypes.NumType[count], output: TRUE]; SimpleIOAux RecType InputPadSeqSimpleIORec SwitchIOAux RecType InputPadSeqSwitchIORec DriveAux RecType InputPadSeqDriveRec EvalSimple DataOut _ Pad; Expand Cedar padSubNodes: RoseTypes.UnnamedConsNE _ NEW[RoseTypes.NodeExpressionRep.unnamedCons _ [unnamedCons [elts: NIL]]]; dataOutSubNodes: RoseTypes.UnnamedConsNE _ NEW[RoseTypes.NodeExpressionRep.unnamedCons _ [unnamedCons [elts: NIL]]]; FOR ip: CARDINAL DECREASING IN [0..count) DO padSubNodes.elts _ CONS[NEW[ NodeExpressionRep.primary _ [primary[ node: to.class.NodeInstance[erInstance: to.instance, name: IO.PutFR["Pad%g", IO.int[ip]], type: NumTypes.boolType], selector: [whole [ ]]]]], padSubNodes.elts]; dataOutSubNodes.elts _ CONS[NEW[ NodeExpressionRep.primary _ [primary[ node: to.class.NodeInstance[erInstance: to.instance, name: IO.PutFR["DataOut%g", IO.int[ip]], type: NumTypes.boolType], selector: [whole [ ]]]]], dataOutSubNodes.elts]; [] _ to.class.CellInstance[erInstance: to.instance, instanceName: IO.PutFR["InputPad%g", IO.int[ip]], typeName: "InputPad", interfaceNodes: IO.PutFR["Pad:Pad%g, DataOut:DataOut%g", IO.int[ip], IO.int[ip]]]; ENDLOOP; to.class.Equivalence[erInstance: to.instance, a: NEW[NodeExpressionRep.primary _ [primary [node: RoseCreate.LookupNode[from: thisCell, path: LIST["Pad"]], selector: [whole [ ]]]]], b: padSubNodes]; to.class.Equivalence[erInstance: to.instance, a: NEW[NodeExpressionRep.primary _ [primary [node: RoseCreate.LookupNode[from: thisCell, path: LIST["DataOut"]], selector: [whole [ ]]]]], b: dataOutSubNodes] ENDCELLTYPE ψPads.rose Last Edited by: Barth, June 18, 1985 6:37:56 pm PDT The protection devices need to be inserted here. SimpleIOAux InitialValue |NEW[InputPadSeqSimpleIORec[?count?]]| SwitchIOAux InitialValue |NEW[InputPadSeqSwitchIORec[2*count]]| ΚΧ˜J™ J™3J˜JšœΟkœ ˜Jšœ˜Jšœœ ˜J˜codešœΟbœ˜Kšœ œœ œ˜4˜ Kšœ œ˜—˜K™0Kšœ.˜.—Kš œ˜ K˜—šœžœ˜Kšœœ œ˜,˜ Kšœ˜—˜Kšœœ˜K™Kšœ.˜.Kšœ7˜7—Kš œ˜ K˜—šœžœ˜Kšœœœ˜6˜ Kšœ˜Kšœ œ˜—˜Kšœœ˜"K™Kšœ.˜.Kšœ9˜9Kšœ>˜>Kšœ8˜8—Kš ˜ K˜—šœžœ˜Kšœ)œœ˜E˜ Kšœœœœœœœœ œœœœ œœœN˜ΚKšœœ ˜Kšœœ ˜—˜Kšœœ˜K™Kšœ8˜8Kšœ7˜7Kšœ&˜&Kšœ%˜%Kšœ.˜.KšœZ˜Z—Kš ˜ K˜—šž œ œœ˜?šœ ˜ Jšœœœ ˜5—˜ Kšœ œ˜šΟnœœœ œœ œœ*˜mKšœ%˜%šœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜—K˜—Kšœ œœ˜Kšœœ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ!˜DKšœœ!˜D—˜˜Kšœ'œ?œ˜pKšœ(œ?œ˜qš œœ œœ ˜,Kš œœœcœœQ˜γKš œœœcœœR˜ζKš œBœœ9œ!œ œ ˜ΠKšœ˜—Kšœ1œYœ5˜ΖKšœ1œYœ5˜Ζ—K˜—Kš œ˜ J˜—š˜Kšœœ˜K˜Kšœœœ˜:š œœœ œœ˜9Kšœ˜Kšœœ˜Kšœ˜Kšœœ˜Kšœœ˜Kšœ˜Kšœ˜—K˜Kšœœœ˜:šœœœ˜9Kšœ˜Kšœ˜Kš œ œœœœ˜?—K˜Kš œœœœœœ ˜jK˜Kšœœ˜1K˜—K˜K˜šž œ œœ˜7šœ ˜ Jšœœœ ˜-—˜ Kš œ œ œœΟc ˜EKšœœ˜šœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœœ˜ —šœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœœ˜ —šœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœœ˜ —šœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœœ˜——Kšœ*˜*Kšœœ"™?Kšœ*˜*Kšœœ"™?Kšœ$˜$˜ Kšœ˜—˜˜Kšœ'œ?œ˜pKšœ+œ?œ˜tš œœ œœ ˜,Kš œœœcœœQ˜γKš œœœcœœU˜οKš œBœœ1œ'œ œ ˜ΞKšœ˜—Kšœ1œYœ4˜ΕKšœ1œYœ;˜Μ—K˜—Kš ˜ J˜——…—\"+