-- File [Indigo]<Sakura>Dragon>DragonMemoryImpl1.sak
-- 15-Mar-82 11:45:52 

DIRECTORY
  DragonCache: TYPE, 
  DragonMemory: TYPE, 
  SakuraRT: TYPE;

DragonMemoryImpl1: MONITOR
  IMPORTS SakuraRT
  EXPORTS DragonMemory
  
  = BEGIN
  MaxMem: CARDINAL = 4000B; MemType: TYPE = ARRAY INTEGER [0..MaxMem) OF LONG CARDINAL; 
  Mem: REF MemType ← NEW[MemType]; 
  
  Memory: PUBLIC PROC
       [ClockA, ClockB, CMDIn, SharedIn: SakuraRT.Handle, MDataIn: SakuraRT.Handle, 
        MDataOut: SakuraRT.Handle] = {
    i: CARDINAL; 
    CalcData: PROC [rp: LONG CARDINAL, bl: INTEGER [0..37B], word: INTEGER [0..3]]
                   RETURNS [ret: LONG CARDINAL] = {
      ret ← rp * 40B * 4B + bl * 4B + word; 
      ret ← Mem[ret]}; 
    ReadDataFromBus: PROC RETURNS [LONG CARDINAL] = {
      WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]↑ SELECT FROM 
        Data => RETURN [b.data]
        ENDCASE => ERROR};
    {ENABLE {ABORTED => GO TO Aborted};
     FOR i IN [0..MaxMem) DO
         Mem[i] ← 37777777777B - i
         ENDLOOP; 
     DO SakuraRT.GetNew[ClockB, TRUE]; NULL; 
        IF NARROW[SakuraRT.Get[CMDIn], REF BOOLEAN]↑ THEN 
           WITH m: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]↑ SELECT FROM 
             Instruction => 
               {mcom: DragonCache.MbusCommand ← m.command; 
                SELECT mcom FROM 
                  ReadQuad => 
                    {rp: LONG CARDINAL ← m.rp; 
                     bl: INTEGER [0..37B] ← m.bl; 
                     word: INTEGER [0..3] ← m.word; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     IF NARROW[SakuraRT.Get[SharedIn], REF BOOLEAN]↑ THEN LOOP; 
                     SakuraRT.Put[MDataOut, NEW
                       [DragonCache.MbusType ← [Data[CalcData[rp, bl, word]]]]]; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     SakuraRT.Put[MDataOut, NEW
                       [DragonCache.MbusType ← [Data[CalcData[rp, bl, (word + 1) MOD 
                                                                4]]]]]; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     SakuraRT.Put[MDataOut, NEW
                       [DragonCache.MbusType ← [Data[CalcData[rp, bl, (word + 2) MOD 
                                                                4]]]]]; 
                     SakuraRT.GetNew[ClockA, TRUE]; NULL; 
                     SakuraRT.Put[MDataOut, NEW
                       [DragonCache.MbusType ← [Data[CalcData[rp, bl, (word + 3) MOD 
                                                                4]]]]]};
                  WriteQuad => 
                    {rp: LONG CARDINAL ← m.rp; 
                     bl: INTEGER [0..37B] ← m.bl; 
                     word: INTEGER [0..3] ← m.word; 
                     ra: LONG CARDINAL ← rp * 40B * 4B + bl * 4B + word; 
                     SakuraRT.GetNew[ClockB, TRUE]; Mem[ra] ← ReadDataFromBus[]; 
                     SakuraRT.GetNew[ClockB, TRUE]; Mem[ra + 1] ← ReadDataFromBus[]; 
                     SakuraRT.GetNew[ClockB, TRUE]; Mem[ra + 2] ← ReadDataFromBus[]; 
                     SakuraRT.GetNew[ClockB, TRUE]; Mem[ra + 3] ← ReadDataFromBus[]};
                  WriteSingle => NULL;
                  NotReady => ERROR;
                  ReadMap => NULL;
                  ReadMapAndSetRpDirty => NULL;
                  DoMapOp => NULL;
                  SetRpDirty => NULL;
                  MapOpDone => NULL
                  ENDCASE => ERROR};
             MapCommand => 
               SELECT m.command FROM 
                 ReadMap => NULL;
                 ReadMapAndSetRpDirty => NULL;
                 MapOpDone => NULL
                 ENDCASE => ERROR;
             Data => ERROR
             ENDCASE => ERROR
        ENDLOOP; 
     SakuraRT.ProcessEnd[]}
    EXITS
      Aborted => SakuraRT.AbortAll[]};
  
  END.