<> <> <> <<>> DIRECTORY ChipCreate, IO, RealOps, Rope, CoreSSI, CoreTransistor; CoreSSIImpl: CEDAR PROGRAM IMPORTS ChipCreate, IO, RealOps, Rope, CoreTransistor EXPORTS CoreSSI = BEGIN OPEN ChipCreate, CoreSSI; fileRoot: ROPE _ "SSI"; CreateInverter: PUBLIC PROC [design: Design, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { name: ROPE _ WidthRatioNameProc["Inverter", width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { p: CellType _ TransistorType[design: design, stackType: pE, width: width, ratio: ratio]; n: CellType _ TransistorType[design: design, width: width, ratio: ratio]; ct _ CreateCellType[design: design, cellTypeName: name]; CreatePort[on: ct, name: "Vdd", pin: [top, 0]]; CreatePort[on: ct, name: "Gnd", pin: [bottom, 0]]; CreatePort[on: ct, name: "Input", pin: [left, 0]]; CreatePort[on: ct, name: "Output", pin: [right, 0], attributes: LIST[[$StcOut, NIL]]]; CreateCell[in: ct, type: p, bind: "gate: Input, ch1: Vdd, ch2: Output"]; CreateCell[in: ct, type: n, bind: "gate: Input, ch1: Output, ch2: Gnd"]; }; }; CreateTristateBuffer: PUBLIC PROC [design: Design, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { class: ROPE _ "TristateBuffer"; name: ROPE _ WidthRatioNameProc[class, width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { p: CellType _ TransistorType[design: design, stackHeight: 2, stackType: pE, width: width, ratio: ratio]; n: CellType _ TransistorType[design: design, stackHeight: 2, width: width, ratio: ratio]; ct _ CreateCellType[design: design, cellTypeName: name, attributes: LIST[[$Behave, class], [$BhvFileRoot, fileRoot]]]; CreatePort[on: ct, name: "Vdd"]; CreatePort[on: ct, name: "Gnd"]; CreatePort[on: ct, name: "nInput"]; CreatePort[on: ct, name: "Drive"]; CreatePort[on: ct, name: "nDrive"]; CreatePort[on: ct, name: "Output", attributes: LIST[[$StcTristate, NIL]]]; CreateNet[in: ct, name: "pstack"]; CreateNet[in: ct, name: "nstack"]; CreateCell[in: ct, type: p, bind: "gate: nInput, ch1: Vdd, ch2: pstack"]; CreateCell[in: ct, type: p, bind: "gate: nDrive, ch1: pstack, ch2: Output"]; CreateCell[in: ct, type: n, bind: "gate: Drive, ch1: Output, ch2: nstack"]; CreateCell[in: ct, type: n, bind: "gate: nInput, ch1: nstack, ch2: Gnd"]; }; }; WidthRatioNameProc: PROC [prefix: ROPE, width: NAT, ratio: REAL] RETURNS [name: ROPE] = { formatName: ROPE _ Rope.Cat[prefix, "%g*%g"]; name _ IO.PutFR[formatName, IO.int[width], IO.real[ratio]]; }; NAndArgsRef: TYPE = REF NAndArgsRec; NAndArgsRec: TYPE = RECORD[inputCount: NAT _ 2]; CreateNAnd: PUBLIC PROC [design: Design, inputCount: NAT _ 2, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { class: ROPE _ "NAnd"; name: ROPE _ CountWidthRatioNameProc[class, inputCount, width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { p: CellType _ TransistorType[design: design, stackType: pE, width: width, ratio: ratio]; n: CellType _ TransistorType[design: design, stackHeight: inputCount, width: width, ratio: ratio]; ct _ CreateRecordCellType[design: design, cellTypeName: name, attributes: LIST[[$Behave, class], [$BhvFileRoot, fileRoot], [$BhvArgs, NEW[NAndArgsRec _ [inputCount: inputCount]]]]]; NPortStackProc[ct: ct, inputCount: inputCount]; FOR input: NAT IN [0..inputCount) DO CreateCell[in: ct, type: p, bind: IO.PutFR["gate: Input[%g], ch1: Vdd, ch2: nOutput", IO.int[input]]]; CreateCell[in: ct, type: n, bind: IO.PutFR["gate: Input[%g], ch1: %g, ch2: %g", IO.int[input], IF input=0 THEN IO.rope["nOutput"] ELSE IO.rope[IO.PutFR["nstack%g", IO.int[input-1]]], IF input=inputCount-1 THEN IO.rope["Gnd"] ELSE IO.rope[IO.PutFR["nstack%g", IO.int[input]]]]]; ENDLOOP; }; }; CreateAnd: PUBLIC PROC [design: Design, inputCount: NAT _ 2, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { name: ROPE _ CountWidthRatioNameProc["And", inputCount, width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { inputSeq: NetType _ CreateSequenceNetType[design: design, count: inputCount]; nand: CellType _ CreateNAnd[design: design, inputCount: inputCount, width: width, ratio: ratio]; -- fix this to scale nand to inverter gate cap. invert: CellType _ CreateInverter[design: design, width: width, ratio: ratio]; ct _ CreateCellType[design: design, cellTypeName: name]; CreatePort[on: ct, name: "Vdd"]; CreatePort[on: ct, name: "Gnd"]; CreatePort[on: ct, name: "Input", type: inputSeq]; CreatePort[on: ct, name: "Output", attributes: LIST[[$StcOut, NIL]]]; CreateNet[in: ct, name: "nOutput"]; CreateCell[in: ct, type: nand]; CreateCell[in: ct, type: invert, bind: "Input: nOutput"]; }; }; CreateNOr: PUBLIC PROC [design: Design, inputCount: NAT _ 2, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { name: ROPE _ CountWidthRatioNameProc["NOr", inputCount, width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { p: CellType _ TransistorType[design: design, stackHeight: inputCount, stackType: pE, width: width, ratio: ratio]; n: CellType _ TransistorType[design: design, width: width, ratio: ratio]; ct _ CreateCellType[design: design, cellTypeName: name]; NPortStackProc[ct: ct, inputCount: inputCount]; FOR input: NAT IN [0..inputCount) DO CreateCell[in: ct, type: p, bind: 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]]]]]; CreateCell[in: ct, type: n, bind: IO.PutFR["gate: Input[%g], ch1: nOutput, ch2: Gnd", IO.int[input]]]; ENDLOOP; }; }; CreateOr: PUBLIC PROC [design: Design, inputCount: NAT _ 2, width: NAT _ 4, ratio: REAL _ 2.5] RETURNS [ct: CellType] = { name: ROPE _ CountWidthRatioNameProc["And", inputCount, width, ratio]; IF (ct _ LookupCellType[design, name])=NIL THEN { inputSeq: NetType _ CreateSequenceNetType[design: design, count: inputCount]; invertSeq: CellType _ CreateSequenceCellType[design: design, baseCellType: CreateInverter[design: design, width: 4, ratio: ratio], axis: y, count: inputCount]; nand: CellType _ CreateNAnd[design: design, inputCount: inputCount, width: width, ratio: ratio]; bindRope: ROPE _ NIL; ct _ CreateCellType[design: design, cellTypeName: name]; CreatePort[on: ct, name: "Vdd"]; CreatePort[on: ct, name: "Gnd"]; CreatePort[on: ct, name: "Input", type: inputSeq]; CreatePort[on: ct, name: "Output", attributes: LIST[[$StcOut, NIL]]]; CreateNet[in: ct, name: "nInput", type: inputSeq]; CreateCell[in: ct, type: invertSeq, bind: "Input: Input, Output: nInput"]; CreateCell[in: ct, type: nand, bind: "Input: nInput, nOutput: Output"]; }; }; NPortStackProc: PROC [ct: CellType, inputCount: NAT] = { inputSeq: NetType _ CreateSequenceNetType[design: design, count: inputCount]; CreatePort[on: ct, name: "Vdd"]; CreatePort[on: ct, name: "Gnd"]; CreatePort[on: ct, name: "Input", type: inputSeq]; FOR input: NAT IN [0..inputCount-1) DO CreateNet[in: ct, name: IO.PutFR["stack%g", IO.int[input]]]; ENDLOOP; CreatePort[on: ct, name: "nOutput", attributes: LIST[[$StcOut, NIL]]]; }; CountWidthRatioNameProc: PROC [prefix: ROPE, inputCount: NAT, width: NAT, ratio: REAL] RETURNS [name: ROPE] = { formatName: ROPE _ Rope.Cat[prefix, "%g*%g*%g"]; name _ IO.PutFR[formatName, IO.int[inputCount], IO.int[width], IO.real[ratio]]; }; TransistorType: PROC [design: Design, stackHeight: NAT _ 1, stackType: Transistor.TransistorType _ nE, width: NAT, ratio: REAL] RETURNS [t: CellType] = { tWidth: NAT _ stackHeight * width; IF stackType = pE THEN tWidth _ RealOps.RoundLI[RealOps.Float[tWidth] * ratio, [round: rp]]; t _ Transistor.CreateTransistor[design: design, type: stackType, width: tWidth]; }; END.