-- MOSSIMFIFOImpl.sak
-- last edited by Suzuki: 20-Nov-81 16:02:15

DIRECTORY
  Connector: TYPE, 
  FIFO: TYPE, 
  MOSSIMFunc: TYPE, 
  Process: TYPE, 
  Scheduler: TYPE;

MOSSIMFIFOImpl: MONITOR
  IMPORTS Connector, MOSSIMFunc, Process, Scheduler
  EXPORTS FIFO
  
  = BEGIN
  choice1: Connector.Choice ← Connector.CreateChoice[]; 
  MAIN: PROC = {
    MOSSIMFunc.Read["fifo.sim"];
    }; 
  FIFOFunc: PUBLIC PROC [size: CARDINAL, 
                         Init, WriteRequest, ReadRequest: Connector.Handle, 
                         DIn: Connector.Handle, 
                         SpaceAv, DataAv: Connector.Handle, 
                         DOut: Connector.Handle] = {
    guardian: PROC = 
      {Initialized: BOOLEAN ← FALSE; 
       Connector.RegisterUp[choice1, 1, Init]; 
       Connector.RegisterUp[choice1, 2, ReadRequest]; 
       Connector.RegisterUp[choice1, 3, WriteRequest]; 
       DO SELECT Connector.GetChoice[choice1] FROM 
            1 => 
             {IF NARROW[Connector.Get[ReadRequest], REF BOOLEAN]↑ OR 
                   NARROW[Connector.Get[WriteRequest], REF BOOLEAN]↑ THEN ERROR; 
              Initialized ← TRUE};
            2 => 
             IF NOT Initialized OR NARROW[Connector.Get[Init], REF BOOLEAN]↑ OR 
                  NOT NARROW[Connector.Get[DataAv], REF BOOLEAN]↑ THEN 
                ERROR;
            3 => 
             IF NOT Initialized OR NARROW[Connector.Get[Init], REF BOOLEAN]↑ OR 
                  NOT NARROW[Connector.Get[SpaceAv], REF BOOLEAN]↑ THEN 
                ERROR
            ENDCASE => ERROR
          ENDLOOP; 
       Scheduler.ProcessEnd[]}; 
    p: PROCESS; 
    device: CONDITION; 
    Wait: ENTRY PROC = {WAIT device}; 
    locInit, locWriteRequest, locReadRequest, locDIn, locSpaceAv, locDataAv, locDOut: 
      CARDINAL;
    Scheduler.IncCurrent[]; 
    p ← Scheduler.Fork[guardian]; 
    Connector.MOSSIMConnect[Init, "INITIALIZE"];
    Connector.MOSSIMConnect[WriteRequest, "WR"];
    Connector.MOSSIMConnect[ReadRequest, "RR"];
    Connector.MOSSIMMultiConnectInit[DIn, 16];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI0", 0];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI1", 1];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI2", 2];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI3", 3];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI4", 4];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI5", 5];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI6", 6];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI7", 7];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI8", 8];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI9", 9];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI10", 10];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI11", 11];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI12", 12];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI13", 13];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI14", 14];
    Connector.MOSSIMMultiConnectAssign[DIn, "DI15", 15];
    Connector.MOSSIMConnect[SpaceAv, "SA"];
    Connector.MOSSIMConnect[DataAv, "DA"];
    Connector.MOSSIMMultiConnectInit[DOut, 16];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO0", 0];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO1", 1];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO2", 2];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO3", 3];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO4", 4];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO5", 5];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO6", 6];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO7", 7];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO8", 8];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO9", 9];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO10", 10];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO11", 11];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO12", 12];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO13", 13];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO14", 14];
    Connector.MOSSIMMultiConnectAssign[DOut, "DO15", 15];
    locInit ← Connector.Assign[@device, Init]; 
    locWriteRequest ← Connector.Assign[@device, WriteRequest]; 
    locReadRequest ← Connector.Assign[@device, ReadRequest]; 
    locDIn ← Connector.Assign[@device, DIn]; 
    locSpaceAv ← Connector.Assign[@device, SpaceAv]; 
    locDataAv ← Connector.Assign[@device, DataAv]; 
    locDOut ← Connector.Assign[@device, DOut]; 
    DO
      Wait[]; 
      Connector.MOSSIMSet[Init]; 
      Connector.MOSSIMSet[WriteRequest]; 
      Connector.MOSSIMSet[ReadRequest]; 
      Connector.MOSSIMSet[DIn]; 
      MOSSIMFunc.Step[]; 
      Connector.MOSSIMGet[SpaceAv]; 
      Connector.MOSSIMGet[DataAv]; 
      Connector.MOSSIMGet[DOut]; 
      ENDLOOP;
    Connector.Remove[locInit, Init]; 
    Connector.Remove[locWriteRequest, WriteRequest]; 
    Connector.Remove[locReadRequest, ReadRequest]; 
    Connector.Remove[locDIn, DIn]; 
    Connector.Remove[locSpaceAv, SpaceAv]; 
    Connector.Remove[locDataAv, DataAv]; 
    Connector.Remove[locDOut, DOut]; 
    Process.Abort[p]; 
    [] ← Scheduler.Join[p]; 
    Scheduler.ProcessEnd[]};
  
  MAIN[]; 
  NULL
  
  END.