<> <> <> <> <> <<>> DIRECTORY Basics, CD, CDPinObjects, Core, CoreClasses, CoreCompose, CoreFlatten, CoreOps, CoreProperties, IO, PW, PWCore, PWPins, Rope, Rosemary, Sinix; CrossRAMDecoder: CEDAR PROGRAM IMPORTS Basics, CDPinObjects, CoreCompose, CoreFlatten, CoreProperties, IO, PW, PWCore, PWPins, Rope, Rosemary, Sinix = BEGIN OPEN CoreCompose; Wire: TYPE = Core.Wire; <> Decoder: ROPE = RegisterStructureProc[name: "Decoder", proc: CreateDecoder]; CreateDecoder: StructureProc = { rowQuads: INT _ GetInt[context, $rowQuads]; rowPairs: INT _ 2*rowQuads; nRopesVdd: ROPE _ "Vdd"; nRopesGnd: ROPE _ "Gnd"; FOR row: INT IN (0 .. rowPairs) DO nRopesVdd _ Rope.Cat[nRopesVdd, ", Vdd"]; ENDLOOP; FOR row: INT IN (0 .. rowPairs) DO nRopesGnd _ Rope.Cat[nRopesGnd, ", Gnd"]; ENDLOOP; RegisterIntProperty[prop: $andDecoderBits]; RegisterIntProperty[prop: $rowPairs]; PushInt[context: context, prop: $andDecoderBits, val: GetInt[context, $addressDecoderBits]-1]; PushInt[context: context, prop: $rowPairs, val: rowPairs]; cellType _ CreateRecordCell[ name: Decoder, context: context, public: CreateWires[context, "Vdd, Gnd, VddMiddle, VddRight, GndLeft, GndMiddle, AccessB, AdrBit[seq: addressDecoderBits], nAdrBit[seq: addressDecoderBits], Word[seq: 4*rowQuads]"], onlyInternal: CreateWires[context, "nDecode[seq: 2*rowQuads]"], instances: LIST [ [type: CreateStructure[name: "DecoderLeftColumn", context: context]], [type: CreateStructure[name: "DecoderAndPlane", context: context], actual: IO.PutFR["Vdd: [%g], Gnd: [%g], AdrBit: AdrBit[start: 0, len: andDecoderBits], nAdrBit: nAdrBit[start: 0, len: andDecoderBits], nDecodeVdd: nDecode, nDecodeGnd: nDecode", IO.rope[nRopesVdd], IO.rope[nRopesGnd]]], [type: CreateStructure[name: "DecoderRightColumn", context: context], actual: IO.PutFR["Vdd: [%g]", IO.rope[nRopesVdd]]], [type: CreateStructure[name: "DecoderLogicColumn", context: context], actual: "Vdd: VddMiddle, VddLeft: Vdd, Gnd: GndMiddle, TreeSelect: [AdrBit[addressDecoderBits-1], nAdrBit[addressDecoderBits-1]]"] ] ]; IF GetBool[context, $PWCore] THEN PWCore.SetAbutX[cellType: cellType]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> <> DecoderRow: ROPE = RegisterStructureProc[name: "DecoderRow", proc: CreateDecoderRow]; CreateDecoderRow: StructureProc = { andDecoderBits: INT _ GetInt[context, $andDecoderBits]; row: INT _ GetInt[context, $row]; design: CD.Design _ NARROW[GetRef[context, $sourceCDDesign]]; dec0: PW.Object _ PW.Get[design, "DecoderZero"]; dec1: PW.Object _ PW.Get[design, "DecoderOne"]; DecoderSelect: PW.XYFunction ={ RenameEach: PWPins.ChangePinProc = { name: ROPE _ CDPinObjects.GetName[oldPin]; SELECT TRUE FROM Rope.Equal[name, "nDecodeGnd"] OR Rope.Equal[name, "nDecodeVdd"] OR Rope.Equal[name, "Vdd"] OR Rope.Equal[name, "Gnd"] => newPin _ PWPins.CopyInstance[oldPin]; Rope.Equal[name, "AdrBit"] OR Rope.Equal[name, "nAdrBit"] => { newPin _ PWPins.CopyInstance[oldPin]; CDPinObjects.SetName[newPin, Rope.Cat[name, "[", IO.PutR[IO.int[x]], "]"]]; }; ENDCASE => ERROR; }; oddBit: BOOL _ PW.XthBitOfN[x, row]; resultingOb _ IF oddBit THEN dec1 ELSE dec0; resultingOb _ PWPins.ChangePins[NIL, resultingOb, RenameEach]; }; actual: ROPE _ "Input: ["; FOR bit: INT IN [0 .. andDecoderBits) DO actual _ Rope.Cat[actual, IO.PutFR["%gAdrBit[%g]", IO.rope[IF Basics.BITAND[Basics.BITSHIFT[row, bit-andDecoderBits+1], 1]#0 THEN NIL ELSE "n"], IO.int[bit]]]; IF bit> [type: CreateStructure[name: "NAnd", context: context], actual: Rope.Cat[actual, "], nOutput: nDecodeGnd"]], <> [type: CreateStructure[name: "NAnd", context: context], actual: Rope.Cat[actual, "], nOutput: nDecodeVdd"]] ] ]; IF GetBool[context, $PWCore] THEN PWCore.SetLayout[cellType, PWCore.LabelPins[cellType.public, PW.MapFunctionX[NIL, DecoderSelect, 0, andDecoderBits]]]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> <> DecoderAndPlane: ROPE = RegisterStructureProc[name: "DecoderAndPlane", proc: CreateDecoderAndPlane]; CreateDecoderAndPlane: StructureProc = { rowPairs: INT _ GetInt[context, $rowPairs]; andDecoderBits: INT _ GetInt[context, $andDecoderBits]; instances: InstanceList _ NIL; RegisterIntProperty[prop: $row]; PushInt[context: context, prop: $SSIInputCount, val: GetInt[context, $andDecoderBits]]; PushInt[context: context, prop: $SSIWidth, val: 4]; PushReal[context: context, prop: $SSIRatio, val: 2.5]; FOR row: INT IN [0..rowPairs) DO -- decreasing? PushInt[context: context, prop: $row, val: row]; instances _ CONS[ [actual: IO.PutFLR["Vdd: Vdd[%g], Gnd: Gnd[%g], nDecodeVdd: nDecodeVdd[%g], nDecodeGnd: nDecodeGnd[%g]", LIST [IO.int[row], IO.int[row], IO.int[row], IO.int[row]]], type: CreateStructure[name: "DecoderRow", context: context]], instances]; ENDLOOP; cellType _ CreateRecordCell[ name: DecoderAndPlane, context: context, public: CreateWires[context, "Vdd[seq: rowPairs], Gnd[seq: rowPairs], AdrBit[seq: andDecoderBits], nAdrBit[seq: andDecoderBits], nDecodeVdd[seq: rowPairs], nDecodeGnd[seq: rowPairs]"], instances: instances]; IF GetBool[context, $PWCore] THEN PWCore.SetAbutFlipY[cellType: cellType, flip: FALSE]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <<>> <> DecoderLeftColumn: ROPE = RegisterStructureProc[name: "DecoderLeftColumn", proc: CreateDecoderLeftColumn]; CreateDecoderLeftColumn: StructureProc = { cellType _ CreateSequenceCell[ name: DecoderLeftColumn, baseCell: CreateStructure[name: DecoderLeftPair, context: context], count: GetInt[context: context, prop: $rowQuads]]; IF GetBool[context, $PWCore] THEN PWCore.SetArrayY[cellType: cellType]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderLeftPair: ROPE = RegisterStructureProc[name: "DecoderLeftPair", proc: CreateDecoderLeftPair]; CreateDecoderLeftPair: StructureProc = { decoderLeft: Core.CellType _ CreateStructure[name: "DecoderLeft", context: context]; cellType _ CreateRecordCell[ name: DecoderLeftPair, context: context, public: CreateWires[context, "Vdd, Gnd"], instances: LIST [ [type: decoderLeft], [type: decoderLeft]]]; IF GetBool[context, $PWCore] THEN PWCore.SetAbutFlipY[cellType: cellType, flip: FALSE]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderLeft: ROPE = RegisterStructureProc[name: "DecoderLeft", proc: CreateDecoderLeft]; CreateDecoderLeft: StructureProc = { cellType _ CreateRecordCell[ name: DecoderLeft, context: context, public: CreateWires[context, "Vdd, Gnd"]]; IF GetBool[context, $PWCore] THEN PWCore.SetGet[cellType: cellType, source: NARROW[GetRef[context, $sourceCDDesign]]]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderRightColumn: ROPE = RegisterStructureProc[name: "DecoderRightColumn", proc: CreateDecoderRightColumn]; CreateDecoderRightColumn: StructureProc = { cellType _ CreateSequenceCell[ name: DecoderRightColumn, baseCell: CreateStructure[name: "DecoderRightPair", context: context], count: GetInt[context: context, prop: $rowQuads], sequencePorts: "nDecode, Vdd"]; IF GetBool[context, $PWCore] THEN PWCore.SetArrayY[cellType: cellType]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderRightPair: ROPE = RegisterStructureProc[name: "DecoderRightPair", proc: CreateDecoderRightPair]; CreateDecoderRightPair: StructureProc = { decoderRight: Core.CellType _ CreateStructure[name: "DecoderRight", context: context]; cellType _ CreateRecordCell[ name: DecoderRightPair, context: context, public: CreateWires[context, "Vdd[seq: 2], nDecode[seq: 2]"], instances: LIST [ [actual: "Vdd: Vdd[0], nDecode: nDecode[0]", type: decoderRight], [actual: "Vdd: Vdd[1], nDecode: nDecode[1]", type: decoderRight]]]; IF GetBool[context, $PWCore] THEN PWCore.SetAbutFlipY[cellType: cellType, flip: FALSE]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderRight: ROPE = RegisterStructureProc[name: "DecoderRight", proc: CreateDecoderRight]; CreateDecoderRight: StructureProc = { cellType _ CreateRecordCell[ name: DecoderRight, context: context, public: CreateWires[context, "Vdd, nDecode"]]; IF GetBool[context, $PWCore] THEN PWCore.SetGet[cellType: cellType, source: NARROW[GetRef[context, $sourceCDDesign]]]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderLogicColumn: ROPE = RegisterStructureProc[name: "DecoderLogicColumn", proc: CreateDecoderLogicColumn]; CreateDecoderLogicColumn: StructureProc = { cellType _ CreateSequenceCell[ name: DecoderLogicColumn, baseCell: CreateStructure[name: DecoderLogicPair, context: context], count: GetInt[context: context, prop: $rowQuads], sequencePorts: "nDecode, Word"]; IF GetBool[context, $PWCore] THEN PWCore.SetArrayY[cellType: cellType]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderLogicPair: ROPE = RegisterStructureProc[name: "DecoderLogicPair", proc: CreateDecoderLogicPair]; CreateDecoderLogicPair: StructureProc = { decoderLogic: Core.CellType _ CreateStructure[name: "DecoderLogic", context: context]; data: CoreClasses.RecordCellType; cellType _ CreateRecordCell[ name: DecoderLogicPair, context: context, public: CreateWires[context, "VddLeft, Vdd, VddRight, GndLeft, Gnd, AccessB, TreeSelect[seq: 2], nDecode[seq: 2], Word[seq: 4]"], instances: LIST [ [actual: "Word: Word[start: 0, len: 2], nDecode: nDecode[0]", type: decoderLogic], [actual: "Word: Word[start: 2, len: 2], nDecode: nDecode[1]", type: decoderLogic]]]; data _ NARROW [cellType.data]; IF GetBool[context, $PWCore] THEN PWCore.SetAbutFlipY[cellType: cellType, flip: FALSE]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> DecoderLogic: ROPE = RegisterStructureProc[name: "DecoderLogic", proc: CreateDecoderLogic]; CreateDecoderLogic: StructureProc = { cellType _ CreateSequenceCell[ name: DecoderLogic, baseCell: CreateStructure[name: WordDriver, context: context], count: 2, sequencePorts: "TreeSelect, Word"]; IF GetBool[context, $PWCore] THEN PWCore.SetGet[cellType: cellType, source: NARROW[GetRef[context, $sourceCDDesign]]]; IF GetBool[context, $Sinix] THEN [] _ Sinix.Extract[PWCore.GetLayout[cellType]]; }; <> WordDriver: ROPE = RegisterStructureProc[name: "WordDriver", proc: CreateWordDriver]; CreateWordDriver: StructureProc = { instances: InstanceList _ LIST [ [actual: "gate: TreeSelect, ch1: nDecode, ch2: nTreeDecode", type: CreateTransistor[name: "Transistor", type: nE]], [actual: "gate: TreeSelect, ch1: Vdd, ch2: nTreeDecode", type: CreateTransistor[name: "Transistor", type: pE]]]; PushInt[context: context, prop: $SSIInputCount, val: 2]; PushInt[context: context, prop: $SSIWidth, val: 4]; PushReal[context: context, prop: $SSIRatio, val: 2.5]; instances _ CONS[[ actual: "Input: nTreeDecode, Output: Decode", type: CreateStructure[name: "Inverter", context: context]], instances]; instances _ CONS[[ actual: "Input: [AccessB, Decode], Output: Word", type: CreateStructure[name: "And", context: context]], instances]; cellType _ CreateRecordCell[ name: WordDriver, context: context, public: CreateWires[context, "VddLeft, Vdd, VddRight, GndLeft, Gnd, AccessB, TreeSelect, Word, nDecode"], onlyInternal: CreateWires[context, "nTreeDecode, Decode"], instances: instances]; IF GetBool[context, $Rosemary] THEN Rosemary.Bind[cellType: cellType, roseClassName: WordDriverRoseClass]; CoreProperties.PutCellTypeProp[on: cellType, prop: CoreFlatten.CoreFlattenCutSets, value: LIST["JustAboveTransistors"]]; }; WordDriverRoseClass: ROPE = Rosemary.Register[roseClassName: WordDriver, init: WordDriverInit, evalSimple: WordDriverSimple]; VddLeft: NAT = 0; Vdd: NAT = 1; VddRight: NAT = 2; GndLeft: NAT = 3; Gnd: NAT = 4; AccessB: NAT = 5; TreeSelect: NAT = 6; Word: NAT = 7; nDecode: NAT = 8; WordDriverInit: Rosemary.InitProc = { FOR port: NAT IN [0..p.size) DO p[port].type _ b; ENDLOOP; p[Word].d _ drive; }; WordDriverSimple: Rosemary.EvalProc = { IF NOT p[VddLeft].b OR NOT p[Vdd].b OR NOT p[VddRight].b THEN SIGNAL Rosemary.Stop[]; IF p[GndLeft].b OR p[Gnd].b THEN SIGNAL Rosemary.Stop[]; p[Word].b _ p[TreeSelect].b AND p[AccessB].b AND NOT p[nDecode].b; }; END.