-- File: [Indigo]<Sakura>Dragon>DragonProcessorImpl8.sak
-- Dragon processor with random fetch
-- 23-Mar-82 11:33:38z

DIRECTORY
  DragonCache: TYPE, 
  DragonProcessor: TYPE, 
  SakuraRT: TYPE, 
  SimIO: TYPE;

DragonProcessorImpl8: MONITOR
  IMPORTS DragonCache, SakuraRT, SimIO
  EXPORTS DragonProcessor
  
  = BEGIN
  ProcID: STRING = "Proc1: "; 
  
  Processor: PUBLIC PROC
       [ClockA, ClockB, Fault, Reject: SakuraRT.Handle, InData: SakuraRT.Handle, 
        Op: SakuraRT.Handle, RQ: SakuraRT.Handle, OutData: SakuraRT.Handle] = {
    
    Store: PROC [loc: CARDINAL, data: LONG CARDINAL] = {
      vp: LONG CARDINAL; 
      bl: INTEGER [0..37B]; 
      word: INTEGER [0..3]; 
      printval: LONG CARDINAL;
      [vp, bl, word] ← SplitAddress[loc]; 
      printval ← word + bl * 4 + vp * 128; 
      SakuraRT.GetNew[ClockB, TRUE];
       {SakuraRT.Put[RQ, NEW[BOOLEAN ← TRUE]]; 
        SakuraRT.Put[Op, NEW[DragonCache.PbusOp ← Store]]; 
        SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Instruction[vp, bl, word]]]]}; 
      DO SakuraRT.GetNew[ClockA, TRUE];
          IF NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]↑ THEN EXIT
         ENDLOOP; 
      SimIO.WF2["    %sStore started %ld*n", ProcID, @printval]; 
      SakuraRT.GetNew[ClockB, TRUE];
       SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Data[data]]]]; 
      -- Match
      SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Put[RQ, NEW[BOOLEAN ← FALSE]]; 
      SimIO.WF2["    %sStore finished %ld*n", ProcID, @printval]}; 
    
    StoreAndRead: PROC [loc, prevloc: CARDINAL, data, prevdata: LONG CARDINAL] = {
      vp, prevvp: LONG CARDINAL; 
      bl, prevbl: INTEGER [0..37B]; 
      word, prevword: INTEGER [0..3]; 
      printval: LONG CARDINAL;
      [vp, bl, word] ← SplitAddress[loc]; 
      printval ← word + bl * 4 + vp * 128; 
      SakuraRT.GetNew[ClockB, TRUE];
       {SakuraRT.Put[RQ, NEW[BOOLEAN ← TRUE]]; 
        SakuraRT.Put[Op, NEW[DragonCache.PbusOp ← Store]]; 
        SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Instruction[vp, bl, word]]]]}; 
      DO SakuraRT.GetNew[ClockA, TRUE];
          IF NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]↑ THEN EXIT
         ENDLOOP; 
      [prevvp, prevbl, prevword] ← SplitAddress[prevloc]; 
      SakuraRT.Delay[40]; 
      DragonCache.CheckVal[prevvp, prevbl, prevword, prevdata]; 
      SimIO.WF2["    %sStore started %ld*n", ProcID, @printval]; 
      SakuraRT.GetNew[ClockB, TRUE];
       SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Data[data]]]]; 
      -- Match
      SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Put[RQ, NEW[BOOLEAN ← FALSE]]; 
      SimIO.WF2["    %sStore finished %ld*n", ProcID, @printval]}; 
    
    Fetch: PROC [loc: CARDINAL] = {
      vp: LONG CARDINAL; 
      bl: INTEGER [0..37B]; 
      word: INTEGER [0..3]; 
      printval: LONG CARDINAL;
      [vp, bl, word] ← SplitAddress[loc]; 
      printval ← word + bl * 4 + vp * 128; 
      SakuraRT.GetNew[ClockB, TRUE];
       {SakuraRT.Put[RQ, NEW[BOOLEAN ← TRUE]]; 
        SakuraRT.Put[Op, NEW[DragonCache.PbusOp ← Fetch]]; 
        SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Instruction[vp, bl, word]]]]}; 
      DO SakuraRT.GetNew[ClockA, TRUE];
          IF NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]↑ THEN EXIT
         ENDLOOP; 
      SimIO.WF2["  %sFetch started %ld*n", ProcID, @printval]; 
      SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Put[RQ, NEW[BOOLEAN ← FALSE]]; 
      SimIO.WF2["  %sFetch finished %ld*n", ProcID, @printval]}; 
    
    FetchAndRead: PROC [loc: CARDINAL, data: CARDINAL] = {
      vp: LONG CARDINAL; 
      bl: INTEGER [0..37B]; 
      word: INTEGER [0..3]; 
      printval: LONG CARDINAL;
      [vp, bl, word] ← SplitAddress[loc]; 
      printval ← word + bl * 4 + vp * 128; 
      SakuraRT.Put[RQ, NEW[BOOLEAN ← TRUE]]; 
      SakuraRT.Put[Op, NEW[DragonCache.PbusOp ← Fetch]]; 
      SakuraRT.Put[OutData, NEW[DragonCache.PbusType ← [Instruction[vp, bl, word]]]]; 
      DO SakuraRT.GetNew[ClockA, TRUE];
          IF NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]↑ THEN EXIT
         ENDLOOP; 
      SimIO.WF2["  %sFetch started %ld*n", ProcID, @printval]; 
      SakuraRT.GetNew[ClockB, TRUE];
       {SakuraRT.Delay[30]; 
        WITH b: NARROW[SakuraRT.Get[InData], REF DragonCache.PbusType]↑ SELECT FROM 
          Data => IF data # b.data THEN ERROR
          ENDCASE => ERROR; 
        SakuraRT.Put[RQ, NEW[BOOLEAN ← FALSE]]}; 
      SimIO.WF2["  %sFetch finished %ld*n", ProcID, @printval]}; 
    
    Read: PROC [prevloc: CARDINAL, prevdata: LONG CARDINAL] = {
      prevvp: LONG CARDINAL; 
      prevbl: INTEGER [0..37B]; 
      prevword: INTEGER [0..3];
      DO SakuraRT.GetNew[ClockA, TRUE];
          IF NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]↑ THEN EXIT
         ENDLOOP; 
      [prevvp, prevbl, prevword] ← SplitAddress[prevloc]; 
      SakuraRT.Delay[40]; 
      DragonCache.CheckVal[prevvp, prevbl, prevword, prevdata]}; 
    
    SplitAddress: PROC [loc: CARDINAL] RETURNS [vp: LONG CARDINAL, 
                                                bl: INTEGER [0..37B], 
                                                word: INTEGER [0..3]] = {
      word ← loc MOD 4; 
      loc ← loc / 4; 
      bl ← loc MOD 40B; 
      vp ← loc / 40B}; 
    
    i: CARDINAL; 
    TestNum: CARDINAL = 100;
    
    {ENABLE {ABORTED => GO TO Aborted};
     SakuraRT.Put[RQ, NEW[BOOLEAN ← FALSE]]; 
     SakuraRT.GetNew[ClockB, TRUE]; NULL; 
     SakuraRT.GetNew[ClockB, TRUE]; NULL; 
     Fetch[0]; 
     FOR i IN [1..TestNum) DO
         FetchAndRead[i, i * 2 - 2]
         ENDLOOP; 
     Read[TestNum - 1, (TestNum - 1) * 2]; 
     Store[0, 0]; 
     FOR i IN [1..TestNum) DO
         StoreAndRead[i, i - 1, i * 2, i * 2 - 2]
         ENDLOOP; 
     SimIO.WF1["%s+++++++++++++++++++++++++++++++++++++++++++++++++++*n1000", ProcID]; 
     SakuraRT.ProcessEnd[]}
    EXITS
      Aborted => SakuraRT.Abort[]};
  
  END.