<> <> <> <> <<>> DIRECTORY CD, CMos, CMosContacts, PW, PWPins, Onion, Rope; CrossRAMGen: CEDAR PROGRAM IMPORTS CMos, CMosContacts, PW, PWPins, Onion, Rope = BEGIN OPEN PW; ROPE: TYPE = Rope.ROPE; MakeCrossRAM: UserProc = { SetDefaultSource[design, OpenDesign["///Users/Barth.pa/CrossRAM/CrossRAMCellLibrary.dale"]]; RETURN[MakeRAM[design]]; }; MakeRAM: PROC [design: Design] RETURNS [crossRAM: ObPtr]= { rowQuads: INT = 60; columnOcts: INT = 15; decoder, array, right, top: ObPtr; CrossRamPadFrame: ObPtr _ PW.Get[design, "CrossRamPadFrame"]; RightPower: ObPtr _ PW.Get[design, "RightPower"]; result: ObPtr; params: Onion.LayersParameters _ NEW[Onion.LayersParametersRec _ [radialLayer: CMos.met, ringLayer: CMos.met2, ringWidth: Onion.RingWidthIs8, contact: CMosContacts.CreateMmCon[10], ringRingDist: 8, wireExtendProc: Onion.WireExtendMetToMet]]; rows: INT = 4*rowQuads; ndecoderCols: INT _ IF rows=TwoToTheLog2[rows] THEN Log2[rows] ELSE Log2[rows]+1; ndecoderCols _ ndecoderCols-1; -- one bit goes to tree decoder IF EVEN[ndecoderCols] THEN ERROR; -- decoder drivers always come in pairs decoder _ MakeDecoder[design, rowQuads, ndecoderCols]; array _ RAMArray[design, rowQuads, columnOcts]; right _ ArrayY[design, RightPower, 2*rowQuads]; top _ MakeTop[design, ndecoderCols, columnOcts]; result _ Onion.MakeInner[design, AbutListY[design, LIST[MakeBottom[design, ndecoderCols, columnOcts], AbutX[design, decoder, array, right], top]]]; crossRAM _ Onion.LRSRoute[design, result, CrossRamPadFrame, Onion.Center[result, CrossRamPadFrame], params].cell; }; MakeDecoder: PROC [design: Design, rowQuads, decoderCols: INT] RETURNS [decoder: ObPtr] = { DecoderLogic: ObPtr_ Get[design, "DecoderLogic"]; DecoderLeft: ObPtr_ Get[design, "DecoderLeft"]; DecoderZero: ObPtr_ Get[design, "DecoderZero"]; DecoderOne: ObPtr_ Get[design, "DecoderOne"]; DecoderRight: ObPtr_ Get[design, "DecoderRight"]; flipDecoderZero: ObPtr_ FlipY[design, DecoderZero]; flipDecoderOne: ObPtr_ FlipY[design, DecoderOne]; leftColumn, rightColumn, driverColumn: ObPtr; rowPairs: INT = 2*rowQuads; DecoderFunction: XYFunction = { flip: BOOL = ODD[y]; IF XthBitOfN[decoderCols-1-x, y] THEN RETURN[IF flip THEN flipDecoderOne ELSE DecoderOne] ELSE RETURN[IF flip THEN flipDecoderZero ELSE DecoderZero]; }; leftColumn _ ArrayY[design, AbutY[design, DecoderLeft, FlipY[design, DecoderLeft]], rowQuads]; rightColumn _ ArrayY[design, AbutY[design, DecoderRight, FlipY[design, DecoderRight]], rowQuads]; driverColumn _ ArrayY[design, AbutY[design, DecoderLogic, FlipY[design, DecoderLogic]], rowQuads]; decoder _ AbutListX[design, LIST[leftColumn, MapFunction[design, DecoderFunction, 0, decoderCols, 0, rowPairs], rightColumn, driverColumn]]; }; RAMArray: PROC [design: Design, rowQuads, columnOcts: INT] RETURNS [array: ObPtr] = { SubArray: PROC [dataName, stitchName: ROPE] RETURNS [array: ObPtr] = { dataCell: ObPtr_ Get[design, dataName]; stitchCell: ObPtr_ Get[design, stitchName]; <> <> <> prestitch: ObPtr _ ArrayX[design, ArrayY[design, ArrayX[design, ArrayY[design, ArrayX[design, dataCell, 2], 2], 2], 2], 2]; withstitch: ObPtr _ AbutX[design, prestitch, ArrayY[design, stitchCell, 4]]; array _ ArrayX[design, ArrayY[design, ArrayX[design, ArrayY[design, withstitch, 3], 3], 5], 5]; }; IF rowQuads#60 OR columnOcts#15 THEN ERROR; array _ AbutY[design, SubArray["SRamTwoBits", "SRamStitch"], SubArray["DRamTwoBits", "DRamStitch"]]; }; MakeBottom: PROC [design: Design, decoderCols, dataOcts: INT] RETURNS [bottom: ObPtr] = { PrechargeSlice: ObPtr _ Get[design, "PrechargeSlice"]; PrechargeStich: ObPtr _ Get[design, "PrechargeStich"]; BottomDecoderLeft: ObPtr _ Get[design, "BottomDecoderLeft"]; BottomDecoder: ObPtr _ Get[design, "BottomDecoder"]; BottomDecoderRight: ObPtr _ Get[design, "BottomDecoderRight"]; BottomRight: ObPtr _ Get[design, "BottomRight"]; precharge: ObPtr _ ArrayX[design, AbutX[design, ArrayX[design, PrechargeSlice, 8], PrechargeStich], dataOcts]; bottomDecoder: ObPtr _ ArrayX[design, BottomDecoder, decoderCols]; bottom _ AbutListX[design, LIST[BottomDecoderLeft, bottomDecoder, BottomDecoderRight, precharge, BottomRight]]; }; MakeTop: PROC [design: Design, decoderCols, dataOcts: INT] RETURNS [top: ObPtr] = { listOb: PW.ListOb _ NIL; DecoderDriverLeft: ObPtr_ Get[design, "DecoderDriverLeft"]; DecoderDriver: ObPtr_ Get[design, "DecoderDriver"]; DecoderLogicDriver: ObPtr_ Get[design, "DecoderLogicDriver"]; dataBuffer: ObPtr_ MakeDataBuffer[design, dataOcts]; DataBufferRight: ObPtr_ Get[design, "DataBufferRight"]; stackDriverCount: INT _ (decoderCols+1)/2-1; stackDriver: ObPtr _ Inst[design, DecoderDriver, LIST["RemoveForStackDecoderBit"]]; treeDriver: ObPtr _ Inst[design, DecoderDriver, LIST["RemoveForTreeDecoderBit"]]; drivers: ObPtr _ treeDriver; IF stackDriverCount>0 THEN { listOb _ CONS[drivers, listOb]; FOR i: INT _ 0, i+2 UNTIL i>=2*stackDriverCount DO RenameData: PWPins.RenameProc = { IF Rope.Equal[oldRope, "add[3]"] THEN newRope _ PWPins.Index["add", i+5]; IF Rope.Equal[oldRope, "add[4]"] THEN newRope _ PWPins.Index["add", i+6]; }; listOb _ CONS[PWPins.RenamePins[design, stackDriver, RenameData], listOb]; ENDLOOP; drivers _ AbutListX[design, listOb]; }; top _ AbutListX[design, LIST[DecoderDriverLeft, drivers, DecoderLogicDriver, dataBuffer, DataBufferRight]] }; MakeDataBuffer: PROC [design: Design, dataOcts: INT] RETURNS [top: ObPtr] = { bitsPerDecoder: INT = 8; listOb: PW.ListOb _ NIL; BitDrive, arrayTop, block, BitSelNoPoly, BitSelContact, BitSelPoly, BitLineConnect, BitMux, BitMuxEnd, DecoderStitch:PW.ObPtr; BitConnect: XYFunction ={ IF x>y THEN RETURN[BitSelNoPoly]; IF x=y THEN RETURN[BitSelContact]; IF x