
#INCLUDE "/home/amu5/users/georget/Phd/Simul/Defs/defs.inc"
#INCLUDE "hostio.inc"

PROC Mem(CHAN OF BUNDLE MemDabt0, MemDabt1, AMemDabt1, AMemDabt0, 
                        MrrDin, MrrPAbtin, MrrAin,
                        MEMad, MEMd, MEMc, MEMa,
           CHAN OF INT To.memory,
         []CHAN OF DEB.MESSAGE screen,CHAN OF BYTE Out.Char,
         CHAN OF [3]INT Read.Write, VAL INT report)

  #USE "hostio.lib"
  #USE "debug.lib"
  #USE "string.lib"
  #USE "convert.lib"
  #USE "/home/amu5/users/georget/Phd/Simul/library"
  

  [MEMSIZE]INT memory.array:
  [4]BYTE instr:
  INT32 fileid:
  INT length,len, hex.instr,out.data,mask, start, finish, num.of.instructions, duration, clock0, clock1, clock2, clock3:
  INT location, i, address, contents:
  BYTE result,temp0,temp1,char:
  BOOL e.o.f,end,finish1,sink.request,Dabort1,Dabort0,Pabort,AddOR1,AddOR2,AddOR3,AddOR4,term: 
  [32]BOOL Ctrlb,Addressb :
  [MESGLEN]INT in.Data,Address,Ctrl,Pabt,out.Data,Ackmrr, Ackmem, AAbt,MAbt:
  TIMER clock:
  [15]INT delay:

  VAL []INT masks IS [#000000FF, #0000FF00, #00FF0000, #FF000000]:
  -------------------------------------------------------------------------
  PROC calculate.delays()
    SEQ
      delay[0]:=SELECT+SELECT
      delay[1]:=SELECT
      delay[2]:=SELECT
      delay[3]:=SELECT
      delay[4]:=XOR
      delay[5]:=XOR+SELECT
      delay[6]:=SELECT
      delay[7]:=SELECT
      delay[8]:=0
      delay[9]:=(SRAM.DELAY+XOR)+XOR
      delay[10]:=XOR
  :
  
  ------------------------------------------------------------
  PROC init.memory()
    INT i:
    SEQ
      SEQ i=0 FOR SIZE memory.array 
        SEQ
          To.memory?memory.array[i]
  :
  ------------------------------------------------------------
  PROC read()
    SEQ
      location:=(Address[0]) >> 2 
      debugmsg(report,screen[0], "MEMORY: READ location is :", [location,0,0,0])        
      --out.data:= memory.array[location] 
      Read.Write![READ, (location*4), 0]
      To.memory?out.data  
      debugmsg(report,screen[0], "MEMORY: READ contents are:", [out.data,0,0,0])        
  :
  ------------------------------------------------------------
  PROC write()
    SEQ
      
      --location:=Address[0] /\ #FFFFFFFC
      location:=(Address[0]) >> 2 
      debugmsg(report,screen[0], "MEMORY: WRITE location is :", [location,0,0,0])
      
      IF
        Ctrlb[1] = TRUE         --byte
          SEQ  
            Read.Write![READ, (location*4), 0]                --get current contents
            To.memory?contents  
            contents:=((contents /\ (~mask)) \/ (in.Data[0]/\mask))  --update it
            Read.Write![WRITE, (location*4), contents]               --write back
      
        Ctrlb[1] = FALSE         --word
          SEQ 
            contents:=in.Data[0] 
            Read.Write![WRITE, (location*4), contents]
               

  :
  -------------------------------------------------------------
  SEQ
    Ackmem[0]:=0
    --init.memory()
    num.of.instructions:=0
    clock?start
    calculate.delays()


                    --Read Address+data+control from DatInt
    MEMad?Address
    address:=Address[0]
    debugmsg(report,screen[0], "MEMORY: receive address:", Address) 
    Pabt[0]:=0
    IF
      Address[0]<>FINISH
        PAR
          MEMd?in.Data
          MEMc?Ctrl          --[Seq, Inc, Ren, Wen, Usr, B/W, Opc] 
                             --  6    5    4    3    2    1    0
      Address[0]=FINISH
        SEQ
          end:=TRUE

    WHILE end=FALSE
      SEQ
        clock3:=Address[TIME.STAMP]

        int.to.bool(Ctrl[0], Ctrlb)
        IF
          Ctrlb[0]=TRUE
            SEQ
              num.of.instructions:=num.of.instructions+1
          TRUE
            SKIP
        SEQ
          -----------------------------------------------------------------------
          --                          MMU
          -----------------------------------------------------------------------
          sink.request:=FALSE
          Dabort1:=FALSE
          Dabort0:=FALSE
          Pabort:=FALSE

          
          int.to.bool(Address[0], Addressb)
          --AddOR1:=((Addressb[31] OR Addressb[30]) OR (Addressb[29] OR Addressb[28]))
          --AddOR2:=((Addressb[27] OR Addressb[26]) OR (Addressb[25] OR Addressb[24]))
          --AddOR3:=((Addressb[23] OR Addressb[22]) OR (Addressb[21] OR Addressb[20]))
          --AddOR4:=((Addressb[19] OR Addressb[18]) OR (Addressb[17] OR Addressb[16]))
          --Pabort:=((AddOR1 OR AddOR2) OR (AddOR3 OR AddOR4))
          clock0:=clock3+ delay[2]  --SELECT
          IF
           
            --------------------------------
            (NOT(Ctrlb[0] OR Ctrlb[5]))=TRUE
              SEQ
                debugmsg(report,screen[1], "MEMORY: Opc NOR Inc is TRUE aborts enable", NULL1)
                debugmsg(report,screen[1], "MEMORY: PABORT IS ..........", [(INT Pabort),0,0,0])
                clock0:=clock0+delay[3]  --SELECT
                IF 
                  --------------------------------------
                  Pabort=TRUE
                    SEQ
                      Dabort1:=TRUE
                      Dabort0:=FALSE
                      clock0:=clock0+delay[3]  --SELECT

                      IF 
                        ---------------------------------
                        Ctrlb[4]=FALSE     --write abort
                          SEQ
                            sink.request:=TRUE                       
                        Ctrlb[4]=TRUE
                          SEQ
                            SKIP
                  ---------------------------------
                  Pabort=FALSE
                    SEQ
                      clock0:=clock0+delay[4]  --XOR
                      Dabort1:=FALSE
                      Dabort0:=TRUE
                      SKIP
              --------------------------------
            (NOT(Ctrlb[0] OR Ctrlb[5]))=FALSE    --No aborts
              SEQ
                debugmsg(report,screen[1], "MEMORY: Opc NOR Inc is FALSE No aborts ", NULL1)

                SKIP
     
                           

          -------------------------------------------------------------------------------
          PAR
            ---------------------------------------------------------------------
            SEQ                                   --send aborts if required
              IF
                ((Dabort1=TRUE) AND (Dabort0=FALSE))
                  SEQ
                    clock1:=clock3+delay[0]   --SELECT+SELECT
                    MAbt[TIME.STAMP]:=clock1
                    AAbt[TIME.STAMP]:=clock1
                    debugmsg(report,screen[1], "MEMORY: Waiting to send Daborts1", NULL1)
                    PAR
                      MemDabt1 !MAbt
                      AMemDabt1!AAbt
                    debugmsg(report,screen[1], "MEMORY: sent Daborts1", NULL1)
                ((Dabort1=FALSE) AND (Dabort0=TRUE))
                  SEQ
                    clock1:=clock3+delay[0]   --SELECT+SELECT
                    MAbt[TIME.STAMP]:=clock1
                    AAbt[TIME.STAMP]:=clock1
                    debugmsg(report,screen[1], "MEMORY: Waiting to send Daborts0", NULL1)
                    PAR
                      MemDabt0 !MAbt
                      AMemDabt0!AAbt
                    debugmsg(report,screen[1], "MEMORY: sent Daborts0", NULL1)
                ((Dabort1=FALSE) AND (Dabort0=FALSE))
                  SEQ
                    debugmsg(report,screen[1], "MEMORY:  dont send  Daborts", NULL1)
                    clock1:=clock3+delay[1] --SELECT
                    SKIP
            ---------------------------------------------------------------------

            -----------------------------------------------------------------------
            --                          MEMORY
            -----------------------------------------------------------------------
          
            SEQ 
              clock2:=clock0
              IF
                sink.request=FALSE
                  SEQ                     
                    mask:= masks[(Address[0])/\3]    --remember mask for writes
                    clock2:=clock2+delay[5]  --XOR+SELECT

                    IF

                      Ctrlb[4] = TRUE             -- read
                        -----------------------------------------------------------------
                        SEQ
                          read()
                          out.Data[0]:=out.data
                          Pabt[TIME.STAMP]:=clock2
                          out.Data[TIME.STAMP]:=clock2
                          out.Data[STALL]:=-1
                          debugmsg(report,screen[0], "MEMORY:  data.out is", out.Data)

                          PAR
                            SEQ
                              init.hex(Pabt[0], [Pabort])
                              MrrPAbtin! Pabt
                            MrrDin!out.Data
                          MrrAin?Ackmrr
                          clock2:=Ackmrr[TIME.STAMP]+delay[6]  --SELECT
                          --debugmsg(report,screen[0], "MEMORY: ack from Mrr received...",NULL1)
                          IF
                            Ctrlb[3] = TRUE       -- read+write
                              SEQ
                                write()
                                clock2:=clock2+delay[9]  --SRAM.DELAY+XOR+XOR
                            TRUE
                              SKIP


                      Ctrlb[4] = FALSE            --write
                        -----------------------------------------------------------------
                        SEQ
                          clock2:=clock2+delay[7]  --SELECT
                          IF
                            (Addressb[14] AND Addressb[15])=TRUE   --Tube-address: #0000C000
                              -----------------------------------------------------------------
                              SEQ
                                clock2:=clock2+delay[7]  --SELECT

                                IF

                                  (Addressb[13])=TRUE  --***!!! INTERRUPTS NOT IMPLEMENTED YET !!!***
                                    -----------------------------------------------------------------
                                    SEQ
                                      --int.generator()
                                      debugmsg(report,screen[0], "MEMORY: REQUEST FOR INTERRUPT!!!!",NULL1)
                                      SKIP
                                  (Addressb[13])=FALSE    -- TUBAS TUBAS TUBAS
                                    -----------------------------------------------------------------
                                    SEQ   -- print out character
                                      clock2:=clock2+TUBAS.DELAY
                                      IF
                                        (in.Data[0] /\ #000000FF)=4
                                          SEQ   
                                            char := BYTE (in.Data[0]/\#000000FF)
                                            PAR
                                              Out.Char!char
                                              Read.Write![Address[TIME.STAMP], 0, 0]
                                            term:=TRUE
                                            clock?finish
                                            duration:=finish MINUS start

                                            debugmsg(report,screen[0], "MEMORY: ---- PROGRAM TERMINATED ---- ",NULL1)
                                        (in.Data[0] /\ #000000FF)<>4
                                          SEQ
                                            char := BYTE (in.Data[0]/\#000000FF)
                                            Out.Char!char
                                            debugmsg(report,screen[0], "MEMORY: printing char....",in.Data)
                           

                            (Addressb[14] AND Addressb[15])=FALSE
                              -----------------------------------------------------------------
                              SEQ
                                clock2:=clock2+delay[9]  --SRAM.DELAY+XOR+XOR

                                write()
                sink.request=TRUE
                  SEQ
                    SKIP
              Ackmem[TIME.STAMP]:=clock2+delay[10]  --XOR
              debugmsg(report,screen[0], "MEMORY: sending ack back to processor",Ackmem)
              IF
                term=TRUE
                  SEQ
                    debugmsg(report,screen[0], "MEMORY: end=TRUE sending FINISH ack back to processor",Ackmem)
                    Ackmem[0]:=FINISH
                    term:=FALSE
                TRUE
                  SKIP                
              MEMa!Ackmem                    --finish memory cycle-send ack to processor
              debugmsg(report,screen[0], "MEMORY: sent ack back to processor",Ackmem)

          ---------------------------------------------------------------------
        --IF
          --end=FALSE
            --SEQ
        MEMad?Address           --Read Address+data+control from DatInt
        address:=Address[0]

        debugmsg(report,screen[0], "MEMORY: receive address:", Address) 
        IF
          Address[0]<>FINISH
            PAR
              MEMd?in.Data
              MEMc?Ctrl          --[Seq, Inc, Ren, Wen, Usr, B/W, Opc] 
                                       --  6    5    4    3    2    1    0
          Address[0]=FINISH
            SEQ
              end:=TRUE


    --end WHILE


    out.Data[0]:=FINISH    --KILL Mrr register
    MrrDin!out.Data

    debugmsg(report,screen[0], "MEMORY: Instructions executed ",[num.of.instructions,0,0,0])
    debugmsg(report,screen[0], "MEMORY:  Time spent ",[duration,0,0,0])
    debugmsg(report,screen[0], "MEMORY: END OF PROGRAM EXECUTION ....",NULL1)
              
    --finish1:=FALSE   -- now produce KILL signal!!

             --out.Data[0]:=FINISH    --KILL Mrr register
             --MrrDin!out.Data

              --MEMad?Address
              --IF
                --Address[0]<>FINISH    
                  --SEQ
                   -- PAR
                     -- MEMd?in.Data
                      --MEMc?Ctrl 

                    --out.Data[0]:=FINISH
                    --MrrPAbtin! Pabt    --send end to MRR
                    --MrrDin!out.Data
                    --MrrAin?Ackmrr         --no acknowledge back!!!!!!! the other end is dead!!! 
   
                    --Ackmem[0]:=FINISH   --inform MemCtrl that end has been encountered
                   -- MEMa!Ackmem                       
                --Address[0]=FINISH
                  --SEQ
                    --finish1:=TRUE

              --WHILE finish1 = FALSE
                --SEQ
                  --MEMad?Address
                  --IF
                    --Address[0]<>FINISH    --sink new addresses arriving from the prosessor and wait to be killed 
                      --SEQ
                        --PAR
                          --MEMd?in.Data
                          --MEMc?Ctrl           
                        --MEMa!Ackmem                       
                    --Address[0]=FINISH
                      --SEQ
                        --finish1:=TRUE

:
--------------------------------------------------------------------------------
      
 


      
      
      
      

      
