<> <> <> <> <> <<>> 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.