SSI.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, November 5, 1985 2:39:33 pm PST
Louis Monier October 21, 1985 5:26:34 pm PDT
Bertrand Serlet November 9, 1985 2:40:31 pm PST
DIRECTORY Core, CoreCompose, CoreFlatten, CoreProperties, IO, RealOps, Rosemary, SymTab;
SSI:
CEDAR
PROGRAM
IMPORTS CoreCompose, CoreFlatten, CoreProperties, IO, RealOps, Rosemary, SymTab
= BEGIN OPEN CoreCompose;
WidthRatioNameProc:
PROC [context: Context, prefix:
ROPE]
RETURNS [name:
ROPE] = {
name ← IO.PutFR["%g%g*%g", IO.rope[prefix], IO.int[GetInt[context, $SSIWidth]], IO.real[GetReal[context, $SSIRatio]]];
};
CountWidthRatioNameProc:
PROC [context: Context, prefix:
ROPE]
RETURNS [name:
ROPE] = {
inputCount: NAT ← GetInt[context: context, prop: $SSIInputCount];
width: NAT ← GetInt[context: context, prop: $SSIWidth];
ratio: REAL ← GetReal[context: context, prop: $SSIRatio];
name ← IO.PutFR["%g%g*%g*%g", IO.rope[prefix], IO.int[inputCount], IO.int[width], IO.real[ratio]];
};
MakeTransistor:
PROC [context: Context, stackHeight:
NAT ← 1, stackType: TransistorType ← nE]
RETURNS [t: Core.CellType] = {
width: NAT ← GetInt[context: context, prop: $SSIWidth];
ratio: REAL ← GetReal[context: context, prop: $SSIRatio];
tWidth: NAT ← stackHeight * width;
IF stackType = pE THEN tWidth ← RealOps.RoundLI[RealOps.Float[tWidth] * ratio, [round: rn]];
t ← CreateTransistor[type: stackType, width: tWidth];
};
SSICache: SymTab.Ref ← SymTab.Create[];
Lookup:
PROC [name:
ROPE]
RETURNS [cellType: Core.CellType ←
NIL] = {
found: BOOL;
val: REF ANY;
[found, val] ← SymTab.Fetch[x: SSICache, key: name];
IF found THEN cellType ← NARROW[val];
};
Insert:
PROC [name:
ROPE, cellType: Core.CellType] = {
IF NOT SymTab.Insert[x: SSICache, key: name, val: cellType] THEN ERROR;
};
Inverter:
ROPE = RegisterStructureProc[name: "Inverter", proc: CreateInverter];
InverterVdd: NAT = 0;
InverterGnd: NAT = 1;
InverterInput: NAT = 2;
InverterOutput: NAT = 3;
CreateInverter: StructureProc = {
name: ROPE ← WidthRatioNameProc[context: context, prefix: Inverter];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, Input, Output"],
instances:
LIST [
[actual: "gate: Input, ch1: Vdd, ch2: Output",
type: MakeTransistor[context: context, stackType: pE]],
[actual: "gate: Input, ch1: Output, ch2: Gnd",
type: MakeTransistor[context: context, stackType: nE]]]];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: InverterRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
InverterRoseClass: ROPE = Rosemary.Register[roseClassName: Inverter, init: InverterInit, evalSimple: InverterSimple];
InverterInit: Rosemary.InitProc = {
p[InverterOutput].d ← drive;
};
InverterSimple: Rosemary.EvalProc = {
p[InverterOutput].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;
};
TristateBuffer:
ROPE = RegisterStructureProc[name: "TristateBuffer", proc: CreateTristateBuffer];
TristateVdd: NAT = 0;
TristateGnd: NAT = 1;
TristatenInput: NAT = 2;
TristateDrive: NAT = 3;
TristatenDrive: NAT = 4;
TristateOutput: NAT = 5;
CreateTristateBuffer: StructureProc = {
pType: Core.CellType;
nType: Core.CellType;
name: ROPE ← WidthRatioNameProc[context: context, prefix: TristateBuffer];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
pType ← MakeTransistor[context: context, stackHeight: 2, stackType: pE];
nType ← MakeTransistor[context: context, stackHeight: 2, stackType: nE];
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, nInput, Drive, nDrive, Output"],
onlyInternal: CreateWires[context, "pstack, nstack"],
instances:
LIST [
[actual: "gate: nInput, ch1: Vdd, ch2: pstack", type: pType],
[actual: "gate: nDrive, ch1: pstack, ch2: Output", type: pType],
[actual: "gate: Drive, ch1: Output, ch2: nstack", type: nType],
[actual: "gate: nInput, ch1: nstack, ch2: Gnd", type: nType]]];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: TristateRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
TristateRoseClass: ROPE = Rosemary.Register[roseClassName: TristateBuffer, init: TristateInit, evalSimple: TristateSimple];
TristateInit: Rosemary.InitProc = {
FOR port:
NAT
IN [0..p.size)
DO
p[port].type ← b;
ENDLOOP;
};
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[TristateOutput].d ← IF p[TristateDrive].b OR NOT p[TristatenDrive].b THEN drive ELSE none;
p[TristateOutput].b ← NOT p[TristatenInput].b;
};
NAnd:
ROPE = RegisterStructureProc[name: "NAnd", proc: CreateNAnd];
NAndVdd: NAT = 0;
NAndGnd: NAT = 1;
NAndInput: NAT = 2;
NAndnOutput: NAT = 3;
CreateNAnd: StructureProc = {
inputCount: NAT;
pType: Core.CellType;
nType: Core.CellType;
instances: InstanceList ← NIL;
name: ROPE ← CountWidthRatioNameProc[context: context, prefix: NAnd];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
inputCount ← GetInt[context: context, prop: $SSIInputCount];
pType ← MakeTransistor[context: context, stackType: pE];
nType ← MakeTransistor[context: context, stackHeight: inputCount, stackType: nE];
FOR input:
NAT
IN [0..inputCount)
DO
instances ←
CONS[[
actual: IO.PutFR["gate: Input[%g], ch1: Vdd, ch2: nOutput", IO.int[input]],
type: pType],
instances];
instances ←
CONS[[
actual:
IO.PutFR["gate: Input[%g], ch1: %g, ch2: %g",
IO.int[input],
IF input=0
THEN
IO.rope["nOutput"]
ELSE IO.rope[IO.PutFR["stack[%g]", IO.int[input-1]]],
IF input=inputCount-1
THEN
IO.rope["Gnd"]
ELSE IO.rope[IO.PutFR["stack[%g]", IO.int[input]]]],
type: nType],
instances];
ENDLOOP;
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], nOutput"],
onlyInternal: CreateWires[context, "stack[SEQ: SSIInputCount-1]"],
instances: instances];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: NAndRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
NAndRoseClass: ROPE = Rosemary.Register[roseClassName: NAnd, init: NAndInit, evalSimple: NAndSimple];
NAndInit: Rosemary.InitProc = {
p[NAndVdd].type ← b;
p[NAndGnd].type ← b;
FOR input:
NAT
IN [0..p[NAndInput].size)
DO
p[NAndInput][input].type ← b;
ENDLOOP;
p[NAndnOutput].type ← b;
p[NAndnOutput].d ← drive;
};
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;
};
And:
ROPE = RegisterStructureProc[name: "And", proc: CreateAnd];
AndVdd: NAT = 0;
AndGnd: NAT = 1;
AndInput: NAT = 2;
AndOutput: NAT = 3;
CreateAnd: StructureProc = {
name: ROPE ← CountWidthRatioNameProc[context: context, prefix: And];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], Output"],
onlyInternal: CreateWires[context, "nOutput"],
instances:
LIST [
[type: CreateStructure[name: "NAnd", context: context]], -- fix this to scale nand to inverter gate cap.
[type: CreateStructure[name: "Inverter", context: context], actual: "Input: nOutput"]]];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: AndRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
AndRoseClass: ROPE = Rosemary.Register[roseClassName: And, init: AndInit, evalSimple: AndSimple];
AndInit: Rosemary.InitProc = {
p[AndVdd].type ← b;
p[AndGnd].type ← b;
FOR input:
NAT
IN [0..p[AndInput].size)
DO
p[AndInput][input].type ← b;
ENDLOOP;
p[AndOutput].type ← b;
p[AndOutput].d ← 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;
};
NOr:
ROPE = RegisterStructureProc[name: "NOr", proc: CreateNOr];
NOrVdd: NAT = 0;
NOrGnd: NAT = 1;
NOrInput: NAT = 2;
NOrnOutput: NAT = 3;
CreateNOr: StructureProc = {
inputCount: NAT;
pType: Core.CellType;
nType: Core.CellType;
instances: InstanceList ← NIL;
name: ROPE ← CountWidthRatioNameProc[context: context, prefix: NOr];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
inputCount ← GetInt[context: context, prop: $SSIInputCount];
pType ← MakeTransistor[context: context, stackType: pE, stackHeight: inputCount];
nType ← MakeTransistor[context: context, stackType: nE];
FOR input:
NAT
IN [0..inputCount)
DO
instances ←
CONS[[
actual:
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]]]],
type: pType],
instances];
instances ←
CONS[[
actual: IO.PutFR["gate: Input[%g], ch1: nOutput, ch2: Gnd", IO.int[input]],
type: nType],
instances];
ENDLOOP;
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], nOutput"],
onlyInternal: CreateWires[context, "stack[SEQ: SSIInputCount-1]"],
instances: instances];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: NOrRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
NOrRoseClass: ROPE = Rosemary.Register[roseClassName: NOr, init: NOrInit, evalSimple: NOrSimple];
NOrInit: Rosemary.InitProc = {
p[NOrVdd].type ← b;
p[NOrGnd].type ← b;
FOR input:
NAT
IN [0..p[NOrInput].size)
DO
p[NOrInput][input].type ← b;
ENDLOOP;
p[NOrnOutput].type ← b;
p[NOrnOutput].d ← drive;
};
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;
};
Or:
ROPE = RegisterStructureProc[name: "Or", proc: CreateOr];
OrVdd: NAT = 0;
OrGnd: NAT = 1;
OrInput: NAT = 2;
OrOutput: NAT = 3;
CreateOr: StructureProc = {
inputCount: NAT;
name: ROPE ← CountWidthRatioNameProc[context: context, prefix: Or];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
inputCount ← GetInt[context: context, prop: $SSIInputCount];
cellType ← CreateRecordCell[
context: context,
name: name,
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], Output"],
onlyInternal: CreateWires[context, "nInput[SEQ: SSIInputCount]"],
instances:
LIST [
[type: CreateStructure[name: "InverterSeq", context: context],
actual: "Input: Input, Output: nInput"],
[type: CreateStructure[name: "NAnd", context: context],
actual: "Input: nInput, nOutput: Output"]]];
IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: OrRoseClass];
CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]];
Insert[name, cellType];
};
OrRoseClass: ROPE = Rosemary.Register[roseClassName: Or, init: OrInit, evalSimple: OrSimple];
OrInit: Rosemary.InitProc = {
p[OrVdd].type ← b;
p[OrGnd].type ← b;
FOR input:
NAT
IN [0..p[OrInput].size)
DO
p[OrInput][input].type ← b;
ENDLOOP;
p[OrOutput].type ← b;
p[OrOutput].d ← 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;
};
InverterSeq:
ROPE = RegisterStructureProc[name: "InverterSeq", proc: CreateInverterSeq];
CreateInverterSeq: StructureProc = {
name: ROPE ← CountWidthRatioNameProc[context: context, prefix: InverterSeq];
IF (cellType ← Lookup[name])#NIL THEN RETURN;
cellType ← CoreCompose.CreateSequenceCell[
name: name,
baseCell: CreateStructure[name: "Inverter", context: context],
count: GetInt[context: context, prop: $SSIInputCount]];
Insert[name, cellType];
};
RegisterIntProperty[prop: $SSIInputCount];
RegisterIntProperty[prop: $SSIWidth];
RegisterRealProperty[prop: $SSIRatio];
END.