<> DIRECTORY Basics, BitOps, Core, CoreClasses, CoreCreate, CoreProperties, Ports, Rosemary, RosemaryUser, TamPorts, Rope, TamDefs, TamarinUtilImpl, TamarinUCodeImpl, TerminalIO, IO, Tam, List; TamUCodeCells: CEDAR PROGRAM IMPORTS Ports, Rosemary, TamPorts, BitOps, TamarinUtilImpl, TerminalIO, IO, Tam, Rope = BEGIN OPEN TamDefs, TamPorts; <<-------------------- UCode Rom --------------------->> UCodeState: TYPE = REF UCodeStateRec; UCodeStateRec: TYPE = RECORD [ mi, mil, nUCodeMuxSel, uCodeSel, aAddr, bAddr, precondAddr, newOpcode, nStall, nClock, vdd, gnd: NAT _ LAST[NAT], lastClock: BOOL]; lastMi, lastMil, nextMil: Rope.ROPE; debug: BOOL _ FALSE; UCodeInit: Rosemary.InitProc = { <<>> <<--PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [stateAny: REF ANY _ NIL]-->> state: UCodeState _ NEW[UCodeStateRec]; lastMi _ Tam.uCodeRomA[0]; lastMil _ Tam.uCodeRomA[0]; nextMil _ lastMi; state.lastClock _ FALSE; [state.vdd, state.gnd, state.nClock] _ Ports.PortIndexes[cellType.public, "Vdd", "Gnd", "nClock"]; [state.nUCodeMuxSel, state.aAddr, state.bAddr, state.nStall, state.uCodeSel, state.precondAddr, state.newOpcode] _ Ports.PortIndexes[cellType.public, "nUCodeMuxSel", "aAddr", "bAddr", "nStall", "UCodeSel", "Precond", "newOpcode"]; [state.mi] _ Ports.PortIndexes[cellType.public, "MI"]; [] _ Rosemary.SetFixedWire[cellType.public[state.vdd], H]; [] _ Rosemary.SetFixedWire[cellType.public[state.gnd], L]; stateAny _ state; }; UCodeEvalSimple: Rosemary.EvalProc = { <> XSet: PROC [p: Ports.Port, index: NAT, val: CARD, name: ATOM _ NIL] = { IF HasXs[p, index] THEN { SetPVal[p, index, val]; p[index].d _ none; IF debug OR clockset THEN TerminalIO.PutF["X Input in UCode: %g index: %g \n", IO.atom[name], IO.int[index]]; }; }; clockset: BOOL_ TRUE; aAddr: NAT _ 0; state: UCodeState _ NARROW[stateAny]; <<-- Clear any inputs with X's, setup to go to Reset>> XSet[p, state.nClock, 0, $nClock]; clockset _ PortToBool[p, state.nClock]; IF debug THEN TerminalIO.PutF["nClock: %g \n", IO.int[PortToNat[p, state.nClock]]]; XSet[p, state.aAddr, 8, $aAddr]; XSet[p, state.bAddr, 9, $bAddr]; XSet[p, state.nUCodeMuxSel, 11, $nUCodeMuxSel]; XSet[p, state.uCodeSel, 1, $uCodeSel]; XSet[p, state.nStall, 1, $nStall]; XSet[p, state.precondAddr, 0, $precondAddr]; XSet[p, state.newOpcode, 128, $newOpcode]; IF PortToBool[p, state.nStall] THEN IF PortToBool[p, state.uCodeSel] THEN { -- Use A side of Rom << -- Select the source for the A side Address>> aAddr _ SELECT PortToNat[p, state.nUCodeMuxSel] FROM 7 => PortToNat[p, state.aAddr], 11 => PortToNat[p, state.precondAddr], 13 => BitOps.WordAND[PortToNat[p, state.newOpcode], 0F8H], 14 => PortToNat[p, state.newOpcode], ENDCASE => 0; SELECT PortToNat[p, state.nUCodeMuxSel] FROM 7, 11, 13, 14 => {}; ENDCASE => TerminalIO.PutF["BAD nUCodeMuxSel Mil: %g \n", IO.int[PortToNat[p, state.nUCodeMuxSel]]]; lastMi _ Tam.uCodeRomA[aAddr]; } ELSE -- Use B side of Rom lastMi _ Tam.uCodeRomB[PortToNat[p, state.bAddr]] ELSE lastMi _ lastMil; IF clockset THEN { nextMil _ lastMi; IF debug THEN { TerminalIO.PutF["New Mi: %g \n", IO.rope[lastMi]]; TerminalIO.PutF[" from: %g, Select: %g, addr: %g, baddr: %g, \n", IO.int[PortToNat[p, state.uCodeSel]], IO.int[PortToNat[p, state.nUCodeMuxSel]], IO.int[aAddr], IO.int[PortToNat[p, state.bAddr]]]; }; } ELSE { lastMil _ nextMil; IF debug THEN TerminalIO.PutF["New Mil: %g \n", IO.rope[lastMil]]; }; FOR i: List.LORA _ Tam.uCodeOrder, i.rest WHILE i # NIL DO bitRec: Tam.BitPos _ NARROW[i.first]; bit: NAT _ bitRec.bitPos; SELECT bitRec.bitType FROM latch => p[state.mi].ls[bit] _ TamPorts.CharToLevel[Rope.Fetch[lastMil, bit]]; unlatched => p[state.mi].ls[bit] _ TamPorts.CharToLevel[Rope.Fetch[lastMi, bit]]; both => p[state.mi].ls[bit] _ TamPorts.CharToLevel[Rope.Fetch[lastMi, bit]]; ENDCASE; ENDLOOP; p[state.mi].d _ drive; state.lastClock _ clockset; stateAny _ state; }; <<>> uCodeName: Rope.ROPE = Rosemary.Register[roseClassName: "UCodeRom", init: UCodeInit, evalSimple: UCodeEvalSimple]; END. <<>>