-- MOSSIMCharFIFOImpl.sak
-- last edited by Suzuki: 15-Dec-81  9:56:17

DIRECTORY
  Connector: TYPE, 
  MOSSIMFIFO: TYPE, 
  MOSSIMFunc: TYPE, 
  Process: TYPE;

MOSSIMCharFIFOImpl: MONITOR
  IMPORTS Connector, MOSSIMFunc, Process
  EXPORTS MOSSIMFIFO
  
  = 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, Done: 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; 
       Connector.ProcessEnd[]}; 
    criticalSection2: ENTRY PROC = {
      Connector.MOSSIMSet[Init]; 
      Connector.MOSSIMSet[WriteRequest]; 
      Connector.MOSSIMSet[ReadRequest]; 
      Connector.MOSSIMSet[DIn]; 
      MOSSIMFunc.Step[]; 
      MOSSIMFunc.CharGet[DOut]; 
      Connector.MOSSIMGet[SpaceAv]; 
      Connector.MOSSIMGet[DataAv]; 
      };
    p: PROCESS; 
    p ← Connector.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"];
    MOSSIMFunc.CharMultiConnectInit[DOut, 16];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO0", 0];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO1", 1];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO2", 2];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO3", 3];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO4", 4];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO5", 5];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO6", 6];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO7", 7];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO8", 8];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO9", 9];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO10", 10];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO11", 11];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO12", 12];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO13", 13];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO14", 14];
    MOSSIMFunc.CharMultiConnectAssign[DOut, "DO15", 15];
    {st1: PROC = {DO Connector.GetNew[ReadRequest, TRUE]; criticalSection2[]; 
                    Connector.GetNew[ReadRequest, FALSE]; criticalSection2[]
                    ENDLOOP; 
                  Scheduler.ProcessEnd[]}; 
     process1: PROCESS; 
     process1 ← Scheduler.Fork[st1]; 
     DO Connector.GetNew[WriteRequest, TRUE]; criticalSection2[]; 
       Connector.GetNew[WriteRequest, FALSE]; criticalSection2[]
       ENDLOOP; 
    [] ← Scheduler.Join[process1]};
    Process.Abort[p]; 
    [] ← Connector.Join[p]; 
    Connector.ProcessEnd[]};
  
  MAIN[]; 
  NULL
  
  END.