<> <> <> <> <<>> <> <<>> DIRECTORY DynaBusInterface, IO, Ports, Rosemary, RosemaryUser, SCLogic, SCParms; <<>> SCOutputSectionImpl: CEDAR PROGRAM IMPORTS Ports, Rosemary, SCLogic, SCParms EXPORTS SCLogic ~ BEGIN OPEN SCLogic; <> outputSectionName: ROPE = Rosemary.Register[roseClassName: "OutputSection", init: Init, evalSimple: Simple, scheduleIfClockEval: TRUE]; MaxNumSignals: NAT = 30; FIFOSize: NAT = 8; SendStatus: TYPE = {h, d21, d51, d52, d53, d54}; -- output automaton states (see schematic) FIFOIndex: TYPE = [0..FIFOSize); <> State: TYPE = REF StateRec; StateRec: TYPE = RECORD [ sendStatus: SendStatus, grantsPending: NAT, cycleAdrs: LevelSequence _ NEW [LevelSequenceRec[2]], rBuf: RECORD [ presence, ppresence: BOOL, rqstPending: BOOL, header: LevelSequence _ NEW [LevelSequenceRec[SCParms.numBitsPerCycle]], dataHi: LevelSequence _ NEW [LevelSequenceRec[SCParms.numBitsPerWord]], dataLo: LevelSequence _ NEW [LevelSequenceRec[SCParms.numBitsPerWord]] ], fifo: RECORD [ count: [0..FIFOSize], wtPtr, rdPtr: FIFOIndex, header: ARRAY FIFOIndex OF LevelSequence, data: ARRAY FIFOIndex OF LevelSequence ], pClock: Level _ X, ps: Signals -- holds values of signals just before positive going edge ]; <> signals: Signals _ NEW [SignalsRec[MaxNumSignals]]; DataShiftEn: NAT = Declare[signals, "DataShiftEn", X, Input]; SerialIn: NAT = Declare[signals, "SerialIn", X, Input]; DataSerialOut: NAT = Declare[signals, "DataSerialOut", X, Output]; AOw: NAT = Declare[signals, "AOw", X, Input]; Grant: NAT = Declare[signals, "Grant", X, Input]; GLength: NAT = Declare[signals, "GLength", X, Input]; PCtlLdFIFO: NAT = Declare[signals, "PCtlLdFIFO", X, Input]; BCtlLdFIFO: NAT = Declare[signals, "BCtlLdFIFO", X, Input]; RplyStale34: NAT = Declare[signals, "RplyStale34", X, Input]; PCtlSetNonFBTIP: NAT = Declare[signals, "PCtlSetNonFBTIP", X, Input]; PCtlLdRBufHeader: NAT = Declare[signals, "PCtlLdRBufHeader", X, Input]; PCtlLdRBufDataHi: NAT = Declare[signals, "PCtlLdRBufDataHi", X, Input]; PCtlLdRBufDataLo: NAT = Declare[signals, "PCtlLdRBufDataLo", X, Input]; PCtlDrABusRqstBuf: NAT = Declare[signals, "PCtlDrABusRqstBuf", X, Input]; Reset: NAT = Declare[signals, "Reset", X, Input]; Clock: NAT = Declare[signals, "Clock", X, Input]; BCmd: NAT = DeclareS[signals, "BCmd", 4, Xs, Input]; PMode: NAT = Declare[signals, "PMode", X, Input]; DevId: NAT = DeclareS[signals, "DevId", SCParms.numDevIdBits, Xs, Input]; DBus: NAT = DeclareS[signals, "DBus", SCParms.numBitsPerWord, Xs, Input]; RplyHeader: NAT = DeclareS[signals, "RplyHeader", SCParms.numBitsPerCycle, Xs, Input]; FIFOData: NAT = DeclareS[signals, "FIFOData", SCParms.numBitsPerLine, Xs, Input]; ABus: NAT = DeclareS[signals, "ABus", SCParms.numBitsPerWord, Xs, InputOutput]; BDataOut: NAT = DeclareS[signals, "BDataOut", SCParms.numBitsPerCycle, Xs, Output]; HeaderCycleOut: NAT = Declare[signals, "HeaderCycleOut", L, Output]; FIFOOverflow: NAT = Declare[signals, "FIFOOverflow", L, Output]; Request: NAT = DeclareS[signals, "Request", 2, 0, Output]; Vdd: NAT = Declare[signals, "Vdd", X, Power]; Gnd: NAT = Declare[signals, "Gnd", X, Power]; <> SCOutputSection: PUBLIC PROC [] RETURNS [ct: CellType] = { ct _ Create[outputSectionName, signals] }; <> Init: Rosemary.InitProc = { state: State; IF oldStateAny=NIL THEN { state _ NEW [StateRec]; FOR i: FIFOIndex IN FIFOIndex DO state.fifo.header[i] _ NEW [LevelSequenceRec[SCParms.numBitsPerCycle]]; state.fifo.data[i] _ NEW [LevelSequenceRec[SCParms.numBitsPerLine]]; ENDLOOP; state.ps _ NEW [SignalsRec[MaxNumSignals]]; CopySignals[state.ps, signals]; stateAny _ state; } ELSE state _ NARROW[oldStateAny]; IF steady THEN InitState[state]; stateAny _ state; }; Simple: Rosemary.EvalProc = { v: PROC [ix: NAT] RETURNS [BOOL] = { RETURN[p[signals[ix].index].l=H] }; pv: PROC [ix: NAT] RETURNS [BOOL] = { RETURN[state.ps[ix].l=H] }; vs: PROC [ix: NAT] RETURNS [NAT] = { RETURN[Ports.LSToLC[p[signals[ix].index].ls]] }; s: PROC [ix: NAT, l: Level] = { p[signals[ix].index].l _ l }; ss: PROC [ix: NAT, c: CARD] = { IF c=Xs THEN Ports.SetLS[p[signals[ix].index].ls, X] ELSE Ports.LCToLS[c, p[signals[ix].index].ls]; }; LdHdrFromPSide: PROC [hdr: LevelSequence] = { CopyLS[hdr, state.ps[BCmd].ls]; hdr[4] _ L; -- rqst/rply bit hdr[5] _ state.ps[PMode].l; -- pMode bit hdr[6] _ L; -- rplyShd bit CopyLS[hdr, state.ps[DevId].ls, 7]; FOR i: NAT IN [8..SCParms.numBitsPerWord) DO hdr[i] _ L; ENDLOOP; CopyLS[hdr, state.ps[ABus].ls, SCParms.numBitsPerWord]; }; WtFIFO: PROC [] = { wtPtr: FIFOIndex _ state.fifo.wtPtr; IF state.fifo.count=FIFOSize THEN ERROR; -- FIFO Overflow IF pv[BCtlLdFIFO] THEN { -- load header from bside <> numBitsPerWord: NAT _ SCParms.numBitsPerWord; FOR i: NAT IN [0..numBitsPerWord) DO state.fifo.header[wtPtr][i] _ state.ps[RplyHeader].ls[2*i]; state.fifo.header[wtPtr][i+numBitsPerWord] _ state.ps[RplyHeader].ls[2*i+1]; ENDLOOP; } ELSE { -- load header from pside LdHdrFromPSide[state.fifo.header[wtPtr]] }; CopyLS[state.fifo.data[wtPtr], state.ps[FIFOData].ls]; state.fifo.wtPtr _ IF wtPtr=FIFOSize-1 THEN 0 ELSE wtPtr+1; state.fifo.count _ state.fifo.count+1; state.grantsPending _ state.grantsPending+1; }; state: State _ NARROW [stateAny]; OutputsToDefault[p, signals]; SELECT p[signals[Reset].index].l FROM = X => OutputsToX[p, signals]; = H => { InitState[state]; p[signals[ABus].index].d _ none; ss[Request, 0]; s[FIFOOverflow, L]; s[HeaderCycleOut, L]; }; = L => { <> s[DataSerialOut, state.rBuf.dataHi[0]]; IF v[PCtlDrABusRqstBuf] THEN {p[signals[ABus].index].d _ drive; CopyLS[p[signals[ABus].index].ls, state.rBuf.header, SCParms.numBitsPerWord]; } ELSE p[signals[ABus].index].d _ none; IF (v[PCtlLdFIFO] AND v[AOw]) OR v[BCtlLdFIFO] THEN ss[Request, 3] ELSE IF v[PCtlSetNonFBTIP] OR state.rBuf.rqstPending THEN ss[Request, 2]; IF state.grantsPending>0 THEN BEGIN rdPtr: NAT _ state.fifo.rdPtr; OutputH2: PROC [] = { numBitsPerWord: NAT _ SCParms.numBitsPerWord; IF state.rBuf.presence THEN s[HeaderCycleOut, H]; FOR i: NAT IN [0..numBitsPerWord) DO p[signals[BDataOut].index].ls[2*i] _ state.rBuf.header[i]; p[signals[BDataOut].index].ls[2*i+1] _ state.rBuf.header[i+numBitsPerWord]; ENDLOOP; }; OutputD2: PROC [] = { numBitsPerWord: NAT _ SCParms.numBitsPerWord; FOR i: NAT IN [0..numBitsPerWord) DO p[signals[BDataOut].index].ls[2*i] _ state.rBuf.dataHi[i]; p[signals[BDataOut].index].ls[2*i+1] _ state.rBuf.dataLo[i]; ENDLOOP; }; OutputH5: PROC [] = { numBitsPerWord: NAT _ SCParms.numBitsPerWord; IF state.fifo.count>0 AND NOT (v[RplyStale34] AND state.fifo.header[rdPtr][4]=L) THEN s[HeaderCycleOut, H]; CopyLS[state.cycleAdrs, state.fifo.header[rdPtr], SCParms.numBitsPerCycle-1-SCParms.logNumCyclesPerLine]; <> FOR i: NAT IN [0..numBitsPerWord) DO p[signals[BDataOut].index].ls[2*i] _ state.fifo.header[rdPtr][i]; p[signals[BDataOut].index].ls[2*i+1] _ state.fifo.header[rdPtr][i+numBitsPerWord]; ENDLOOP; }; OutputD5: PROC [cycle: NAT] = { cpl: NAT _ SCParms.numCyclesPerLine; cix: NAT _ (Ports.LSToLC[state.cycleAdrs]+cycle) MOD cpl; FOR i: NAT IN [0..SCParms.numBitsPerWord) DO p[signals[BDataOut].index].ls[2*i] _ state.fifo.data[rdPtr][i*2*cpl+2*cix]; p[signals[BDataOut].index].ls[2*i+1] _ state.fifo.data[rdPtr][i*2*cpl+2*cix+1] ENDLOOP; }; SELECT state.sendStatus FROM h => IF v[GLength] THEN OutputH5[] ELSE OutputH2[]; d21 => { IF v[Grant] THEN OutputD2[] ELSE IF v[GLength] THEN OutputH5[] ELSE OutputH2[]; }; d51 => { IF v[Grant] THEN OutputD5[0] ELSE IF v[GLength] THEN OutputH5[] ELSE OutputH2[]; }; d52 => OutputD5[1]; d53 => OutputD5[2]; d54 => OutputD5[3]; ENDCASE => ERROR; END; <<>> <> IF NOT v[Clock] AND NOT clockEval THEN CopyInputValues[state.ps, p]; <<>> <> IF state.pClock=L AND v[Clock] AND NOT clockEval THEN BEGIN ldfifo: BOOL _ (pv[PCtlLdFIFO] AND pv[AOw]) OR pv[BCtlLdFIFO]; presenceCopy: BOOL _ state.rBuf.presence; ppresenceCopy: BOOL _ state.rBuf.ppresence; state.rBuf.ppresence _ presenceCopy; IF pv[PCtlSetNonFBTIP] THEN state.rBuf.presence _ TRUE; IF pv[PCtlSetNonFBTIP] AND ldfifo THEN state.rBuf.rqstPending _ TRUE; IF (pv[PCtlSetNonFBTIP] OR state.rBuf.rqstPending) AND NOT ldfifo THEN state.grantsPending _ state.grantsPending+1; IF pv[PCtlLdRBufHeader] THEN LdHdrFromPSide[state.rBuf.header]; IF pv[DataShiftEn] THEN { FOR i: NAT IN [0..SCParms.numBitsPerWord) DO state.rBuf.dataHi[i] _ state.rBuf.dataHi[i+1] ENDLOOP; state.rBuf.dataHi[SCParms.numBitsPerWord] _ p[signals[SerialIn].index].l; } ELSE IF pv[PCtlLdRBufDataHi] THEN CopyLS[state.rBuf.dataHi, state.ps[DBus].ls]; IF pv[PCtlLdRBufDataLo] THEN CopyLS[state.rBuf.dataLo, state.ps[DBus].ls]; IF ldfifo THEN WtFIFO[] ELSE state.rBuf.rqstPending _ FALSE; <<>> <> SELECT state.sendStatus FROM h => IF pv[GLength] THEN state.sendStatus _ d51 ELSE state.sendStatus _ d21; d21 => { IF pv[Grant] THEN { state.sendStatus _ h; IF NOT pv[PCtlSetNonFBTIP] AND ppresenceCopy THEN { state.rBuf.presence _ FALSE; state.grantsPending _ state.grantsPending-1; } } ELSE {IF pv[GLength] THEN state.sendStatus _ d51}; }; d51 => { IF pv[Grant] THEN state.sendStatus _ d52 ELSE {IF NOT pv[GLength] THEN state.sendStatus _ d21}; }; d52 => IF pv[Grant] THEN state.sendStatus _ d53; d53 => IF pv[Grant] THEN state.sendStatus _ d54; d54 => IF pv[Grant] THEN { rdPtr: NAT _ state.fifo.rdPtr; state.sendStatus _ h; state.grantsPending _ state.grantsPending-1; state.fifo.rdPtr _ IF rdPtr=FIFOSize-1 THEN 0 ELSE rdPtr+1; state.fifo.count _ state.fifo.count-1; }; ENDCASE => ERROR; END; }; ENDCASE; <<>> <> IF NOT clockEval THEN state.pClock _ p[signals[Clock].index].l; }; InitState: PROC [state: State] = { state.sendStatus _ h; state.grantsPending _ 0; state.rBuf.presence _ FALSE; state.fifo.wtPtr _ state.fifo.rdPtr _ state.fifo.count _ 0; state.pClock _ X; }; END.