SSIImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, April 25, 1986 2:09:56 pm PST
Louis Monier June 11, 1986 2:04:50 pm PDT
Bertrand Serlet January 27, 1986 4:16:01 pm PST
DIRECTORY Basics, Core, CoreCreate, CoreOps, Ports, RealOps, Rope, Rosemary, SSI;
SSIImpl:
CEDAR
PROGRAM
IMPORTS Basics, CoreCreate, RealOps, Rosemary, Ports
EXPORTS SSI
= BEGIN OPEN SSI, CoreCreate;
PWRule:
PROC [nw:
NAT, r:
REAL, pw:
NAT]
RETURNS [newpw:
NAT] = {
foo: INT ← IF pw=0 THEN RealOps.RoundLI[RealOps.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:
NAT ←
SELECT 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"]],
Instance[MakeTransistor[nE, nw, nl, r, pw, pl, size],
["gate", "Input"], ["ch1", "nOutput"], ["ch2", "Gnd"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: InverterName];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[InverterVdd], initType: l];
[] ← Ports.InitPort[wire: ct.public[InverterGnd], initType: l];
[] ← Ports.InitPort[wire: ct.public[InverterInput], initType: l];
[] ← Ports.InitPort[wire: ct.public[InverternOutput], initType: 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"]],
Instance[pType, ["gate", "nDrive"], ["ch1", "pstack"], ["ch2", "nOutput"]],
Instance[nType, ["gate", "Drive"], ["ch1", "nOutput"], ["ch2", "nstack"]],
Instance[nType, ["gate", "Input"], ["ch1", "nstack"], ["ch2", "Gnd"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TristateBufferName];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "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"]],
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];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[NAndnOutput], initType: 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];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[AndOutput], initType: 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]]],
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];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[NOrnOutput], initType: 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];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: "JustAboveTransistors"];
[] ← Ports.InitPort[wire: ct.public[OrOutput], initType: 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.