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

DIRECTORY
  DragonCache,
  DragonMemory,
  SakuraRT;
  
DragonMemoryImpl1: MONITOR 
  IMPORTS SakuraRT
  EXPORTS DragonMemory = {

MaxMem: CARDINAL = 4000B;
MemType: TYPE = ARRAY [0..MaxMem) OF LONG CARDINAL;
Mem: REF MemType ← NEW[MemType];

Memory: PUBLIC DEVICE = {
  IN ClockA, ClockB, CMDIn, SharedIn: BOOLEAN, MDataIn: DragonCache.MbusType
  OUT MDataOut: DragonCache.MbusType
  GUARDIAN {}
  CONTROL {
    i: CARDINAL;
    CalcData: PROC [rp: LONG CARDINAL, bl: [0..37B], word: [0..3]] 
      RETURNS [ret: LONG CARDINAL] = {
      ret ← rp*40B*4B + bl*4B + word;
      ret ← Mem[ret]};
    ReadDataFromBus: PROC RETURNS [LONG CARDINAL] = {
      WITH b: MDataIn SELECT FROM
        Data => RETURN[b.data];
	ENDCASE => ERROR};
    FOR i IN [0..MaxMem) DO
      Mem[i] ← 37777777777B - i
      ENDLOOP;
    DO
      WHEN ClockB UP: NULL;
      IF CMDIn THEN
        WITH m: MDataIn SELECT FROM
          Instruction => {  
  	    mcom: DragonCache.MbusCommand ← m.command;
	    SELECT mcom FROM  
	      ReadQuad => {
	        rp: LONG CARDINAL ← m.rp;
		bl: [0..37B] ← m.bl;
		word: [0..3] ← m.word;
		WHEN ClockA UP: NULL;
		WHEN ClockA UP: NULL;
		WHEN ClockA UP: NULL;
		IF SharedIn THEN LOOP;
		MDataOut ← [Data[CalcData[rp, bl, word]]];
		WHEN ClockA UP: NULL;
		MDataOut ← [Data[CalcData[rp, bl, (word+1) MOD 4]]];
		WHEN ClockA UP: NULL;
		MDataOut ← [Data[CalcData[rp, bl, (word+2) MOD 4]]];
		WHEN ClockA UP: NULL;
		MDataOut ← [Data[CalcData[rp, bl, (word+3) MOD 4]]]};  
	      WriteQuad => { 
	        rp: LONG CARDINAL ← m.rp;
		bl: [0..37B] ← m.bl;
		word: [0..3] ← m.word;
		ra: LONG CARDINAL ← rp*40B*4B + bl*4B + word;
		WHEN ClockB UP: Mem[ra] ← ReadDataFromBus[];
		WHEN ClockB UP: Mem[ra+1] ← ReadDataFromBus[];
		WHEN ClockB UP: Mem[ra+2] ← ReadDataFromBus[];
		WHEN ClockB UP: 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}
};
  
}.