SSIImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Barth, October 10, 1986 5:35:29 pm PDT
Bertrand Serlet April 2, 1987 11:39:42 pm PST
Louis Monier August 7, 1986 7:46:46 pm PDT
DIRECTORY Basics, Core, CoreCreate, CoreFlat, CoreOps, Ports, Real, RealOps, Rope, Rosemary, SSI;
SSIImpl: CEDAR PROGRAM
IMPORTS Basics, CoreCreate, CoreFlat, Real, RealOps, Rosemary, Ports
EXPORTS SSI
= BEGIN OPEN SSI, CoreCreate;
PWRule: PROC [nw: NAT, r: REAL, pw: NAT] RETURNS [newpw: NAT] = {
foo: INTIF pw=0 THEN RealOps.ModalRound[Real.Float[nw] * r, [round: rn]] ELSE pw;
IF Basics.HighHalf[foo]#0 THEN ERROR;
newpw ← Basics.LowHalf[foo];
};
MakeTransistor: PROC [type: TransistorType, nw: NAT, nl: NAT, r: REAL, pw: NAT, pl: NAT, size: Rosemary.TransistorSize ← drive] RETURNS [t: Core.CellType] = {
tWidth: NATSELECT type FROM
nE, nD => nw,
pE => PWRule[nw, r, pw],
ENDCASE => ERROR;
t ← Rosemary.SetTransistorCellTypeSize[Transistor[type: type, width: tWidth], size];
};
InverterName: ROPE = Rosemary.Register[roseClassName: "Inverter", evalSimple: InverterSimple];
InverterVdd: NAT = 0;
InverterGnd: NAT = 1;
InverterInput: NAT = 2;
InverternOutput: NAT = 3;
Inverter: PUBLIC PROC [nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2, size: Rosemary.TransistorSize ← drive] RETURNS [ct: CellType] = {
ct ← Cell[
name: InverterName,
public: Wires["Vdd", "Gnd", "Input", "nOutput"],
instances: LIST [
Instance[MakeTransistor[pE, nw, nl, r, pw, pl, size],
["gate", "Input"], ["ch1", "Vdd"], ["ch2", "nOutput"], ["well", "Vdd"]],
Instance[MakeTransistor[nE, nw, nl, r, pw, pl, size],
["gate", "Input"], ["ch1", "nOutput"], ["ch2", "Gnd"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: InverterName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[InverterVdd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[InverterGnd], levelType: l];
[] ← Ports.InitPort[wire: ct.public[InverterInput], levelType: l];
[] ← Ports.InitPort[wire: ct.public[InverternOutput], levelType: l, initDrive: size];
};
InverterSimple: Rosemary.EvalProc = {
p[InverternOutput].l ← SELECT TRUE FROM
p[InverterInput].l=X OR p[InverterVdd].l#H OR p[InverterGnd].l#L => X,
p[InverterInput].l=L => H,
p[InverterInput].l=H => L,
ENDCASE => ERROR;
};
TristateBufferName: ROPE = Rosemary.Register[roseClassName: "TristateBuffer", evalSimple: TristateSimple];
TristateVdd: NAT = 0;
TristateGnd: NAT = 1;
TristateInput: NAT = 2;
TristateDrive: NAT = 3;
TristatenDrive: NAT = 4;
TristatenOutput: NAT = 5;
TristateBuffer: PUBLIC PROC [nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
pType: Core.CellType ← MakeTransistor[pE, nw, nl, r, pw, pl];
nType: Core.CellType ← MakeTransistor[nE, nw, nl, r, pw, pl];
ct ← Cell[
name: TristateBufferName,
public: Wires["Vdd", "Gnd", "Input", "Drive", "nDrive", "nOutput"],
onlyInternal: Wires["pstack", "nstack"],
instances: LIST [
Instance[pType, ["gate", "Input"], ["ch1", "Vdd"], ["ch2", "pstack"], ["well", "Vdd"]],
Instance[pType, ["gate", "nDrive"], ["ch1", "pstack"], ["ch2", "nOutput"], ["well", "Vdd"]],
Instance[nType, ["gate", "Drive"], ["ch1", "nOutput"], ["ch2", "nstack"]],
Instance[nType, ["gate", "Input"], ["ch1", "nstack"], ["ch2", "Gnd"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TristateBufferName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
};
TristateSimple: Rosemary.EvalProc = {
IF NOT p[TristateVdd].b OR p[TristateGnd].b OR (p[TristateDrive].b AND NOT p[TristatenDrive].b) THEN SIGNAL Rosemary.Stop[];
p[TristatenOutput].d ← IF p[TristateDrive].b OR NOT p[TristatenDrive].b THEN drive ELSE none;
p[TristatenOutput].b ← NOT p[TristateInput].b;
};
NAndName: ROPE = Rosemary.Register[roseClassName: "NAnd", evalSimple: NAndSimple];
NAndVdd: NAT = 0;
NAndGnd: NAT = 1;
NAndInput: NAT = 2;
NAndnOutput: NAT = 3;
NAnd: PUBLIC PROC [i: NAT, nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
instances: LIST OF CellInstance ← NIL;
pType: Core.CellType ← MakeTransistor[pE, nw, nl, r, pw, pl];
nType: Core.CellType ← MakeTransistor[nE, nw, nl, r, pw, pl];
FOR input: NAT IN [0..i) DO
instances ← CONS[Instance[pType,
["gate", Index["Input", input]], ["ch1", "Vdd"], ["ch2", "nOutput"], ["well", "Vdd"]],
instances];
instances ← CONS[Instance[nType,
["gate", Index["Input", input]],
["ch1", IF input=0 THEN "nOutput" ELSE Index["stack", input-1]],
["ch2", IF input=i-1 THEN "Gnd" ELSE Index["stack", input]]],
instances];
ENDLOOP;
ct ← Cell[
name: NAndName,
public: Wires["Vdd", "Gnd", Seq["Input", i], "nOutput"],
onlyInternal: Wires[Seq["stack", i-1]],
instances: instances];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: NAndName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[NAndnOutput], levelType: b, initDrive: drive];
};
NAnd2: PUBLIC PROC [nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] ~ {
nand: CellType ← NAnd[2, nw, nl, r, pw, pl];
public: Wire ← Wires["Vdd", "Gnd", "Input0", "Input1", "nOutput"];
ct ← Cell[
name: "NAnd2",
public: public,
instances: LIST[Instance[nand, ["Input", Wires["Input0", "Input1"]]]] ];
};
NAndSimple: Rosemary.EvalProc = {
IF NOT p[NAndVdd].b OR p[NAndGnd].b THEN SIGNAL Rosemary.Stop[];
FOR input: NAT IN [0..p[NAndInput].size) DO
IF NOT p[NAndInput][input].b THEN {
p[NAndnOutput].b ← TRUE;
EXIT;
};
REPEAT
FINISHED => p[NAndnOutput].b ← FALSE;
ENDLOOP;
};
AndName: ROPE = Rosemary.Register[roseClassName: "And", evalSimple: AndSimple];
AndVdd: NAT = 0;
AndGnd: NAT = 1;
AndInput: NAT = 2;
AndOutput: NAT = 3;
And: PUBLIC PROC [i: NAT, nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
ct ← Cell[
name: AndName,
public: Wires["Vdd", "Gnd", Seq["Input", i], "Output"],
onlyInternal: Wires["nOutput"],
instances: LIST [
Instance[NAnd[i, nw, nl, r, pw, pl]], -- fix this to scale nand to inverter gate cap.
Instance[Inverter[nw, nl, r, pw, pl], ["Input", "nOutput"], ["nOutput", "Output"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: AndName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[AndOutput], levelType: b, initDrive: drive];
};
AndSimple: Rosemary.EvalProc = {
IF NOT p[AndVdd].b OR p[AndGnd].b THEN SIGNAL Rosemary.Stop[];
FOR input: NAT IN [0..p[AndInput].size) DO
IF NOT p[AndInput][input].b THEN {
p[AndOutput].b ← FALSE;
EXIT;
};
REPEAT
FINISHED => p[AndOutput].b ← TRUE;
ENDLOOP;
};
NOrName: ROPE = Rosemary.Register[roseClassName: "NOr", evalSimple: NOrSimple];
NOrVdd: NAT = 0;
NOrGnd: NAT = 1;
NOrInput: NAT = 2;
NOrnOutput: NAT = 3;
NOr: PUBLIC PROC [i: NAT, nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
instances: LIST OF CellInstance ← NIL;
pType: Core.CellType ← MakeTransistor[pE, nw, nl, r, pw, pl];
nType: Core.CellType ← MakeTransistor[nE, nw, nl, r, pw, pl];
FOR input: NAT IN [0..i) DO
instances ← CONS[Instance[pType,
["gate", Index["Input", input]],
["ch1", IF input=0 THEN "Vdd" ELSE Index["stack", input-1]],
["ch2", IF input=i-1 THEN "nOutput" ELSE Index["stack", input]],
["well", "Vdd"]],
instances];
instances ← CONS[Instance[nType,
["gate", Index["Input", input]], ["ch1", "nOutput"], ["ch2", "Gnd"]],
instances];
ENDLOOP;
ct ← Cell[
name: NOrName,
public: Wires["Vdd", "Gnd", Seq["Input", i], "nOutput"],
onlyInternal: Wires[Seq["stack", i-1]],
instances: instances];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: NOrName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[NOrnOutput], levelType: b, initDrive: drive];
};
NOr2: PUBLIC PROC [nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] ~ {
nor: CellType ← NOr[2, nw, nl, r, pw, pl];
public: Wire ← Wires["Vdd", "Gnd", "Input0", "Input1", "nOutput"];
ct ← Cell[
name: "NOr2",
public: public,
instances: LIST[Instance[nor, ["Input", Wires["Input0", "Input1"]]]] ];
};
NOrSimple: Rosemary.EvalProc = {
IF NOT p[NOrVdd].b OR p[NOrGnd].b THEN SIGNAL Rosemary.Stop[];
FOR input: NAT IN [0..p[NOrInput].size) DO
IF p[NOrInput][input].b THEN {
p[NOrnOutput].b ← FALSE;
EXIT;
};
REPEAT
FINISHED => p[NOrnOutput].b ← TRUE;
ENDLOOP;
};
OrName: ROPE = Rosemary.Register[roseClassName: "Or", evalSimple: OrSimple];
OrVdd: NAT = 0;
OrGnd: NAT = 1;
OrInput: NAT = 2;
OrOutput: NAT = 3;
Or: PUBLIC PROC [i: NAT, nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
ct ← Cell[
name: OrName,
public: Wires["Vdd", "Gnd", Seq["Input", i], "Output"],
onlyInternal: Wires[Seq["nInput", i]],
instances: LIST [
Instance[InverterSeq[i, nw, nl, r, pw, pl], ["Input", "Input"], ["nOutput", "nInput"]],
Instance[NAnd[i, nw, nl, r, pw, pl], ["Input", "nInput"], ["nOutput", "Output"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: OrName];
[] ← CoreFlat.CellTypeCutLabels[ct, "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[OrOutput], levelType: b, initDrive: drive];
};
OrSimple: Rosemary.EvalProc = {
IF NOT p[OrVdd].b OR p[OrGnd].b THEN SIGNAL Rosemary.Stop[];
FOR input: NAT IN [0..p[OrInput].size) DO
IF p[OrInput][input].b THEN {
p[OrOutput].b ← TRUE;
EXIT;
};
REPEAT
FINISHED => p[OrOutput].b ← FALSE;
ENDLOOP;
};
InverterSeqName: ROPE = "InverterSeq";
InverterSeq: PROC [i: NAT, nw: NAT ← 4, nl: NAT ← 2, r: REAL ← 2.5, pw: NAT ← 0, pl: NAT ← 2] RETURNS [ct: CellType] = {
baseCell: CellType ← Inverter[nw, nl, r, pw, pl];
ct ← SequenceCell[
name: InverterSeqName,
baseCell: baseCell,
count: i,
sequencePorts: Wires[baseCell.public[InverterInput], baseCell.public[InverternOutput]]];
};
END.