-- File: [Indigo]<Sakura>Dragon>DragonProcessorImpl1.sak
-- Dragon processor with random fetch
--  

DIRECTORY
  DragonCache,
  DragonProcessor,
  SakuraRT,
  SimIO;
  
DragonProcessorImpl1: MONITOR
  IMPORTS 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 {
      Fetch: PROC [vp: LONG CARDINAL, bl: [0..37B], word: [0..3]]= {
        printval: LONG CARDINAL ← 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 [vp: LONG CARDINAL, bl: [0..37B], word: [0..3], data: LONG CARDINAL] = {
        printval: LONG CARDINAL ← 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 [data: LONG CARDINAL] = {
	DO
	  WHEN ClockA UP: IF ~Reject THEN EXIT;
	  ENDLOOP;
	WHEN ClockB UP: SakuraRT.Delay[30];
	WITH b: InData SELECT FROM
	    Data => IF data # b.data THEN ERROR;
	    ENDCASE => ERROR};
	  
      RQ ← FALSE;
      WHEN ClockB UP: NULL;
      WHEN ClockB UP: NULL;
      Fetch[0,0,1];
      FetchAndRead[0,0,2,37777777776B];
      FetchAndRead[0,0,3,37777777775B];
      FetchAndRead[0,1,0,37777777774B];
      Read[37777777773B]
      }
    };
    
  }.