<> <> <> DIRECTORY CoreCreate, Dragon, EU2Arith, EU2Control, EU2ControlAlps, EU2Utils, Ports, Rosemary; EU2ControlImpl: CEDAR PROGRAM IMPORTS CoreCreate, EU2Arith, EU2ControlAlps, EU2Utils, Ports, Rosemary EXPORTS EU2Control = BEGIN OPEN CoreCreate, EU2Arith, EU2Control, EU2Utils; public: Wire _ Union[GenPGnEWires[], GenClockWires[], GenWiresCtrlToPads[], GenWiresPadsToCtrl[], GenWiresDBus[], GenWiresForRouter[]]; <<-- PGE>> Vdd: PUBLIC NAT _ PortIndex[public, "Vdd"]; Gnd: PUBLIC NAT _ PortIndex[public, "Gnd"]; phA: PUBLIC NAT _ PortIndex[public, "phA"]; phB: PUBLIC NAT _ PortIndex[public, "phB"]; nPhA: PUBLIC NAT _ PortIndex[public, "nPhA"]; nPhB: PUBLIC NAT _ PortIndex[public, "nPhB"]; <<-- Inputs>> res3BisP: PUBLIC NAT _ PortIndex[public, "res3BisP"]; writePBus: PUBLIC NAT _ PortIndex[public, "writePBus"]; aluOp: PUBLIC NAT _ PortIndex[public, "aluOp"]; condSel: PUBLIC NAT _ PortIndex[public, "condSel"]; reject: PUBLIC NAT _ PortIndex[public, "reject"]; debug: PUBLIC NAT _ PortIndex[public, "debug"]; ramAdr: PUBLIC NAT _ PortIndex[public, "ramAdr"]; ctrl8: PUBLIC NAT _ PortIndex[public, "ctrl8"]; st3AisC: PUBLIC NAT _ PortIndex[public[ctrl8], "st3AisC"]; leftSrc: PUBLIC NAT _ PortIndex[public[ctrl8], "leftSrc"]; rightSrc: PUBLIC NAT _ PortIndex[public[ctrl8], "rightSrc"]; st2ASrc: PUBLIC NAT _ PortIndex[public[ctrl8], "st2ASrc"]; zero: PUBLIC NAT _ PortIndex[public, "zero"]; carryOut: PUBLIC NAT _ PortIndex[public, "carryOut"]; res: PUBLIC NAT _ PortIndex[public, "res"]; opL: PUBLIC NAT _ PortIndex[public, "opL"]; opR: PUBLIC NAT _ PortIndex[public, "opR"]; fd: PUBLIC NAT _ PortIndex[public, "fd"]; insertFd: PUBLIC NAT _ PortIndex[public[fd], "insertFd"]; maskFd: PUBLIC NAT _ PortIndex[public[fd], "maskFd"]; shiftFd: PUBLIC NAT _ PortIndex[public[fd], "shiftFd"]; <<-- Outputs>> enWrtPBus: PUBLIC NAT _ PortIndex[public, "enWrtPBus"]; enWrtIFU: PUBLIC NAT _ PortIndex[public, "enWrtIFU"]; condition: PUBLIC NAT _ PortIndex[public, "condition"]; selA: PUBLIC NAT _ PortIndex[public, "selA"]; selB: PUBLIC NAT _ PortIndex[public, "selB"]; selC: PUBLIC NAT _ PortIndex[public, "selC"]; selALow: PUBLIC NAT _ PortIndex[public, "selALow"]; selBLow: PUBLIC NAT _ PortIndex[public, "selBLow"]; selCLow: PUBLIC NAT _ PortIndex[public, "selCLow"]; dRamRead: PUBLIC NAT _ PortIndex[public, "dRamRead"]; pipeRegsSel: PUBLIC NAT _ PortIndex[public, "pipeRegsSel"]; op: PUBLIC NAT _ PortIndex[public, "op"]; carryIn: PUBLIC NAT _ PortIndex[public, "carryIn"]; insert: PUBLIC NAT _ PortIndex[public, "insert"]; mask: PUBLIC NAT _ PortIndex[public, "mask"]; shift: PUBLIC NAT _ PortIndex[public, "shift"]; sh: PUBLIC NAT _ PortIndex[public, "sh"]; CreateEU2Control: PUBLIC PROC RETURNS [cellType: CellType] = { cellType _ Cell[ name: "EU2Control", public: public, instances: LIST[ Instance[EU2ControlAlps.CreateDPControl[]], Instance[EU2ControlAlps.CreateRamControl[]]] ]; <<-- PGE>> [] _ Rosemary.SetFixedWire[cellType.public[Vdd], H]; [] _ Rosemary.SetFixedWire[cellType.public[Gnd], L]; <<-- Inputs>> [] _ Ports.InitPort[cellType.public[aluOp], c, none]; [] _ Ports.InitPort[cellType.public[condSel], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][a][hi], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][a][hi], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][b][low], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][b][hi], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][c][low], c, none]; [] _ Ports.InitPort[cellType.public[ramAdr][c][low], c, none]; [] _ Ports.InitPort[cellType.public[ctrl8][st3AisC], b, none]; [] _ Ports.InitPort[cellType.public[ctrl8][leftSrc], c, none]; [] _ Ports.InitPort[cellType.public[ctrl8][rightSrc], c, none]; [] _ Ports.InitPort[cellType.public[ctrl8][st2ASrc], c, none]; [] _ Ports.InitPort[cellType.public[res], c, none]; [] _ Ports.InitPort[cellType.public[opL], c, none]; [] _ Ports.InitPort[cellType.public[opR], c, none]; [] _ Ports.InitPort[cellType.public[fd][insertFd], b, none]; [] _ Ports.InitPort[cellType.public[fd][maskFd], c, none]; [] _ Ports.InitPort[cellType.public[fd][shiftFd], c, none]; <<-- Outputs>> [] _ Ports.InitPort[cellType.public[enWrtPBus], b, drive]; [] _ Ports.InitPort[cellType.public[enWrtIFU], b, drive]; [] _ Ports.InitPort[cellType.public[condition], b, drive]; InitLeafPorts[cellType.public[selA], drive]; InitLeafPorts[cellType.public[selB], drive]; InitLeafPorts[cellType.public[selC], drive]; InitLeafPorts[cellType.public[selALow], drive]; InitLeafPorts[cellType.public[selBLow], drive]; InitLeafPorts[cellType.public[selCLow], drive]; [] _ Ports.InitPort[cellType.public[dRamRead], b, drive]; InitLeafPorts[cellType.public[pipeRegsSel], drive]; InitLeafPorts[cellType.public[op], drive]; [] _ Ports.InitPort[cellType.public[carryIn], b, drive]; [] _ Ports.InitPort[cellType.public[insert], b, drive]; [] _ Ports.InitPort[cellType.public[mask], c, drive]; [] _ Ports.InitPort[cellType.public[shift], c, drive]; InitLeafPorts[cellType.public[sh], drive]; [] _ Rosemary.BindCellType[cellType: cellType, roseClassName: EU2ControlClass]; }; EU2ControlClass: ROPE = Rosemary.Register[roseClassName: "EU2Control", evalSimple: EU2ControlSimple]; bndCheck: NAT = ORD[Dragon.ALUOps[BndChk]]; -- also in EU2Utils fop: NAT = ORD[Dragon.ALUOps[FOP]]; EU2ControlSimple: Rosemary.EvalProc = { state: EU2ControlState _ NARROW[stateAny]; {OPEN state; Reset: PROC [reg: PipeRange] ~ { size: NAT _ sources[reg].sizeSel; FOR i: NAT IN [0..size+1) DO p[pipeRegsSel][reg][i].b _ FALSE; ENDLOOP; }; SimpleSel: PROC [reg: PipeRange, source: NAT] ~ { size: NAT _ sources[reg].sizeSel; FOR i: NAT IN [0..size) DO p[pipeRegsSel][reg][i].b _ (p[source].c=i) AND ~rejectBA; ENDLOOP; p[pipeRegsSel][reg][size].b _ FALSE; -- read for debugging }; IF p[phA].b THEN { selAluOps: Dragon.ALUOps _ VAL[p[aluOp].c]; aluOpRec: ALUOpRec _ aluOps[selAluOps]; cAdr: NAT _ p[ramAdr][c][hi].c*4+p[ramAdr][c][low].c; <<-- drive PBus>> p[enWrtPBus].b _ TRUE; <<-- drive KBus>> p[enWrtIFU].b _ cAdr=IFUAdr; <<-- drive condition>> p[condition].b _ FALSE; -- actually, it could be anything I like <<-- drive ram select lines>> p[selA][p[ramAdr][a][hi].c].b _ TRUE; p[selB][p[ramAdr][b][hi].c].b _ TRUE; p[selC][p[ramAdr][c][hi].c].b _ TRUE; p[selALow][p[ramAdr][a][low].c].b _ TRUE; p[selBLow][p[ramAdr][b][low].c].b _ TRUE; p[selCLow][p[ramAdr][c][low].c].b _ TRUE; <<-- set PhA regs muxes>> SimpleSel[left, leftSrc]; SimpleSel[right, rightSrc]; SimpleSel[st2A, st2ASrc]; p[pipeRegsSel][st3A][0].b _ ~p[st3AisC].b AND ~rejectBA; -- s2Bus p[pipeRegsSel][st3A][1].b _ p[st3AisC].b AND ~rejectBA; -- cBus p[pipeRegsSel][field][0].b _ (cAdr=fieldAdr) AND ~rejectBA; p[pipeRegsSel][r3A][0].b _ ~rejectBA; p[pipeRegsSel][cBus][0].b _ ~rejectBA; -- dataIn p[pipeRegsSel][cBus][1].b _ rejectBA; -- r3B <<-- reset PhB regs muxes>> Reset[st2B]; Reset[kReg]; Reset[r2B]; Reset[r3B]; Reset[dataIn]; <<-- States: cycle carry: before ALU op!!!>> IF ~rejectBA AND ~conditionBA THEN carryAB _ carryBA; <<-- alu and cc>> p[op][0].b _ TRUE; -- !!! p[op][1].b _ TRUE; p[op][2].b _ TRUE; p[op][3].b _ TRUE; p[op][4].b _ TRUE; p[carryIn].b _ OpToCarryIn[selAluOps, carryAB]; <<>> <<-- field unit>> p[insert].b _ p[fd][insertFd].b; p[mask].c _ p[fd][maskFd].c; p[shift].c _ p[fd][shiftFd].c; FOR i: NAT IN [0..wordSize+1) DO p[sh][i].b _ p[fd][shiftFd].c=i; ENDLOOP; }; IF p[phB].b THEN { selAluOps: Dragon.ALUOps _ VAL[p[aluOp].c]; overflow: BOOL _ ((p[carryOut].b#p[res][0].b)#(p[opL][0].b#p[opR][0].b)); lz: BOOL _ (p[carryOut].b#(p[opL][0].b#p[opR][0].b)); il: BOOL _ p[opL].c IN (0..7) OR p[opR].c IN (0..7) OR p[res].c IN (0..7); <<-- States: latch reject ASAP>> rejectBA _ p[reject].b; <<-- drive PBus>> p[enWrtPBus].b _ FALSE; -- work on this!!! <<-- drive KBus>> p[enWrtIFU].b _ FALSE; -- IFU sends addresses and control, so wait <<-- drive condition and set carry>> p[condition].b _ SELECT Dragon.CondSelects[VAL[p[condSel].c]] FROM False => FALSE, EZ => p[zero].b, LZ => lz, LE => p[zero].b OR lz, AddressCheckFault => p[res].c=0, NE => ~p[zero].b, GE => ~lz, GZ => ~(p[zero].b AND lz), OvFl => overflow, BC => p[carryOut].b, IL => il, NotBC => ~p[carryOut].b, NotIL => ~il, ModeFault => TRUE, ENDCASE => ERROR; <<-- ALU and Field Unit: just wait since they are combinatorial and started on PhA>> carryBA _ OpToCarryOut[selAluOps, p[carryOut].b, carryBA]; <<-- lower all select lines>> FOR i: NAT IN [0.. nRows) DO p[selA][i].b _ p[selB][i].b _ p[selC][i].b _ FALSE; ENDLOOP; FOR i: NAT IN [0.. sizeSelLow) DO p[selALow][i].b _ p[selBLow][i].b _ p[selCLow][i].b _ FALSE; ENDLOOP; <<-- set PhB regs muxes>> p[pipeRegsSel][st2B][0].b _ TRUE; p[pipeRegsSel][kReg][0].b _ ~p[reject].b; p[pipeRegsSel][kReg][1].b _ p[reject].b; -- cAdr _ euMAR p[pipeRegsSel][r2B][0].b _ ~(p[aluOp].c=bndCheck OR p[aluOp].c=fop); p[pipeRegsSel][r2B][1].b _ p[aluOp].c=fop; p[pipeRegsSel][r2B][2].b _ p[aluOp].c=bndCheck; p[pipeRegsSel][r3B][0].b _ p[res3BisP].b; -- address p[pipeRegsSel][dataIn][0].b _ p[res3BisP].b; -- data from cache, or junk <<-- reset PhA regs muxes>> Reset[left]; Reset[right]; Reset[st2A]; Reset[st3A]; Reset[field]; Reset[r3A]; }; }}; END.