<> <> 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