SSIImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by: Barth, July 9, 1985 6:14:47 pm PDT
DIRECTORY Core, IO, RealOps, Rope, SSI, Transistor;
SSIImpl:
CEDAR
PROGRAM
IMPORTS Core, IO, RealOps, Rope, Transistor
EXPORTS SSI =
BEGIN OPEN Core, SSI;
CreateInverter:
PUBLIC PROC [design: Design, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← WidthRatioNameProc["Inverter", width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
p: CellType ← TransistorType[design: design, stackType: pE, width: width, ratio: ratio];
n: CellType ← TransistorType[design: design, width: width, ratio: ratio];
ct ← CreateCellType[design: design, cellTypeName: name];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
CreatePort[on: ct, name: "Input"];
CreatePort[on: ct, name: "Output", direction: output];
CreateCell[in: ct, type: p, bind: "gate: Input, ch1: Vdd, ch2: Output"];
CreateCell[in: ct, type: n, bind: "gate: Input, ch1: Output, ch2: Gnd"];
};
};
CreateTristateBuffer:
PUBLIC PROC [design: Design, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← WidthRatioNameProc["TristateBuffer", width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
p: CellType ← TransistorType[design: design, stackHeight: 2, stackType: pE, width: width, ratio: ratio];
n: CellType ← TransistorType[design: design, stackHeight: 2, width: width, ratio: ratio];
ct ← CreateCellType[design: design, cellTypeName: name];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
CreatePort[on: ct, name: "nInput"];
CreatePort[on: ct, name: "Drive"];
CreatePort[on: ct, name: "nDrive"];
CreatePort[on: ct, name: "Output", direction: tristate];
CreateNet[in: ct, name: "pstack"];
CreateNet[in: ct, name: "nstack"];
CreateCell[in: ct, type: p, bind: "gate: nInput, ch1: Vdd, ch2: pstack"];
CreateCell[in: ct, type: p, bind: "gate: nDrive, ch1: pstack, ch2: Output"];
CreateCell[in: ct, type: n, bind: "gate: Drive, ch1: Output, ch2: nstack"];
CreateCell[in: ct, type: n, bind: "gate: nInput, ch1: nstack, ch2: Gnd"];
ChipBehaviour.Register[cellType: ct, evalSimple: TristateBufferBehaviour];
};
};
TristateBufferBehaviour: ChipBehaviour.EvalProc = {
PortIndex: TYPE = {Vdd, Gnd, nInput, Drive, nDrive, Output};
IF (Drive AND nDrive) OR (NOT Drive AND NOT nDrive) THEN RoseTypes.Stop["Bad control signals in tristate buffer", $FailedAssertion];
Output ← NOT nDataIn;
drive[Output] ← IF Drive THEN drive ELSE ignore;
};
WidthRatioNameProc:
PROC [prefix:
ROPE, width:
NAT, ratio:
REAL]
RETURNS [name:
ROPE] = {
formatName: ROPE ← Rope.Cat[prefix, "%g*%g"];
name ← IO.PutFR[formatName, IO.int[width], IO.real[ratio]];
};
CreateNAnd:
PUBLIC
PROC [design: Design, inputCount:
NAT ← 2, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← CountWidthRatioNameProc["NAnd", inputCount, width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
p: CellType ← TransistorType[design: design, stackType: pE, width: width, ratio: ratio];
n: CellType ← TransistorType[design: design, stackHeight: inputCount, width: width, ratio: ratio];
ct ← CreateCellType[design: design, cellTypeName: name];
NPortStackProc[ct: ct, inputCount: inputCount];
FOR input:
NAT
IN [0..inputCount)
DO
CreateCell[in: ct, type: p, bind: IO.PutFR["gate: Input%g, ch1: Vdd, ch2: nOutput", IO.int[input]]];
CreateCell[in: ct, type: n, bind: IO.PutFR["gate: Input%g, ch1: %g, ch2: %g", IO.int[input], IF input=0 THEN IO.rope["nOutput"] ELSE IO.rope[IO.PutFR["nstack%g", IO.int[input-1]]], IF input=inputCount-1 THEN IO.rope["Gnd"] ELSE IO.rope[IO.PutFR["nstack%g", IO.int[input]]]]];
ENDLOOP;
};
};
CreateAnd:
PUBLIC
PROC [design: Design, inputCount:
NAT ← 2, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← CountWidthRatioNameProc["And", inputCount, width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
nand: CellType ← CreateNAnd[design: design, inputCount: inputCount, width: width, ratio: ratio]; -- fix this to scale nand to inverter gate cap.
invert: CellType ← CreateInverter[design: design, width: width, ratio: ratio];
ct ← CreateCellType[design: design, cellTypeName: name];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
FOR input:
NAT
IN [0..inputCount)
DO
inputName: ROPE ← IO.PutFR["Input%g", IO.int[input]];
CreatePort[on: ct, name: inputName];
ENDLOOP;
CreatePort[on: ct, name: "Output", direction: output];
CreateNet[in: ct, name: "nOutput"];
CreateCell[in: ct, type: nand];
CreateCell[in: ct, type: invert, bind: "Input: nOutput"];
};
};
CreateNOr:
PUBLIC
PROC [design: Design, inputCount:
NAT ← 2, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← CountWidthRatioNameProc["NOr", inputCount, width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
p: CellType ← TransistorType[design: design, stackHeight: inputCount, stackType: pE, width: width, ratio: ratio];
n: CellType ← TransistorType[design: design, width: width, ratio: ratio];
ct ← CreateCellType[design: design, cellTypeName: name];
NPortStackProc[ct: ct, inputCount: inputCount];
FOR input:
NAT
IN [0..inputCount)
DO
CreateCell[in: ct, type: p, bind: IO.PutFR["gate: Input%g, ch1: %g, ch2: %g", IO.int[input], IF input=0 THEN IO.rope["Vdd"] ELSE IO.rope[IO.PutFR["stack%g", IO.int[input-1]]], IF input=inputCount-1 THEN IO.rope["nOutput"] ELSE IO.rope[IO.PutFR["stack%g", IO.int[input]]]]];
CreateCell[in: ct, type: n, bind: IO.PutFR["gate: Input%g, ch1: nOutput, ch2: Gnd", IO.int[input]]];
ENDLOOP;
};
};
CreateOr:
PUBLIC
PROC [design: Design, inputCount:
NAT ← 2, width:
NAT ← 4, ratio:
REAL ← 2.5]
RETURNS [ct: CellType] = {
name: ROPE ← CountWidthRatioNameProc["And", inputCount, width, ratio];
IF (ct ← LookupCellType[design, name])=
NIL
THEN {
invert: CellType ← CreateInverter[design: design, width: 4, ratio: ratio];
nand: CellType ← CreateNAnd[design: design, inputCount: inputCount, width: width, ratio: ratio];
bindRope: ROPE ← NIL;
ct ← CreateCellType[design: design, cellTypeName: name];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
FOR input:
NAT
IN [0..inputCount)
DO
inputName: ROPE ← IO.PutFR["Input%g", IO.int[input]];
ninputName: ROPE ← IO.PutFR["nInput%g", IO.int[input]];
CreatePort[on: ct, name: inputName];
CreateNet[in: ct, name: ninputName];
bindRope ← Rope.Cat[bindRope, inputName, ": ", ninputName, IF input<inputCount-1 THEN ", " ELSE NIL];
ENDLOOP;
bindRope ← Rope.Cat[bindRope, ", nOutput: Output"];
CreatePort[on: ct, name: "Output", direction: output];
FOR input:
NAT
IN [0..inputCount)
DO
CreateCell[in: ct, type: invert, bind: IO.PutFR["Input: Input%g, Output: nInput%g", IO.int[input], IO.int[input]]];
ENDLOOP;
CreateCell[in: ct, type: nand, bind: bindRope];
};
};
NPortStackProc:
PROC [ct: CellType, inputCount:
NAT] = {
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
FOR input:
NAT
IN [0..inputCount)
DO
CreatePort[on: ct, name: IO.PutFR["Input%g", IO.int[input]]];
IF input < inputCount-2 THEN CreateNet[in: ct, name: IO.PutFR["stack%g", IO.int[input]]];
ENDLOOP;
CreatePort[on: ct, name: "nOutput", direction: output];
};
CountWidthRatioNameProc:
PROC [prefix:
ROPE, inputCount:
NAT, width:
NAT, ratio:
REAL]
RETURNS [name:
ROPE] = {
formatName: ROPE ← Rope.Cat[prefix, "%g*%g*%g"];
name ← IO.PutFR[formatName, IO.int[inputCount], IO.int[width], IO.real[ratio]];
};
TransistorType:
PROC [design: Design, stackHeight:
NAT ← 1, stackType: Transistor.TransistorType ← nE, width:
NAT, ratio:
REAL]
RETURNS [t: CellType] = {
tWidth: NAT ← stackHeight * width;
IF stackType = pE THEN tWidth ← RealOps.RoundLI[RealOps.Float[tWidth] * ratio, [round: rp]];
t ← Transistor.CreateTransistor[design: design, type: stackType, width: tWidth];
};
END.