<> <> <> DIRECTORY CD, CDCells, CDPinObjects, CMos, Convert, EuControl, EuGen, EUtils, PW, PWCmos, PWDescr, PWPins, Rope; EuGenImplA: CEDAR PROGRAM IMPORTS CDCells, CMos, Convert, EuControl, EuGen, EUtils, PW, PWCmos, PWDescr, PWPins, Rope EXPORTS EuGen = BEGIN OPEN EuGen; <<-- Control descriptors>> ramcdpd: PWDescr.Descriptor; ramcdpu: PWDescr.Descriptor; regscdpd: PWDescr.Descriptor; regscdpu: PWDescr.Descriptor; <<>> <<-- Here starts the layout of the RAM>> RAMGen: PUBLIC PROC [design: CD.Design] RETURNS [ram: PW.ObPtr] = BEGIN <<-- This generates every row of the ram, with the appropriate decoder>> RamDecFn: PW.XYFunction = {dec: PW.ObPtr _ RamRow3Dec[y]; RETURN[IF PW.EVEN[y] THEN PW.AbutX[design, dec, ramRow] ELSE PW.AbutX[design, PW.FlipY[design, dec], ramRowFlipped]]}; <<-- Generating the three decoders for each row of the RAM>> RamRow3Dec: PROC [n: INT] RETURNS [row3Dec: PW.ObPtr] = BEGIN aDec, bDec, cDec: PW.ObPtr; PW.Output["Row number ", Convert.RopeFromInt[n], "\n"]; PWDescr.SetInt[ramcdpd, "aAdrHi", n]; aDec _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "aAdrHi", 0, 0]; PWDescr.SetInt[ramcdpd, "bAdrHi", n]; bDec _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "bAdrHi", 0, 0]; PWDescr.SetInt[ramcdpd, "cAdrHi", n]; cDec _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "cAdrHi", 0, 0]; row3Dec _ PW.AbutX[design, PW.AbutY[design, bDec, cDec, aDec, fillerDec], -- same order as select lines routingDecToRam]; END; PrechargeGen: PROC RETURNS [ramPrecharge: PW.ObPtr] = BEGIN PrechargeCtrlGen: PROC RETURNS [prechCtrl: PW.ObPtr] = BEGIN VddProc: PW.SelectNamesProc = {keepIt _ Rope.Equal[name, "vdd"]}; RenameNPhA: PWPins.RenameProc = {SELECT TRUE FROM Rope.Equal[oldRope, "wireLeft"] => newRope _ "nPhA"; Rope.Equal[oldRope, "wireRight"] => newRope _ NIL; ENDCASE => newRope _ oldRope}; RenameNPhB: PWPins.RenameProc = {SELECT TRUE FROM Rope.Equal[oldRope, "wireLeft"] => newRope _ "nPhB"; Rope.Equal[oldRope, "wireRight"] => newRope _ "nPhB"; ENDCASE => newRope _ oldRope}; RenamePhA: PWPins.RenameProc = {SELECT TRUE FROM Rope.Equal[oldRope, "wireLeft"] => newRope _ "PhA"; Rope.Equal[oldRope, "wireRight"] => newRope _ NIL; ENDCASE => newRope _ oldRope}; RenamePhB: PWPins.RenameProc = {SELECT TRUE FROM Rope.Equal[oldRope, "wireLeft"] => newRope _ "PhB"; Rope.Equal[oldRope, "wireRight"] => newRope _ NIL; ENDCASE => newRope _ oldRope}; wire, vddConnect, ctrl, vddRect:PW.ObPtr; listOb: PW.ListOb _ NIL; size: CD.Position; ramcdpu _ EmptyDescrRamPU[]; ramcdpd _ EmptyDescrRamPD[]; <<-- PhA>> PWDescr.SetBit[ramcdpd, "PhA", TRUE]; wire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; PWDescr.SetBit[ramcdpd, "PhA", FALSE]; listOb _ CONS[PWPins.RenamePins[design, wire, RenamePhA], listOb]; <<-- nPhA>> PWDescr.SetBit[ramcdpu, "nPhA", TRUE]; wire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; PWDescr.SetBit[ramcdpu, "nPhA", FALSE]; listOb _ CONS[PWPins.RenamePins[design, wire, RenameNPhA], listOb]; <<-- PhB>> PWDescr.SetBit[ramcdpd, "PhB", TRUE]; wire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; PWDescr.SetBit[ramcdpd, "PhB", FALSE]; listOb _ CONS[PWPins.RenamePins[design, wire, RenamePhB], listOb]; <<-- nPhB>> PWDescr.SetBit[ramcdpu, "nPhB", TRUE]; wire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; PWDescr.SetBit[ramcdpu, "nPhB", FALSE]; listOb _ CONS[PWPins.RenamePins[design, wire, RenameNPhB], listOb]; <<>> <<-- Bias voltage generator>> PWDescr.SetBit[ramcdpu, "Vbias", TRUE]; listOb _ CONS[EuControl.BiasVoltage[design, ramcdpd, ramcdpu], listOb]; PWDescr.SetBit[ramcdpu, "Vbias", FALSE]; ctrl _ PW.AbutListY[design, listOb]; vddConnect _ EUtils.CtrlFiller[design, ctrl, contactPrechargeBitLines, VddProc]; size _ PW.Size[vddConnect]; vddRect _ PWCmos.Rect[CMos.met2, [size.x, size.y-12* PW.IncludeInCell[design, vddConnect, vddRect, [0, 12* [] _ CDCells.RepositionCell[vddConnect, design]; prechCtrl _ PW.AbutY[design, ctrl, vddConnect]; END; listOb: PW.ListOb _ NIL; block, prechargeBitLines, contactPrechargeBitLines, ctrl: PW.ObPtr; <<-- Make one block (=1 bitslice = 4 RAM bits)>> PW.Output["The precharge of the RAM", "\n"]; prechargeBitLines _ PW.Get[design, "prechargeBitLines"]; contactPrechargeBitLines _ PW.Get[design, "contactPrechargeBitLines"]; block _ PW.AbutX[design, contactPrechargeBitLines, PW.ArrayX[design, prechargeBitLines, nbBitsperSliceInRam]]; block _ PWPins.RenamePins[design, block]; <<>> <<-- Rename the kBus pins>> listOb _ NIL; -- re-used FOR i: INT IN [0..nbSlices) DO RenameK: PWPins.RenameProc = {IF Rope.Equal[oldRope, "kBus"] THEN newRope _ PWPins.Index[oldRope, nbSlices-1-i]; IF Rope.Equal[oldRope, "vdd"] OR Rope.Equal[oldRope, "gnd"] THEN newRope _ oldRope}; listOb _ CONS[PWPins.RenamePins[design, block, RenameK], listOb]; ENDLOOP; <<-- Now add the control>> ctrl _ PrechargeCtrlGen[]; ramPrecharge _ PW.AbutX[design, ctrl, EUtils.QadCR[design, ctrl, contactPrechargeBitLines, glueWidth, FALSE], PW.AbutListX[design, listOb]]; END; decConnectionPrecharge, genericDec, genericCtrl, fillerDec, routingDecToRam, contactSelectLinesAndKBus, ramRow, ramRowFlipped, ramArrayandDec: PW.ObPtr; PW.Output["Generating the RAM", "\n"]; decConnectionPrecharge _ PW.CreateEmptyCell[]; ramcdpu _ InitDescrRamPU[]; ramcdpd _ InitDescrRamPD[]; <<-- Cells which will be re-used a lot>> contactSelectLinesAndKBus _ PW.Get[design, "contactSelectLinesAndKBus"]; genericDec _ EuControl.Nand[design, ramcdpd, ramcdpu]; genericCtrl _ PW.AbutY[design, genericDec, PW.FlipY[design, genericDec], genericDec]; fillerDec _ EUtils.CtrlFiller[design, genericCtrl, contactSelectLinesAndKBus]; genericCtrl _ PW.AbutY[design, genericCtrl, fillerDec]; routingDecToRam _ EUtils.QadCR[design, genericCtrl, contactSelectLinesAndKBus, glueWidth]; <<>> <<-- One row of ram cells>> ramRow _ PW.ArrayX[design, PW.AbutX[design, contactSelectLinesAndKBus, PW.ArrayX[design, PW.Get[design, "threePortedRamCell"], nbBitsperSliceInRam]], nbSlices]; ramRow _ PWPins.RenamePins[design, ramRow]; ramRowFlipped _ PW.FlipY[design, ramRow]; <<-- The whole ram with the decoder, generated row by row, flipping alternate rows>> ramArrayandDec _ PW.MapFunctionY[design, RamDecFn, 0, nbRowsInRam]; <<-- Add precharge on top of the array>> ram _ PW.AbutY[design, ramArrayandDec, PrechargeGen[]]; ram _ PWPins.RenamePins[design, ram]; PW.RenameObject[design, ram, "ram"]; END; BitLinesMuxesGen: PUBLIC PROC [design: CD.Design] RETURNS [mux: PW.ObPtr] = BEGIN MuxCtrlGen: PROC [] RETURNS [muxCtrl: PW.ObPtr] = BEGIN a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3: PW.ObPtr; ramcd1: PWDescr.Descriptor; ramcd1 _ InitDescrRamPD[]; ramcdpd _ InitDescrRamPD[]; ramcdpu _ InitDescrRamPU[]; PWDescr.SetBit[ramcdpd, "nhold2BA", TRUE]; PWDescr.SetBit[ramcdpd, "nrejectBA", TRUE]; PWDescr.SetInt[ramcdpd, "aAdrLow", 0]; a0 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "aAdrLow", 1]; a1 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "aAdrLow", 2]; a2 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "aAdrLow", 3]; a3 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "aAdrLow", 0, 0]; PWDescr.SetInt[ramcdpd, "bAdrLow", 0]; b0 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "bAdrLow", 1]; b1 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "bAdrLow", 2]; b2 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "bAdrLow", 3]; b3 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "bAdrLow", 0, 0]; PWDescr.SetInt[ramcdpd, "cAdrLow", 0]; c0 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "cAdrLow", 1]; c1 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "cAdrLow", 2]; c2 _ EuControl.Nand[design, ramcdpd, ramcdpu]; PWDescr.SetInt[ramcdpd, "cAdrLow", 3]; c3 _ EuControl.Nand[design, ramcdpd, ramcdpu, TRUE]; PWDescr.SetInt[ramcdpd, "cAdrLow", 0, 0]; muxCtrl _ PW.AbutListY[design, LIST[a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3]]; END; MuxDataGen: PROC [] RETURNS [muxDataPathSlice: PW.ObPtr] = BEGIN ABLFn: PW.XYFunction = {RETURN[IF x=y THEN aBLMuxTrans ELSE bitLineMuxNoTrans]}; BBLFn: PW.XYFunction = {RETURN[IF x=y THEN bBLMuxTrans ELSE bitLineMuxNoTrans]}; CBLFn: PW.XYFunction = {RETURN[IF x=y THEN cBLMuxTrans ELSE bitLineMuxNoTrans]}; muxA, muxB, muxC, fourToOne, contacts: PW.ObPtr; bitLineMuxNoTrans: PW.ObPtr _ PW.Get[design, "bitLineMuxNoTrans"]; aBLMuxTrans: PW.ObPtr _ PW.Get[design, "aBLMuxTrans"]; bBLMuxTrans: PW.ObPtr _ PW.Get[design, "bBLMuxTrans"]; cBLMuxTrans: PW.ObPtr _ PW.Get[design, "cBLMuxTrans"]; PW.Output["Bit lines multiplexers", "\n"]; <<-- The three sets of muxes>> muxA _ PW.MapFunction[design, ABLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam]; muxB _ PW.MapFunction[design, BBLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam]; muxC _ PW.MapFunction[design, CBLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam]; <<-- Put together (from top to bottom, a, b and c), and add the contacts on the left>> contacts _ PW.AbutY[design, PW.Get[design, "contactFourToOne"], PW.ArrayY[design, PW.Get[design, "contactBLMux"], 3*nbBitsperSliceInRam]]; fourToOne _ PW.AbutY[design, PW.ArrayX[design, PW.Get[design, "fourToOneBLMuxes"], nbBitsperSliceInRam], muxC, muxB, muxA]; muxDataPathSlice _ PW.AbutX[design, contacts, fourToOne]; END; fillerSlice, muxDataPathSlice, ctrl, dp: PW.ObPtr; ramcdpd _ InitDescrRamPD[]; ctrl _ MuxCtrlGen[]; muxDataPathSlice _ MuxDataGen[]; fillerSlice _ EUtils.CtrlFiller[design, muxDataPathSlice, ctrl]; dp _ PW.ArrayX[design, PW.AbutY[design, muxDataPathSlice, fillerSlice], nbSlices]; mux _ PW.AbutX[design, ctrl, EUtils.QadCR[design, ctrl, dp, glueWidth], dp]; PW.RenameObject[design, mux, "mux"]; END; BitLinesReadWriteGen: PUBLIC PROC [design: CD.Design] RETURNS [readWrite: PW.ObPtr] = BEGIN ReadWriteCtrlGen: PROC [] RETURNS [readWriteCtrl: PW.ObPtr] = BEGIN nPhBWire, phAWire, inverters: PW.ObPtr; ramcdpd _ EmptyDescrRamPD[]; ramcdpu _ EmptyDescrRamPU[]; <<-- nPhB wire>> PWDescr.SetBit[ramcdpu, "nPhB", TRUE]; nPhBWire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; <> PWDescr.SetBit[ramcdpu, "nPhB", FALSE]; <<-- PhA wire: no hold, since the muxes take care of it >> PWDescr.SetBit[ramcdpd, "PhA", TRUE]; phAWire _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; <> PWDescr.SetBit[ramcdpd, "PhA", FALSE]; <<-- The 3*8 inverters computing the complement of the RAM address>> ramcdpd _ EmptyDescrRamPD[]; ramcdpu _ EmptyDescrRamPU[]; PWDescr.SetInt[ramcdpd, "aAdrHi", PWDescr.allOnes]; PWDescr.SetInt[ramcdpd, "aAdrLow", PWDescr.allOnes]; PWDescr.SetInt[ramcdpd, "bAdrHi", PWDescr.allOnes]; PWDescr.SetInt[ramcdpd, "bAdrLow", PWDescr.allOnes]; PWDescr.SetInt[ramcdpd, "cAdrHi", PWDescr.allOnes]; PWDescr.SetInt[ramcdpd, "cAdrLow", PWDescr.allOnes]; inverters _ EuControl.Inverters[design, ramcdpd, ramcdpu, TRUE]; readWriteCtrl _ PW.AbutY[design, phAWire, nPhBWire, inverters]; END; ReadWriteDataGen: PROC [] RETURNS [readWriteDataPath: PW.ObPtr] = BEGIN bitLinesRead, bitLinesWrite, readWrite: PW.ObPtr; bitLinesRead _ PW.Get[design, "bitLinesRead"]; bitLinesWrite _ PW.Get[design, "bitLinesWrite"]; readWrite _ PW.AbutY[design, bitLinesWrite, bitLinesRead]; readWriteDataPath _ PW.ArrayX[design, readWrite, nbSlices]; END; PW.Output["Read and write ports of the RAM", "\n"]; readWrite _ EUtils.Assemble[design, ReadWriteCtrlGen[], ReadWriteDataGen[]]; PW.RenameObject[design, readWrite, "readWrite"]; END; DrivekBusGen: PUBLIC PROC [design: CD.Design] RETURNS [cell: PW.ObPtr] = BEGIN cAdrGreaterThan239: PW.ObPtr; PW.Output["kBus driver", "\n"]; ramcdpd _ InitDescrRamPD[]; ramcdpu _ InitDescrRamPU[]; PWDescr.SetInt[ramcdpd, "cAdrHi", 60, 60]; -- cAdr>239, i.e. cAdr=1111xxxx PWDescr.SetBit[ramcdpd, "nhold2BA", TRUE]; cAdrGreaterThan239 _ EuControl.Nand[design, ramcdpd, ramcdpu]; <<>> cell _ EUtils.MakeTstDriver[design: design, in: "c", out: "kOut", ctrlListOb: LIST[cAdrGreaterThan239]]; PW.RenameObject[design, cell, "kBusDriver"]; END; AdrRegGen: PUBLIC PROC [design: CD.Design] RETURNS [regs: PW.ObPtr] = BEGIN ctrl: PW.ObPtr; regD: EUtils.RegDescr; PW.Output["Address registers", "\n"]; <<-- Bringing PhB to the address register>> ramcdpd _ EmptyDescrRamPD[]; ramcdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[ramcdpd, "PhB", TRUE]; ctrl _ EuControl.RouteTo[design, ramcdpd, ramcdpu]; <> <<>> <<-- The address register is a regular register>> regD _ NEW[EUtils.RegDescrRec _ [ inListOb: LIST["k"], out: "down", ctrlListOb: LIST[ctrl]]]; regs _ PW.AbutY[design, RoutingAdrRegGen[design], EUtils.MakeReg[design, regD]]; PW.RenameObject[design, regs, "addressRegisters"]; END; RoutingAdrRegGen: PROC [design: CD.Design] RETURNS [routing: PW.ObPtr] = BEGIN RoutingCtrlGen: PROC RETURNS [ctAdr: PW.ObPtr] = BEGIN listOb: PW.ListOb _ NIL; IntToWires: PROC [name: ROPE, nbBits: INT] = BEGIN ramcdpd _ EmptyDescrRamPD[]; PWDescr.SetInt[ramcdpd, name, PWDescr.allOnes]; FOR i: INT DECREASING IN [0..nbBits) DO PWDescr.SetInt[ramcdpd, name, PW.TwoToThe[i], PW.TwoToThe[i]]; listOb _ CONS[EuControl.RouteTo[design, ramcdpd, ramcdpu], listOb]; ENDLOOP; PWDescr.SetInt[ramcdpd, name, 0, 0]; END; ramcdpd _ EmptyDescrRamPD[]; ramcdpu _ EmptyDescrRamPU[]; <<-- Connecting the address wires>> IntToWires["aAdrHi", 6]; IntToWires["aAdrLow", 2]; IntToWires["bAdrHi", 6]; IntToWires["bAdrLow", 2]; IntToWires["cAdrHi", 6]; IntToWires["cAdrLow", 2]; <<-- Now the gap between the RAM control part and the rest (mask=> pass) (except bit)>> <<-- Notice the change in descriptor>> regscdpd _ EmptyDescrRegsPD[]; PWDescr.SetBit[regscdpd, "PhA", TRUE]; PWDescr.SetBit[regscdpd, "PhB", TRUE]; PWDescr.SetBit[regscdpd, "nhold2BA", TRUE]; PWDescr.SetBit[regscdpd, "nrejectBA", TRUE]; PWDescr.SetBit[regscdpd, "DExecute", TRUE]; PWDescr.SetInt[regscdpd, "DStateAddress", PWDescr.allOnes]; regscdpu _ InitDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhA", TRUE]; listOb _ CONS[EuControl.Gap[design, regscdpd, regscdpu], listOb]; <<-- And the connection of the 8 remaining wires to the bottom (add the inverters somewhere!!!)>> regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 2, 2]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 1, 1]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 0, 0]; PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 2, 2]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 1, 1]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 0, 0]; PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 2, 2]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 1, 1]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 0, 0]; PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", TRUE]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", FALSE, FALSE]; PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", TRUE]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", FALSE, FALSE]; ctAdr _ PW.AbutListY[design, listOb]; END; WiringFn24: PW.XYFunction = {RETURN[SELECT TRUE FROM x=23-y => wiresCt, x<23-y => wiresNothing, -- below ENDCASE => wiresNoCt]}; -- above WiringFn8: PW.XYFunction = {RETURN[SELECT TRUE FROM x=31-y => wiresCt, x<31-y => wiresNothing, -- below ENDCASE => wiresNoCt]}; -- above routingAdrRegToCtrlPass, routingAdrRegToCtrlNoPass, wires, gapWires, glue, ctrl: PW.ObPtr; wiresCt: PW.ObPtr _ PW.Get[design, "routingAdrRegToCtrl"]; wiresNoCt: PW.ObPtr _ PW.Inst[design, wiresCt, LIST["Contact"]]; wiresNothing: PW.ObPtr _ PW.Inst[design, wiresCt, LIST["Contact", "wire"]]; routingAdrRegToCtrlPass _ PW.Get[design, "routingAdrRegToCtrlPass"]; routingAdrRegToCtrlNoPass _ PW.Inst[design, routingAdrRegToCtrlPass, LIST["vertical"]]; PW.Output["A lot of routing for the addresses", "\n"]; gapWires _ PW.AbutX[design, PW.ArrayX[design, routingAdrRegToCtrlNoPass, 24], PW.ArrayX[design, routingAdrRegToCtrlPass, 8]]; wires _ PW.AbutY[design, PW.MapFunction[design, WiringFn8, 0, nbSlices, 0, 8], gapWires, PW.MapFunction[design, WiringFn24, 0, nbSlices, 0, 24]]; ctrl _ RoutingCtrlGen[]; glue _ EUtils.QadCR[design, ctrl, wires, glueWidth]; routing _ PW.AbutX[design, ctrl, glue, wires]; PW.RenameObject[design, routing, "addressRegisters"]; END; <<>> <<-- The registers providing the field descriptor>> FDRegsGen: PUBLIC PROC [design: CD.Design] RETURNS [fdRegs: PW.ObPtr] = BEGIN Regs: PROC RETURNS [regs: PW.ObPtr] = BEGIN regD: EUtils.RegDescr; listOb: PW.ListOb _ NIL; genericCtrl, ctrl, kBusAB, field, fd, dp: PW.ObPtr; <<>> <<-- The 4 inverters for DStateAddress, 8 inverters for EUAluLeftSrc1BA, EUAluRightSrc1BA, EUStore2ASrc1BA, EUSt3AisCBus2BA and EURes3AisCBus2BA, then 13 inverters for the fd, 5 for EUAluOp2AB, 1 for EUWriteToPBus3AB, and 1 for EURes3BisPBus3AB>> regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRegsPU[]; PWDescr.SetInt[regscdpd, "DStateAddress", PWDescr.allOnes]; PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", PWDescr.allOnes]; PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", PWDescr.allOnes]; PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", PWDescr.allOnes]; PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", TRUE]; PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", TRUE]; PWDescr.SetBool[regscdpd, "FDInsert", TRUE]; PWDescr.SetInt[regscdpd, "FDMask", PWDescr.allOnes]; PWDescr.SetInt[regscdpd, "FDShift", PWDescr.allOnes]; PWDescr.SetInt[regscdpd, "EUAluOp2AB", PWDescr.allOnes]; PWDescr.SetBool[regscdpd, "EUWriteToPBus3AB", TRUE]; PWDescr.SetBool[regscdpd, "EURes3BisPBus3AB", TRUE]; listOb _ CONS[EuControl.Inverters[design, regscdpd, regscdpu, TRUE], listOb]; <<-- The 2 nand decoders for fd>> regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhB", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhA", TRUE]; PWDescr.SetInt[regscdpd, "EUAluOp2AB", fop]; -- EUAluOp2AB=FOP listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, "EUAluOp2AB", fopk]; -- EUAluOp2AB=FOPK listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb]; PWDescr.SetInt[regscdpd, "EUAluOp2AB", 0, 0]; -- clean-up <<-- The 2 nand decoders for field and kBusAB (reject???)>> <<-- just PhA.nrejectBA for kBusAB>> PWDescr.SetBit[regscdpd, "nrejectBA", TRUE]; PWDescr.SetBit[regscdpd, "nhold2BA", TRUE]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb]; PWDescr.SetBit[regscdpd, "EULoadField3BA", TRUE]; -- for field genericCtrl _ EuControl.Nand[design, regscdpd, regscdpu, TRUE]; listOb _ CONS[genericCtrl, listOb]; PWDescr.SetBit[regscdpd, "nrejectBA", FALSE]; PWDescr.SetBit[regscdpd, "nhold2BA", FALSE]; ctrl _ PW.AbutListY[design, listOb]; <<-- Generate the three registers>> regD _ NEW[EUtils.RegDescrRec _ [inListOb: LIST["k"], out: "opL"]]; kBusAB _ EUtils.MakeRegDP[design, regD]; regD _ NEW[EUtils.RegDescrRec _ [inListOb: LIST["c"], out: "opR", interruptBuses: LIST["opLBus", "opRBus", "downBus"]]]; field _ EUtils.MakeRegDP[design, regD]; regD _ NEW[EUtils.RegDescrRec _ [inListOb: LIST["opL", "opR"], out: "down"]]; fd _ EUtils.MakeRegDP[design, regD]; dp _ PW.AbutY[design, field, kBusAB, fd]; regs _ EUtils.Assemble[design, ctrl, dp]; END; Routing: PROC RETURNS [routing: PW.ObPtr] = BEGIN WiringFn13: PW.XYFunction = {RETURN[SELECT TRUE FROM x<3 => wiresNothing, x=15-y => wiresCt, x>15-y => wiresNothing, ENDCASE => wiresNoCt]}; Ctrl: PROC RETURNS [ctrl: PW.ObPtr] = BEGIN IntToWires: PROC [name: ROPE, nbBits: INT] = BEGIN regscdpd _ EmptyDescrRegsPD[]; PWDescr.SetInt[regscdpd, name, PWDescr.allOnes]; FOR i: INT DECREASING IN [0..nbBits) DO PWDescr.SetInt[regscdpd, name, PW.TwoToThe[i], PW.TwoToThe[i]]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; ENDLOOP; PWDescr.SetInt[regscdpd, name, 0, 0]; END; listOb: PW.ListOb _ NIL; regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRegsPU[]; <<-- insert>> PWDescr.SetBool[regscdpd, "FDInsert", TRUE]; listOb _ CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb]; <<-- mask>> IntToWires["FDMask", 6]; <<-- shift>> IntToWires["FDShift", 6]; ctrl _ PW.AbutListY[design, listOb]; END; wires: PW.ObPtr _ PW.MapFunction[design, WiringFn13, 0, nbSlices, 0, 13]; routing _ EUtils.Assemble[design, Ctrl[], wires]; END; wiresCt: PW.ObPtr _ PW.Get[design, "routingfdRegsToCtrl"]; wiresNoCt: PW.ObPtr _ PW.Inst[design, wiresCt, LIST["Contact"]]; wiresNothing: PW.ObPtr _ PW.Inst[design, wiresCt, LIST["Contact", "wire"]]; PW.Output["Registers associated with the Field Unit", "\n"]; regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRegsPU[]; PWDescr.SetBit[regscdpu, "nPhB", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhA", TRUE]; PWDescr.SetBit[regscdpd, "nhold2BA", TRUE]; PWDescr.SetBit[regscdpd, "nrejectBA", TRUE]; fdRegs _ PW.AbutY[design, Regs[], Routing[]]; PW.RenameObject[design, fdRegs, "fdRegisters"]; END; <<>> <<-- Let's shift to the layout of the Field Unit>> FieldUnitGen: PUBLIC PROC [design: CD.Design] RETURNS [fieldUnit: PW.ObPtr] = BEGIN MaskGen: PROC[maskNb: INT] RETURNS [mask: PW.ObPtr] = BEGIN MaskCtrlGen: PROC [maskNb: INT] RETURNS [maskCtrl: PW.ObPtr] = BEGIN ctrl: PW.ObPtr; listOb: PW.ListOb _ NIL; name: ROPE = IF maskNb=1 THEN "FDShift" ELSE "FDMask"; regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhA", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhB", TRUE]; <<-- I want to isolate the ith bit of FDShift>> PWDescr.SetInt[regscdpd, name, 0, 1]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb]; PWDescr.SetInt[regscdpd, name, 0, 2]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, name, 4, 4]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb]; PWDescr.SetInt[regscdpd, name, 0, 8]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb]; PWDescr.SetInt[regscdpd, name, 16, 16]; listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb]; PWDescr.SetInt[regscdpd, name, 0, 32]; ctrl _ EuControl.Nand[design, regscdpd, regscdpu]; listOb _ CONS[ctrl, listOb]; maskCtrl _ PW.AbutListY[design, listOb]; END; MaskGate: PROC [i, b: INT] RETURNS [PW.ObPtr] = BEGIN useNand: BOOL _ ~PW.XthBitOfN[b, i]; IF PW.ODD[b] THEN useNand _ ~useNand; IF useNand THEN RETURN[maskNandArray[b]] ELSE RETURN[maskNorArray[b]]; END; MaskFn: PW.XYFunction = {RETURN[ PW.AbutListX[design, LIST[IF PW.EVEN[x] THEN maskBusesSel ELSE maskBusesOne, MaskGate[x, 1], MaskGate[x, 2], MaskGate[x, 3], MaskGate[x, 4], MaskGate[x, 5], IF maskNb=1 THEN maskRight1 ELSE maskRight2]]]}; maskNor, maskNand, maskBuses, maskBusesOne, maskBusesSel, maskRight, maskRight1, maskRight2: PW.ObPtr; maskNorArray, maskNandArray: ARRAY [1..5] OF PW.ObPtr; maskNor _ PW.Get[design, "maskNor"]; maskNand _ PW.Get[design, "maskNand"]; maskBuses _ PW.Get[design, "maskBuses"]; maskRight _ PW.Get[design, "maskRight"]; maskNorArray[1] _ PW.Inst[design, maskNor, LIST["Ct1"], FALSE]; maskNorArray[2] _ PW.Inst[design, maskNor, LIST["Ct2"], FALSE]; maskNorArray[3] _ PW.Inst[design, maskNor, LIST["Ct3"], FALSE]; maskNorArray[4] _ PW.Inst[design, maskNor, LIST["Ct4"], FALSE]; maskNorArray[5] _ PW.Inst[design, maskNor, LIST["Ct5"], FALSE]; maskNandArray[1] _ PW.Inst[design, maskNand, LIST["Ct1"], FALSE]; maskNandArray[2] _ PW.Inst[design, maskNand, LIST["Ct2"], FALSE]; maskNandArray[3] _ PW.Inst[design, maskNand, LIST["Ct3"], FALSE]; maskNandArray[4] _ PW.Inst[design, maskNand, LIST["Ct4"], FALSE]; maskNandArray[5] _ PW.Inst[design, maskNand, LIST["Ct5"], FALSE]; maskBusesOne _ PW.Inst[design, maskBuses, LIST["One"], FALSE]; maskBusesSel _ PW.Inst[design, maskBuses, LIST["Sel"], FALSE]; maskRight1 _ PW.Inst[design, maskRight, LIST["mask1"], FALSE]; maskRight2 _ PW.Inst[design, maskRight, LIST["mask2"], FALSE]; mask _ EUtils.Assemble[design, MaskCtrlGen[maskNb], PW.MapFunctionX[design, MaskFn, 0, nbSlices]]; END; ShifterGen: PROC RETURNS [shifter: PW.ObPtr] = BEGIN CtrlGen: PROC RETURNS [ctrl: PW.ObPtr] = BEGIN listOb: PW.ListOb _ NIL; regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhA", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhB", TRUE]; FOR i: INT IN [0..nbSlices+1) DO PWDescr.SetInt[regscdpd, "FDShift", i]; -- shift=i listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, PW.ODD[i]], listOb]; ENDLOOP; ctrl _ PW.AbutListY[design, listOb]; END; shifter0Cell, shifterCell, shifter32Cell, ctrl, sh: PW.ObPtr; shifter0Cell _ PW.Get[design, "shifter0Cell"]; shifterCell _ PW.Get[design, "shifterCell"]; shifter32Cell _ PW.Get[design, "shifter32Cell"]; sh _ PW.AbutY[design, PW.ArrayX[design, shifter32Cell, nbSlices], PW.Array[design, shifterCell, nbSlices, nbSlices-1], PW.ArrayX[design, shifter0Cell, nbSlices]]; ctrl _ CtrlGen[]; shifter _ EUtils.Assemble[design, ctrl, sh]; END; MergeGen: PROC RETURNS [merge: PW.ObPtr] = BEGIN CtrlGen: PROC RETURNS [ctrl: PW.ObPtr] = BEGIN generic: PW.ObPtr; regscdpd2: PWDescr.Descriptor; listOb: PW.ListOb _ NIL; regscdpd _ EmptyDescrRegsPD[]; regscdpd2 _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhA", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhB", TRUE]; PWDescr.SetBit[regscdpd2, "PhB", TRUE]; generic _ EuControl.Nand[design, regscdpd, regscdpu]; <<-- EUAluOp2AB=FOP OR EUAluOp2AB=FOPK (could be checked on one bit)>> PWDescr.SetInt[regscdpd, "EUAluOp2AB", fop]; -- EUAluOp2AB=FOP PWDescr.SetInt[regscdpd2, "EUAluOp2AB", fopk]; -- EUAluOp2AB=FOPK listOb _ CONS[EuControl.NorOfNands[design, LIST[regscdpd, regscdpd2], regscdpu], listOb]; regscdpd _ EmptyDescrRegsPD[]; regscdpu _ EmptyDescrRamPU[]; PWDescr.SetBit[regscdpu, "nPhA", TRUE]; PWDescr.SetBit[regscdpu, "Vbias", TRUE]; PWDescr.SetBit[regscdpd, "PhB", TRUE]; PWDescr.SetBool[regscdpd, "FDInsert", TRUE]; -- insert listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb]; PWDescr.SetBool[regscdpd, "FDInsert", FALSE]; -- ~insert listOb _ CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb]; ctrl _ PW.AbutListY[design, listOb]; END; ctrl, mergeDp: PW.ObPtr; mergeDp _ PW.ArrayX[design, PW.Get[design, "fuMerge"], nbSlices]; ctrl _ CtrlGen[]; merge _ EUtils.Assemble[design, ctrl, mergeDp]; END; PW.Output["The Field Unit", "\n"]; fieldUnit _ PW.AbutY[design, MaskGen[1], PW.FlipY[design, MaskGen[2]], MergeGen[], ShifterGen[] ]; PW.RenameObject[design, fieldUnit, "fieldUnit"]; END; <<>> <<>> END. <<>>