<> <> <> <> <> <<>> DIRECTORY Core, CoreCreate, IO, RealOps, Rosemary, SSI, Ports; SSIImpl: CEDAR PROGRAM IMPORTS CoreCreate, IO, RealOps, Rosemary, Ports EXPORTS SSI = BEGIN OPEN SSI, CoreCreate; WidthRatioNameProc: PROC [prefix: ROPE, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [name: ROPE] = { name _ IO.PutFR["%g%g*%g", IO.rope[prefix], IO.int[width], IO.real[ratio]]; }; CountWidthRatioNameProc: PROC [prefix: ROPE, inputCount: NAT, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [name: ROPE] = { name _ IO.PutFR["%g%g*%g*%g", IO.rope[prefix], IO.int[inputCount], IO.int[width], IO.real[ratio]]; }; MakeTransistor: PROC [stackHeight: NAT _ 1, stackType: TransistorType _ nE, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [t: Core.CellType] = { tWidth: NAT _ stackHeight * width; IF stackType = pE THEN tWidth _ RealOps.RoundLI[RealOps.Float[tWidth] * ratio, [round: rn]]; t _ Transistor[type: stackType, width: tWidth]; }; InverterName: ROPE = Rosemary.Register[roseClassName: "Inverter", evalSimple: InverterSimple]; InverterVdd: NAT = 0; InverterGnd: NAT = 1; InverterInput: NAT = 2; InverternOutput: NAT = 3; Inverter: PUBLIC PROC [w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { ct _ Cell[ name: WidthRatioNameProc[prefix: InverterName, width: w, ratio: r], public: Wires["Vdd", "Gnd", "Input", "nOutput"], instances: LIST [ Instance[MakeTransistor[width: w, ratio: r, stackType: pE], ["gate", "Input"], ["ch1", "Vdd"], ["ch2", "nOutput"]], Instance[MakeTransistor[width: w, ratio: r, stackType: nE], ["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: drive]; }; 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 [w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { pType: Core.CellType _ MakeTransistor[stackHeight: 2, stackType: pE, width: w, ratio: r]; nType: Core.CellType _ MakeTransistor[stackHeight: 2, stackType: nE, width: w, ratio: r]; ct _ Cell[ name: WidthRatioNameProc[prefix: TristateBufferName, width: w, ratio: r], 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, w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { instances: LIST OF CellInstance _ NIL; pType: Core.CellType _ MakeTransistor[stackType: pE, width: w, ratio: r]; nType: Core.CellType _ MakeTransistor[stackHeight: i, stackType: nE, width: w, ratio: r]; 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: CountWidthRatioNameProc[NAndName, i, w, r], 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]; }; 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, w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { ct _ Cell[ name: CountWidthRatioNameProc[AndName, i, w, r], public: Wires["Vdd", "Gnd", Seq["Input", i], "Output"], onlyInternal: Wires["nOutput"], instances: LIST [ Instance[NAnd[i, w, r]], -- fix this to scale nand to inverter gate cap. Instance[Inverter[w, r], ["Input", "nOutput"]]]]; [] _ 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, w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { instances: LIST OF CellInstance _ NIL; pType: Core.CellType _ MakeTransistor[stackType: pE, stackHeight: i, width: w, ratio: r]; nType: Core.CellType _ MakeTransistor[stackType: nE, width: w, ratio: r]; 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: CountWidthRatioNameProc[NOrName, i, w, r], 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]; }; 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, w: NAT _ 4, r: REAL _ 2.5] RETURNS [ct: CellType] = { ct _ Cell[ name: CountWidthRatioNameProc[OrName, i, w, r], public: Wires["Vdd", "Gnd", Seq["Input", i], "Output"], onlyInternal: Wires[Seq["nInput", i]], instances: LIST [ Instance[InverterSeq[i, w, r], ["Input", "Input"], ["nOutput", "nInput"]], Instance[NAnd[i, w, r], ["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 [inputCount: NAT, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { baseCell: CellType _ Inverter[width, ratio]; ct _ SequenceCell[ name: CountWidthRatioNameProc[InverterSeqName, inputCount, width, ratio], baseCell: baseCell, count: inputCount, sequencePorts: Wires[baseCell.public[InverterInput], baseCell.public[InverternOutput]]]; }; END.