<> <> <> <> <> DIRECTORY Boole, BooleCore, CoreCreate, CoreOps, CoreProperties, Dragon, EUInner, EUUtils, PWCore, PWCoreRoute; EUControlImpl: CEDAR PROGRAM IMPORTS Boole, BooleCore, CoreCreate, CoreOps, CoreProperties, EUUtils, PWCore EXPORTS EUInner = BEGIN OPEN Boole, BooleCore, CoreCreate, EUInner; <<-- The whole control: three pieces assembled with two channels>> CreateControl: PUBLIC PROC [] RETURNS [ct: CellType] ~ { ct _ EUUtils.Fetch["Control"]; IF ct=NIL THEN { ct _ EUUtils.Extract["Control.sch"]; EUUtils.Store["Control", ct]; }; }; <<-- Ram decoder plus a few odds and ends>> CreateRamControl: PUBLIC PROC [] RETURNS [ct: CellType] ~ { ct _ EUUtils.Fetch["RamControl"]; IF ct=NIL THEN { ct _ CreateRamControlFromEquations[]; EUUtils.Store["RamControl", ct]; }; }; <<-- Standard cell block: carry, cc and DBus>> CreateSCControl: PUBLIC PROC [] RETURNS [ct: CellType] ~ { ct _ EUUtils.Fetch["SCControl"]; IF ct=NIL THEN { ct _ EUUtils.Extract["SCControl.sch"]; EUUtils.Store["SCControl", ct]; }; }; <<-- Control for datapath>> CreateDPControl: PUBLIC PROC [] RETURNS [ct: CellType] ~ { ct _ EUUtils.Fetch["DPControl"]; IF ct=NIL THEN { ct _ CreateDPControlFromEquations[]; EUUtils.Store["DPControl", ct]; }; }; ExprProc: TYPE ~ PROC [i: NAT _ 0] RETURNS [Expression]; AppendInput: PROC [public: Wire, wr: WR, inputD: Inputs] RETURNS [ins: Inputs]~ { AppendOneInput: CoreOps.EachWireProc ~ { IF wire.size#0 THEN RETURN; ins _ CONS[[input: wire, driver: inv], ins]}; inv: CellType _ EUUtils.AlpsExtract["InputDriver.sch"]; ins _ inputD; [] _ CoreOps.VisitWire[FindWire[public, wr], AppendOneInput]; }; AppendOutput: PROC [wire: WR, expr: Expression, clock: ROPE _ NIL, outputDrivers: Outputs] RETURNS [Outputs] ~ { out: CellType _ EUUtils.AlpsExtract[IF clock=NIL THEN "OutputDriver.sch" ELSE "ClockedOutputDriver.sch"]; RETURN [CONS[ [driver: out, pas: IF clock=NIL THEN LIST[["VRef", "VRef"]] ELSE LIST[["Clock", clock], ["VRef", "VRef"]], output: wire, expr: expr], outputDrivers]]; }; -- To be generated by Alps (Ave, Serlet, programatori te salutant!) CreateRamControlFromEquations: PROC RETURNS [cellType: CellType] = { BEGIN inputDrivers: Inputs _ NIL; outputDrivers: Outputs _ NIL; expr: Expression _ NIL; selA: Wire _ Seq["selA", EUUtils.nRows]; -- outputs of the y-decoder selB: Wire _ Seq["selB", EUUtils.nRows]; selC: Wire _ Seq["selC", EUUtils.nRows]; selALow: Wire _ Seq["selALow", 4]; -- outputs of the x-decoder selBLow: Wire _ Seq["selBLow", 4]; selCLow: Wire _ Seq["selCLow", 4]; selRam: Wire _ WireList[wrs: LIST[selA, selB, selC, selALow, selBLow, selCLow], name: "selRam"]; <<-- public>> public: Wire _ WireList[LIST[ "Vdd", "Gnd", "VRef", "phA", selRam, Seq["ramAdr", 24], <> "reject", "hold", "read", "write", Seq["dStateAd", 4], "enWrtIFUPhA", "enWrtIFUPhB", EUUtils.GenRegSelWire[EUUtils.fieldRow]]]; -- selFieldSrc[0..2) <<>> <<-- All the wires used as inputs (numbers)>> dStateAd: Wire _ FindWire[public, "dStateAd"]; ramAdr: Wire _ FindWire[public, "ramAdr"]; aHi: Wire _ Range[ramAdr, 0, 6]; aLow: Wire _ Range[ramAdr, 6, 2]; bHi: Wire _ Range[ramAdr, 8, 6]; bLow: Wire _ Range[ramAdr, 14, 2]; cHi: Wire _ Range[ramAdr, 16, 6]; cLow: Wire _ Range[ramAdr, 22, 2]; cAdr: Wire _ Range[ramAdr, 16, 8]; <<-- Expressions (booleans)>> read: Variable _ FindWire[public, "read"]; write: Variable _ FindWire[public, "write"]; reject: Variable _ FindWire[public, "reject"]; nReject: Expression _ Not[reject]; hold: Variable _ FindWire[public, "hold"]; nHold: Expression _ Not[hold]; AppendRamDriver: PROC [output: WR, expr: Expression] ~ { outputDrivers _ AppendOutput[output , expr, "phA", outputDrivers]; }; <<>> IF aLow.size#2 OR bLow.size#2 OR cLow.size#2 THEN ERROR; IF aHi.size#6 OR bHi.size#6 OR cHi.size#6 THEN ERROR; <<-- Input inverters to the Alps blocks>> inputDrivers _ AppendInput[public, "reject", inputDrivers]; -- 1 inputDrivers _ AppendInput[public, "hold", inputDrivers]; -- 1 inputDrivers _ AppendInput[public, "read", inputDrivers]; -- 1 inputDrivers _ AppendInput[public, "write", inputDrivers]; -- 1 inputDrivers _ AppendInput[public, "dStateAd", inputDrivers]; -- 4 inputDrivers _ AppendInput[public, ramAdr, inputDrivers]; -- 24 <<-- Enable Write on the KBus (IFU side); by luck, same timing as ram>> outputDrivers _ AppendOutput["enWrtIFUPhA", EqualInt[cAdr, EUUtils.IFUAdr], NIL, outputDrivers]; <<-- enWrtIFUPhA _ cAdr=IFUAdr>> outputDrivers _ AppendOutput["enWrtIFUPhB", false, NIL, outputDrivers]; <<-- enWrtIFUPhB _ false (if no // debug, never used, so could be removed)>> <<>> <<-- Output drivers, all of the same type: they follow PhA>> FOR i: INT IN [0..EUUtils.nRows) DO AppendRamDriver[selA[i], EqualInt[aHi, i]]; <<-- selHi[i][a] _ aAdrH=i>> AppendRamDriver[selB[i], EqualInt[bHi, i]]; <<-- selHi[i][b] _ bAdrH=i>> expr _ IF i=EUUtils.marAdr/4 THEN Or[reject, EqualInt[cHi, i]] ELSE And[nReject, EqualInt[cHi, i]]; AppendRamDriver[selC[i], expr]; <<-- selHi[i][c] _ (cAdrH=i).~reject for i#marAdr/4>> <<-- selHi[marAdr/4][c] _ (cAdrH=i)+reject>> ENDLOOP; FOR i: INT IN [0..4) DO AppendRamDriver[selALow[i], EqualInt[aLow, i]]; <<-- selLow[i][a] _ aAdrL=i>> AppendRamDriver[selBLow[i], EqualInt[bLow, i]]; <<-- selLow[i][b] _ bAdrL=i>> expr _ IF i=EUUtils.marAdr MOD 4 THEN Or[reject, EqualInt[cLow, i]] ELSE And[nReject, EqualInt[cLow, i]]; AppendRamDriver[selCLow[i], expr]; <<-- selLow[i][c] _ (cAdrL=i).~reject for i#marAdr MOD 4>> <<-- selHi[marAdr MOD 4][c] _ (cAdrL=i)+reject>> ENDLOOP; <<>> <<-- Control for Field register; located here because it requires cAdr; also same timing as ram>> outputDrivers _ AppendOutput["selFieldSrc[0]", And[nReject, nHold, EqualInt[cAdr, EUUtils.fieldAdr]], "phA", outputDrivers]; <<-- selFieldSrc[0] _ (cAdr=fieldAdr).~reject.~hold.PhA>> outputDrivers _ AppendOutput["selFieldSrc[1]", And[write, EqualInt[dStateAd, EUUtils.fieldRow]], NIL, outputDrivers]; <<-- selFieldSrc[1] _ (dStateAd=field).write>> outputDrivers _ AppendOutput["selFieldSrc[2]", And[read, EqualInt[dStateAd, EUUtils.fieldRow]], NIL, outputDrivers]; <<-- selFieldSrc[2] _ (dStateAd=field).read>> <<>> cellType _ AlpsCell[ name: "RamControl", public: public, inputs: inputDrivers, outputs: outputDrivers, props: CoreProperties.Props[[$ContactPolyMetal2, NEW[INT _ 20]]] ]; END; }; <<-- Creates the control for the bottom of the Datapath>> <<-- 716*2737, 28 inputs, and 89 outputs>> CreateDPControlFromEquations: PROC RETURNS [cellType: CellType] = { BEGIN <<-- Control of input muxes for pipeline registers, and their DBus>> MakeRegSelExpr: PROC [reg: EUUtils.PipeRange, exprProc: ExprProc, clock: ROPE _ NIL] ~ { size: NAT _ EUUtils.sources[reg].sizeSel; FOR i: INT IN [0..size) DO outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, i], expr: exprProc[i], clock: clock, outputDrivers: outputDrivers]; ENDLOOP; outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, size], expr: And[write, EqualInt[dStateAd, reg]], clock: NIL, outputDrivers: outputDrivers]; outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, size+1], expr: And[read, EqualInt[dStateAd, reg]], clock: NIL, outputDrivers: outputDrivers]; }; MakeTristateSelExpr: PROC [reg: EUUtils.PipeRange, exprProc: ExprProc, clock, enWClock: ROPE _ NIL] ~ { size: NAT _ EUUtils.sources[reg].sizeSel; FOR i: INT IN [0..size) DO outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, i], expr: exprProc[i], clock: clock, outputDrivers: outputDrivers]; ENDLOOP; outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, size], -- read cBus during debugging expr: exprProc[size], clock: clock, outputDrivers: outputDrivers]; outputDrivers _ AppendOutput[ wire: Index[EUUtils.sources[reg].nameSel, size+1], -- enable write on cBus expr: exprProc[size+1], clock: enWClock, outputDrivers: outputDrivers]; }; MakeSelExpr: PROC [reg: EUUtils.PipeRange, exprProc: ExprProc, clock, enWClock: ROPE _ NIL] ~ { IF EUUtils.sources[reg].tristate THEN MakeTristateSelExpr[reg, exprProc, clock, enWClock] ELSE MakeRegSelExpr[reg, exprProc, clock]; }; inputDrivers: Inputs _ NIL; outputDrivers: Outputs _ NIL; public: Wire _ Union[ WireList[LIST["Vdd", "Gnd", "phA", "phB", "nPhB", Seq["selCarry", 5], "enWrtPBusPhA", "enWrtPBusPhB", Seq["ctrl8", 8], "writePBus", "res3BisP", "reject", Seq["aluOp", 4], "hold", "read", "write", Seq["dStateAd", 4], "VRef", Seq["op", 5] ]], Wires[EUUtils.GenRegSelWire[EUUtils.leftRow], EUUtils.GenRegSelWire[EUUtils.rightRow], EUUtils.GenRegSelWire[EUUtils.st2ARow], EUUtils.GenRegSelWire[EUUtils.st2BRow], EUUtils.GenRegSelWire[EUUtils.st3ARow], EUUtils.GenRegSelWire[EUUtils.kRegRow], EUUtils.GenRegSelWire[EUUtils.r2BRow], EUUtils.GenRegSelWire[EUUtils.r3ARow], EUUtils.GenRegSelWire[EUUtils.r3BRow], EUUtils.GenRegSelWire[EUUtils.dataInRow]], Wires[Seq["shift", 6], Seq["sh", 33]]]; <<-- All the wires used as inputs (numbers)>> ctrl8: Wire _ FindWire[public, "ctrl8"]; leftSrc: Wire _ Range[ctrl8, 1, 2]; rightSrc: Wire _ Range[ctrl8, 3, 3]; st2ASrc: Wire _ Range[ctrl8, 6, 2]; shift: Wire _ FindWire[public, "shift"]; aluOp: Wire _ FindWire[public, "aluOp"]; dStateAd: Wire _ FindWire[public, "dStateAd"]; <<-- Expressions (booleans)>> reject: Variable _ FindWire[public, "reject"]; -- latched on PhB in the pad nReject: Expression _ Not[reject]; read: Variable _ FindWire[public, "read"]; write: Variable _ FindWire[public, "write"]; hold: Variable _ FindWire[public, "hold"]; nHold: Expression _ Not[hold]; fetch: Variable _ FindWire[public, "res3BisP"]; store: Variable _ FindWire[public, "writePBus"]; st3AisC: Variable _ FindWire[public, ctrl8[0]]; <<>> <<-- PhA latches>> LeftExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[leftSrc, i]]]}; <> RightExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[rightSrc, i]]]}; <<-- selRightSrc[i] _ PhA . (rightSrc=i) . ~reject . ~hold>> St2AExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[st2ASrc, i]]]}; <<-- selSt2ASrc[i] _ PhA . (st2ASrc=i) . ~reject . ~hold>> R3AExpr: ExprProc = {RETURN[And[nReject, nHold]]}; <<-- selRes3ABSrc _ PhA . ~reject . ~hold>> St3AExpr: ExprProc = {RETURN[ SELECT i FROM 0 => And[nReject, nHold, Not[st3AisC]], 1 => And[nReject, nHold, st3AisC], ENDCASE => ERROR]}; <<-- selSt3ABSrc[st2B] _ PhA . ~st3AisC . ~reject . ~hold>> <<-- selSt3ABSrc[cBus] _ PhA . st3AisC . ~reject . ~hold>> <<-- PhB latches>> KRegExpr: ExprProc = {RETURN[nHold]}; <<-- selKRegAdr _ PhB . ~hold>> R2BExpr: ExprProc = {RETURN[ SELECT i FROM 0 => And[nHold, Nor[OpIs[FOP], OpIs[BndChk]]], -- aluOut 1 => And[nHold, OpIs[FOP]], -- fuOut 2 => And[nHold, OpIs[BndChk]], -- left ENDCASE => ERROR]}; <<-- selRes2BASrc[aluOut] _ PhB . ~hold . (aluOp#FOP AND aluOp#BndChk)>> <<-- selRes2BASrc[fuOut] _ PhB . ~hold . (aluOp=FOP)>> <<-- selRes2BASrc[left] _ PhB . ~hold . (aluOp=BndChk)>> St2BExpr: ExprProc = {RETURN[nHold]}; <<-- selSt2BASrc _ PhB . ~hold>> R3BExpr: ExprProc = {RETURN[ SELECT i FROM 0 => nHold, -- input 1 => And[write, EqualInt[dStateAd, EUUtils.r3BRow]], -- read cBus 2 => Or[And[nHold, Nand[fetch, nReject]], And[read, EqualInt[dStateAd, EUUtils.r3BRow]]], -- enable Write < Or[And[nHold, Nor[fetch, nReject]], And[read, EqualInt[dStateAd, EUUtils.r3BRow]]], -- enable Write>> ENDCASE => ERROR]}; <<-- selRes3BASrc[0] _ PhB . ~hold>> <<-- selRes3BASrc[1] _ PhB . write . (dStateAd=r3B)>> <<-- selRes3BASrc[enW] _ nPhB . ( ~hold.(~fetch+reject) + read.(dStateAd=r3B) )>> DataInExpr: ExprProc = {RETURN[ SELECT i FROM 0 => nHold, -- input 1 => And[write, EqualInt[dStateAd, EUUtils.dataInRow]], -- read cBus 2 => Or[And[nHold, fetch, nReject], And[read, EqualInt[dStateAd, EUUtils.dataInRow]]], -- enable Write ENDCASE => ERROR]}; <<-- selDataInSrc[0] _ PhB . ~hold>> <<-- selDataInSrc[enW] _ nPhB . ( ~hold.fetch.~reject + read.(dStateAd=dataIn) )>> <<-- Special guys>> <> <