CoreSSIImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by: Barth, July 10, 1985 8:40:19 pm PDT
DIRECTORY ChipCreate, IO, RealOps, Rope, CoreSSI, CoreTransistor;
CoreSSIImpl: CEDAR PROGRAM
IMPORTS ChipCreate, IO, RealOps, Rope, CoreTransistor
EXPORTS CoreSSI =
BEGIN OPEN ChipCreate, CoreSSI;
fileRoot: ROPE ← "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", pin: [top, 0]];
CreatePort[on: ct, name: "Gnd", pin: [bottom, 0]];
CreatePort[on: ct, name: "Input", pin: [left, 0]];
CreatePort[on: ct, name: "Output", pin: [right, 0], attributes: LIST[[$StcOut, NIL]]];
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] = {
class: ROPE ← "TristateBuffer";
name: ROPE ← WidthRatioNameProc[class, 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, attributes: LIST[[$Behave, class], [$BhvFileRoot, fileRoot]]];
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", attributes: LIST[[$StcTristate, NIL]]];
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"];
};
};
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]];
};
NAndArgsRef: TYPE = REF NAndArgsRec;
NAndArgsRec: TYPE = RECORD[inputCount: NAT ← 2];
CreateNAnd: PUBLIC PROC [design: Design, inputCount: NAT ← 2, width: NAT ← 4, ratio: REAL ← 2.5] RETURNS [ct: CellType] = {
class: ROPE ← "NAnd";
name: ROPE ← CountWidthRatioNameProc[class, 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 ← CreateRecordCellType[design: design, cellTypeName: name, attributes: LIST[[$Behave, class], [$BhvFileRoot, fileRoot], [$BhvArgs, NEW[NAndArgsRec ← [inputCount: inputCount]]]]];
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 {
inputSeq: NetType ← CreateSequenceNetType[design: design, count: inputCount];
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"];
CreatePort[on: ct, name: "Input", type: inputSeq];
CreatePort[on: ct, name: "Output", attributes: LIST[[$StcOut, NIL]]];
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 {
inputSeq: NetType ← CreateSequenceNetType[design: design, count: inputCount];
invertSeq: CellType ← CreateSequenceCellType[design: design, baseCellType: CreateInverter[design: design, width: 4, ratio: ratio], axis: y, count: inputCount];
nand: CellType ← CreateNAnd[design: design, inputCount: inputCount, width: width, ratio: ratio];
bindRope: ROPENIL;
ct ← CreateCellType[design: design, cellTypeName: name];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
CreatePort[on: ct, name: "Input", type: inputSeq];
CreatePort[on: ct, name: "Output", attributes: LIST[[$StcOut, NIL]]];
CreateNet[in: ct, name: "nInput", type: inputSeq];
CreateCell[in: ct, type: invertSeq, bind: "Input: Input, Output: nInput"];
CreateCell[in: ct, type: nand, bind: "Input: nInput, nOutput: Output"];
};
};
NPortStackProc: PROC [ct: CellType, inputCount: NAT] = {
inputSeq: NetType ← CreateSequenceNetType[design: design, count: inputCount];
CreatePort[on: ct, name: "Vdd"];
CreatePort[on: ct, name: "Gnd"];
CreatePort[on: ct, name: "Input", type: inputSeq];
FOR input: NAT IN [0..inputCount-1) DO
CreateNet[in: ct, name: IO.PutFR["stack%g", IO.int[input]]];
ENDLOOP;
CreatePort[on: ct, name: "nOutput", attributes: LIST[[$StcOut, NIL]]];
};
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.