CrossRAMSSI.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, October 27, 1985 4:40:48 pm PST
Louis Monier October 21, 1985 5:26:34 pm PDT
DIRECTORY Core, CoreCompose, IO, RealOps, Rosemary;
CrossRAMSSI: CEDAR PROGRAM
IMPORTS CoreCompose, IO, RealOps, Rosemary
= 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];
};
Inverter: ROPE = RegisterStructureProc[name: "Inverter", proc: CreateInverter];
InverterVdd: NAT = 0;
InverterGnd: NAT = 1;
InverterInput: NAT = 2;
InverterOutput: NAT = 3;
CreateInverter: StructureProc = {
cellType ← CreateRecordCell[
context: context,
name: WidthRatioNameProc[context: context, prefix: Inverter],
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]]]];
Rosemary.Register[cellType: cellType, 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 ← MakeTransistor[context: context, stackHeight: 2, stackType: pE];
nType: Core.CellType ← MakeTransistor[context: context, stackHeight: 2, stackType: nE];
cellType ← CreateRecordCell[
context: context,
name: WidthRatioNameProc[context: context, prefix: TristateBuffer],
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]]];
Rosemary.Register[cellType: cellType, 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 ERROR;
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 ← GetInt[context: context, prop: $SSIInputCount];
pType: Core.CellType ← MakeTransistor[context: context, stackType: pE];
nType: Core.CellType ← MakeTransistor[context: context, stackHeight: inputCount, stackType: nE];
instances: InstanceList ← NIL;
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: CountWidthRatioNameProc[context: context, prefix: NAnd],
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], nOutput"],
onlyInternal: CreateWires[context, "stack[SEQ: SSIInputCount-1]"],
instances: instances];
Rosemary.Register[cellType: cellType, 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 ERROR;
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 = {
cellType ← CreateRecordCell[
context: context,
name: CountWidthRatioNameProc[context: context, prefix: And],
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"]]];
Rosemary.Register[cellType: cellType, 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 ERROR;
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 ← GetInt[context: context, prop: $SSIInputCount];
pType: Core.CellType ← MakeTransistor[context: context, stackType: pE, stackHeight: inputCount];
nType: Core.CellType ← MakeTransistor[context: context, stackType: nE];
instances: InstanceList ← NIL;
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: CountWidthRatioNameProc[context: context, prefix: NOr],
public: CreateWires[context, "Vdd, Gnd, Input[SEQ: SSIInputCount], nOutput"],
onlyInternal: CreateWires[context, "stack[SEQ: SSIInputCount-1]"],
instances: instances];
Rosemary.Register[cellType: cellType, 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 ERROR;
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 ← GetInt[context: context, prop: $SSIInputCount];
cellType ← CreateRecordCell[
context: context,
name: CountWidthRatioNameProc[context: context, prefix: Or],
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"]]];
Rosemary.Register[cellType: cellType, 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 ERROR;
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 = {
cellType ← CoreCompose.CreateSequenceCell[
name: CountWidthRatioNameProc[context: context, prefix: InverterSeq],
baseCell: CreateStructure[name: "Inverter", context: context],
count: GetInt[context: context, prop: $SSIInputCount]];
};
END.