-- File: [Indigo]<Sakura>Dragon>DragonProcessorImpl5.sak
-- Dragon processor with random fetch
-- 10-Mar-82 12:36:24

DIRECTORY
  DragonCache,
  DragonProcessor,
  RandomCard,
  SakuraRT,
  SimIO;
  
DragonProcessorImpl5: MONITOR
  IMPORTS DragonCache, RandomCard, SakuraRT, SimIO 
  EXPORTS DragonProcessor = {

  Processor: PUBLIC DEVICE = {
    IN ClockA, ClockB, Fault, Reject: BOOLEAN, InData: DragonCache.PbusType
    OUT Op: DragonCache.PbusOp, RQ: BOOLEAN, OutData: DragonCache.PbusType
    GUARDIAN {}
    CONTROL {
      
      Store: PROC [loc: CARDINAL, data: LONG CARDINAL]= {
        vp: LONG CARDINAL;
	bl: [0..37B];
	word: [0..3];
	printval: LONG CARDINAL;
	[vp, bl, word] ← SplitAddress[loc];
	printval ← word+bl*4+vp*128;
	WHEN ClockB UP: {
	  RQ ← TRUE;
	  Op ← Store;
	  OutData ← [Instruction[vp, bl, word]]};
	DO
	  WHEN ClockA UP: IF ~Reject THEN EXIT;
	  ENDLOOP;
	SimIO.WF1["    Store started %ld*n", @printval];
	WHEN ClockB UP: OutData ← [Data[data]]; -- Match
	WHEN ClockB UP: RQ ← FALSE;
	SimIO.WF1["    Store finished %ld*n", @printval]};
      
      StoreAndRead: PROC [loc, prevloc: CARDINAL, data, 
          prevdata: LONG CARDINAL] = {
        vp, prevvp: LONG CARDINAL;
	bl, prevbl: [0..37B];
	word, prevword: [0..3];
	printval: LONG CARDINAL;
	[vp, bl, word] ← SplitAddress[loc];
	printval ← word+bl*4+vp*128;
	WHEN ClockB UP: {
	  RQ ← TRUE;
	  Op ← Store;
	  OutData ← [Instruction[vp, bl, word]]};
	DO
	  WHEN ClockA UP: IF ~Reject THEN EXIT;
	  ENDLOOP;
	[prevvp, prevbl, prevword] ← SplitAddress[prevloc];
	SakuraRT.Delay[40];
	DragonCache.CheckVal[prevvp, prevbl, prevword, prevdata];
	SimIO.WF1["    Store started %ld*n", @printval];
	WHEN ClockB UP: OutData ← [Data[data]]; -- Match
	WHEN ClockB UP: RQ ← FALSE;
	SimIO.WF1["    Store finished %ld*n", @printval]};
      
      Fetch: PROC [loc: CARDINAL]= {
        vp: LONG CARDINAL;
	bl: [0..37B];
	word: [0..3];
	printval: LONG CARDINAL;
	[vp, bl, word] ← SplitAddress[loc];
	printval ← word+bl*4+vp*128;
	WHEN ClockB UP: {
	  RQ ← TRUE;
	  Op ← Fetch;
	  OutData ← [Instruction[vp, bl, word]]};
	DO
	  WHEN ClockA UP: IF ~Reject THEN EXIT;
	  ENDLOOP;
	SimIO.WF1["  Fetch started %ld*n", @printval];
	WHEN ClockB UP: RQ ← FALSE;
	SimIO.WF1["  Fetch finished %ld*n", @printval]};
      
      FetchAndRead: PROC [loc: CARDINAL, data: CARDINAL] = {
        vp: LONG CARDINAL;
	bl: [0..37B];
	word: [0..3];
	printval: LONG CARDINAL;
	[vp, bl, word] ← SplitAddress[loc];
	printval ← word+bl*4+vp*128;
	RQ ← TRUE;
	Op ← Fetch;
	OutData ← [Instruction[vp, bl, word]];
	DO
	  WHEN ClockA UP: IF ~Reject THEN EXIT;
	  ENDLOOP;
	SimIO.WF1["  Fetch started %ld*n", @printval];
	WHEN ClockB UP: {
	  SakuraRT.Delay[30];
	  WITH b: InData SELECT FROM
	    Data => IF data # b.data THEN ERROR;
	    ENDCASE => ERROR;
	  RQ ← FALSE};
	SimIO.WF1["  Fetch finished %ld*n", @printval]};
      
      Read: PROC [prevloc: CARDINAL, prevdata: LONG CARDINAL] = {
        prevvp: LONG CARDINAL;
	prevbl: [0..37B];
	prevword: [0..3];
	DO
	  WHEN ClockA UP: IF ~Reject 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: [0..37B], word: [0..3]] = {
	word ← loc MOD 4;
	loc ← loc / 4;
	bl ← loc MOD 40B;
	vp ← loc / 40B};
	  
      i, loc, prevloc: CARDINAL;
      data, prevdata: LONG CARDINAL;
      
      RQ ← FALSE;
      WHEN ClockB UP: NULL;
      WHEN ClockB UP: NULL;
      Store[0, 0];
      FOR i IN [1..1000) DO
        StoreAndRead[i, i-1, i*2, i*2 - 2];
	ENDLOOP;
      Fetch[0];
      FOR i IN [1..1000) DO
        FetchAndRead[i, i*2 - 2];
	ENDLOOP;
      Read[999, 999*2];
      SimIO.WF0["++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"];
      }
    };
    
  }.