<> <> <> <> <> <> <<>> <<>> DIRECTORY Convert, DynaStats, DisplayModel, DynaSeer, FIFO, IO, Real; DisplayModelImpl: CEDAR PROGRAM IMPORTS Convert, DynaStats, DynaSeer, FIFO, IO, Real EXPORTS DisplayModel ~ BEGIN OPEN DisplayModel; DisplayState: TYPE = REF DisplayStateRec; DisplayStateRec: TYPE = RECORD [ displayAddress: INT _ 0, underflowCount: INT _ 0, cyclesToMonitorRequest: INT _ 0, monitorRequestInterval: INT _ 0, -- 0 => display inactive inputFIFO: FIFO.FIFO, fifoLowWaterMark, fifoHighWaterMark, fifoSize: INT _ 0 ]; mri: INT _ 0; defaultMri: INT = Real.Fix[625/DynaSeer.busCycle]; fifoLWM, fifoHWM, fifoS: INT _ 0; <> Init: PUBLIC PROC [handle: Handle] = { mri _ DynaSeer.GetIntParm[handle.in, handle.out, "\nInterval (in cycles) between monitor requests (0 => display inactive):", defaultMri]; IF mri=0 THEN RETURN; fifoLWM _ DynaSeer.GetIntParm[handle.in, handle.out, "Fifo low-water-mark (#entries)", 4]; WHILE (fifoHWM _ DynaSeer.GetIntParm[handle.in, handle.out, "Fifo high-water-mark (#entries)", 8]) < fifoLWM DO IO.PutRope[handle.out, "\nfifoHighWaterMark must be >= fifoLowWaterMark"]; ENDLOOP; WHILE (fifoS _ DynaSeer.GetIntParm[handle.in, handle.out, "Fifo size (#entries)", 12]) < fifoHWM DO IO.PutRope[handle.out, "\fifoSize must be >= fifoHighWaterMark"]; ENDLOOP; }; CreateDisplay: PUBLIC PROC [deviceId: DeviceId] RETURNS [device: Device] = { device _ DynaSeer.CreateDevice[]; device.deviceId _ deviceId; device.state _ NEW [DisplayStateRec]; device.init _ InitDisplay; device.cycle _ CycleDisplay; }; InitDisplay: PUBLIC DynaSeer.InitProc = { cs: DisplayState _ NARROW[device.state]; cs.displayAddress _ 0; cs.underflowCount _ 0; cs.cyclesToMonitorRequest _ cs.monitorRequestInterval _ mri; cs.inputFIFO _ FIFO.Create[]; cs.fifoLowWaterMark _ fifoLWM; cs.fifoHighWaterMark _ fifoHWM; cs.fifoSize _ fifoS; }; CycleDisplay: PUBLIC DynaSeer.CycleProc = { myState: DisplayState _ NARROW[device.state]; myId: DeviceId _ device.deviceId; GenerateDisplayRequest: PROC [p: Priority] RETURNS [Request] = { rbRqstCycle: Cycle _ DynaSeer.MakeCycle[RBRqst, myId, myId, myState.displayAddress]; myState.displayAddress _ myState.displayAddress+1; RETURN [DynaSeer.MakeRequest[Two, rbRqstCycle, p]]; }; TreatBusCycle: PROC [cycle: Cycle] = { IF cycle.cmd=RBRply AND cycle.deviceId=myId THEN { IF FIFO.Size[myState.inputFIFO] > myState.fifoSize THEN IO.PutRope[handle.out, "\n**Display FIFO overflow**"]; FIFO.Put[myState.inputFIFO, cycle]; } }; CheckMonitorRequest: PROC [] = { IF (myState.cyclesToMonitorRequest _ myState.cyclesToMonitorRequest-1)<=0 THEN { fifoCycle: Cycle _ NARROW[FIFO.Get[myState.inputFIFO]]; IF fifoCycle=NIL THEN { myState.underflowCount _ myState.underflowCount + 1; IO.PutF[handle.out, "\n**Display FIFO underflow** (count: %g, cycle: %g)", [integer[myState.underflowCount]], [integer[handle.cycleNumber]] ]; }; myState.cyclesToMonitorRequest _ myState.monitorRequestInterval } }; IF myState.monitorRequestInterval=0 THEN RETURN; TreatBusCycle[cycle]; CheckMonitorRequest[]; IF DynaStats.PrintIt[handle] THEN { IO.PutRope[handle.out, " Display FIFO: "]; IO.PutRope[handle.out, Convert.RopeFromInt[FIFO.Size[myState.inputFIFO]]] }; IF FIFO.Size[myState.inputFIFO]