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


PROC AddC(CHAN OF BUNDLE frompcpipe,fromapipe,fromlsreg,W,Wc,MA,MAc,LSMP,
          MAa,Pca,Wa,WLx,APa,LSMPa,LSMa,CHAN OF DEB.MESSAGE screen,
          VAL INT report, evaluate, preemption) 

  BOOL pcparchanged, end,Ren,Wen,oldPCpar,PCpar,Nusr,Sp, Lsm, Opc, Ntrm,
       dPc,lsmpc,dPCc,ToInc,LSin, finish, found, term, first:

  [32]BOOL Ctrlb, Dec1ctrlb:  
  [10]BOOL Ctrl1b:

  [MESGLEN]INT Ctrl,Data,Wdata.occ,Pcdata.occ,ack, ackw:
  TIMER clock:
  VAL INT delays IS 2343:   --0.5 sec
  INT time, previous.report, preempt.frequency, preempt.magnitude, accum.preempt, clock0, msgnum :

  [5][OCCT.SIZE][OCCT.COL]INT occupancy.table:  --an array of occupancy tables!!!!
  [20]INT delay:
  VAL INT process.id IS ADDC.ID:

  -------------------------------------------------------------------------
  PROC calculate.delays()
    SEQ
      delay[0]:=(XOR+ARBITER)+SELECT
      delay[1]:=ARBITER+SELECT
      delay[2]:=SELECT
      delay[3]:=CALLR+CALLR
      delay[4]:=(MULLERC+CALLR)+CALLR
      delay[5]:=CALLA+CALLA
      delay[6]:=((CALLA+CALLA)+XOR)+XOR
      delay[7]:=SELECT+XOR
      delay[8]:=(MULLERC+CALLR)+CALLR
      delay[9]:=((((CALLA+CALLA)+SELECT)+SELECT)+XOR)+XOR
      delay[10]:=MULLERC + XOR
      delay[11]:=(MULLERC+CALLR)+CALLR
      delay[12]:=CALLR+CALLR
      delay[13]:=(CALLA+CALLA)+XOR
      delay[14]:=XOR
  :
  -----------------------------------------------------------------------------
  -------------------------------------------------------------------------
  PROC  initialize.occup.tables()
    SEQ
      initialize.occup.table(occupancy.table[0], PCREGPIPE, PCREGPIPE.SIZE,REGISTER.DELAY)  
      initialize.occup.table(occupancy.table[1], LSMREG, LSMREG.SIZE,REGISTER.DELAY)  
      initialize.occup.table(occupancy.table[2], APIPE,APIPE.SIZE ,REGISTER.DELAY)  
      initialize.occup.table(occupancy.table[3], DEC1REGA,DEC1REGA.SIZE ,REGISTER.DELAY)  
      initialize.occup.table(occupancy.table[4], WCTRLREG,WCTRLREG.SIZE ,REGISTER.DELAY)  
  :
  -------------------------------------------------------------------------

  PROC mkpcc()
    SEQ
      init.hex(Ctrl[0], [PCpar,VSS,VDD, VDD, VSS, Nusr, VSS,VDD, VDD, Opc])

      int.to.bool(Ctrl[0], Ctrlb)      
      Wen:=Ctrlb[7]
      Ren:=Ctrlb[6]
      Opc:=Ctrlb[3]
  :

  -----------------------------------------------------------------------------
  PROC rpcpipe()

    [MESGLEN]INT ack:
    
    SEQ
      IF 
        term =FALSE  --term is always FALSE
          -----------------------------------------------------------------------
          SEQ
            IF
              pcparchanged=FALSE          --ignore the first after the parity change
                SEQ
                  Data[TIME.STAMP]:=clock0 + delay[12]  --CALL+CALL
                  Ctrl[TIME.STAMP]:=clock0 + delay[12]  --CALL+CALL
                  Data[STALL]:=(-1)
                  mkpcc()                 -- make PCc
                  PAR                     -- to/from the register
                    MA!Data
                    MAc!Ctrl
                  MAa? ack 
                  ------------------------------------
                  IF 
                    ack[0]=FINISH
                      SEQ
                        debugmsg(report,screen, "ADDINT-AddC: rpcpipe() Ack FINISH received",ack)
                        debugmsg(report,screen, "ADDINT-AddC: occupancy [1] is", [(occupancy.table[0][0][2]),0,0,0])

                        terminate(evaluate, ack[TIME.IN],NO.KILL, FLUSH, occupancy.table, screen, [MA])
                        debugmsg(report,screen, "ADDINT-AddC: occupancy [1] is", [(occupancy.table[0][0][2]),0,0,0])

                        ack[0]:=0
                        --term:=TRUE
                    TRUE
                      SKIP
                  -------------------------------------

                  debugmsg(report,screen, "ADDINT-AddC: For Address sent to memory", Data)
                  debugmsg(report,screen, "ADDINT-AddC: ack has been received from memory", ack)

                  clock0:=ack[TIME.STAMP]+delay[13]  --CALL+CALL+XOR                  
              TRUE
                SEQ
                  clock0:=clock0+delay[14]   --XOR
                  debugmsg(report,screen, "ADDINT-AddC: reject PC after pcpar changed ", Data)
                  pcparchanged:=FALSE
        term =TRUE
          -----------------------------------------------------------------------
          SEQ            --sink instruction addresses after finish.ack has been received
            SKIP   

      SEQ
        IF
          first=FALSE
            -------------------------------------------------------
            SEQ  
              ack[TIME.STAMP]:=clock0
              debugmsg(report,screen, "ADDINT-AddC: clock0 is", [clock0,0,0,0])
              debugmsg(report,screen, "ADDINT-AddC: Pcdata.occ is", Pcdata.occ)
              debugmsg(report,screen, "ADDINT-AddC: occupancy [1] is", [(occupancy.table[0][0][2]),0,0,0])
              debugmsg(report,screen, "ADDINT-AddC: waiting to send ack to pca for PC", Data)
              Pca!ack                   -- to the pcreg pipe
              debugmsg(report,screen, "ADDINT-AddC: send ack to pca for PC", Data)         
              calculate.occupancy(evaluate, occupancy.table[0], clock0, Pcdata.occ) 
          first=TRUE
            -------------------------------------------------------  do not acknowledge address 0!!!
            SEQ   
              first:=FALSE    
  :
  --------------------------------------------------------------------------

  PROC mkwac()

    SEQ
      int.to.bool(Ctrl[0],Ctrlb)
      lsmpc:=(Ctrlb[8] AND dPc)
      dPCc:=(lsmpc OR Ctrlb[1])
      Ctrl1b[0]:=Ctrlb[0]
      Ctrl1b[1]:=dPCc
      [Ctrl1b FROM 2 FOR 6]:=[Ctrlb FROM 2 FOR 6]
      LSin:=(Ctrlb[8] AND Ntrm)
      ToInc:=(LSin OR  Ctrlb[3])
      Ctrl1b[8]:=ToInc
      Ctrl1b[9]:=VSS
      init.hex(Ctrl[0], Ctrl1b)

      int.to.bool(Ctrl[0], Ctrlb)      
      Wen:=Ctrlb[7]
      Ren:=Ctrlb[6]
      Opc:=Ctrlb[3]

      ---initial implementation follows.....
      --get.bit(OPC, Ctrl[0],Opc)
      --get.bit(WEN, Ctrl[0],Wen)
      --get.bit(REN, Ctrl[0],Ren)      
      --set.bit(LSM, INT ((Opc OR (Lsm AND Ntrm))), Ctrl[0]) 
      --set.bit(SP, IVSS, Ctrl[0])  --Lsm  is 1 anyway
  : 


  ----------------------------------------------------------------------------
 
  PROC rwbus()
  
    [MESGLEN]INT ack,ackw: 
     
    SEQ
      mkwac()                         --make Wctrl 
      Data[TIME.STAMP]:=clock0
      Data[STALL]:=(-1)

      PAR                            --to/from register
        MA!Data
        MAc!Ctrl
      MAa? ack
      ------------------------------------
      IF 
        ack[0]=FINISH
          SEQ
            debugmsg(report,screen, "ADDINT-AddC: wbus() Ack FINISH received",NULL1)
            terminate(evaluate, ack[TIME.IN],NO.KILL, NO.FLUSH, occupancy.table, screen, [MA])
            --term:=TRUE
        TRUE
          SKIP
      -------------------------------------
 
      ackw[TIME.STAMP]:=  ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
      ack[TIME.STAMP]:=ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
      calculate.occupancy(evaluate, occupancy.table[4], ack[TIME.STAMP], Wdata.occ)  

      PAR            
        Wa!ack                      --to the wbus(wregister)
        WLx!ackw                    --to write-control             
  :
  -----------------------------------------------------------------------
  PROC rapipe() 

    [MESGLEN]INT  ack, ack1,ackw,Apipedata.occ:
    SEQ
      fromapipe? Data        --from apipe
      mkwac() 
      Apipedata.occ:=Data
                             --make Actrl 
      Data[TIME.STAMP]:= max(clock0, Data[TIME.STAMP]) +delay[4]  --MULLERC+CALL+CALL  
      Data[STALL]:=(-1)
                  
      PAR                            --to/from the register
        MA!Data
        MAc!Ctrl
      MAa? ack

      ack1[TIME.STAMP]:= ack[TIME.STAMP] +delay[5] --CALL+CALL
      ackw[TIME.STAMP]:=  ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
      ack[TIME.STAMP]:=ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
      clock0:=ackw[TIME.STAMP]
      calculate.occupancy(evaluate, occupancy.table[2], ack1[TIME.STAMP], Apipedata.occ)  
      calculate.occupancy(evaluate, occupancy.table[4], ack[TIME.STAMP], Wdata.occ)  

      PAR
        Wa!ack                    -- to the wbus for the Wc
        WLx!ackw
        APa!ack1                   -- to the apipe
  :        
  -----------------------------------------------------------------------
  PROC mklsc()

    SEQ
      
      init.hex(Ctrl[0], [PCpar,dPc, VDD, VSS, VSS,Nusr, Ren,Wen ,Ntrm, VDD])
      int.to.bool(Ctrl[0], Ctrlb)      
      Wen:=Ctrlb[7]
      Ren:=Ctrlb[6]
      Opc:=Ctrlb[3]
  :
  --------------------------------------------------------------------------

  PROC rlsmreg()

    [MESGLEN]INT  Dec1ctrl, ack, ack1,ack2,ackw,Lsmdata.occ :
 
    SEQ
      SEQ
        SEQ
      
          debugmsg(report,screen, "ADDINT-AddC: rlsmreg waiting  from Dec1",NULL1)
          LSMP? Dec1ctrl    --control from Dec1/includes Ntrm, dPc
          debugmsg(report,screen, "ADDINT-AddC rlsmreg received from Dec1",NULL1)
          int.to.bool(Dec1ctrl[0],Dec1ctrlb)
          Ntrm:=Dec1ctrlb[0]
          dPc:=Dec1ctrlb[1]

          mkwac()                 --use the above two values
          debugmsg(report,screen, "ADDINT-AddC rlsmreg waiting to send to MA",NULL1)
          Data[TIME.STAMP]:=max(clock0, Dec1ctrl[TIME.STAMP]) + delay[8]  --MULLERC+CALL+CALL
          Data[STALL]:=(-1)

          PAR
            MA!Data
            MAc!Ctrl
          debugmsg(report,screen, "ADDINT-AddC rlsmreg sent to MA",NULL1)
          debugmsg(report,screen, "ADDINT-AddC rlsmreg waiting for ack from MA",NULL1)
          MAa?  ack
          debugmsg(report,screen, "ADDINT-AddC rlsmreg received ack from MA",NULL1)
          debugmsg(report,screen, "ADDINT-AddC rlsmreg waiting to send LSMPa",NULL1)
          clock0:=ack[TIME.STAMP]
          ackw[TIME.STAMP]:=ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
          ack[TIME.STAMP]:=ack[TIME.STAMP] +delay[6] -- CALL+CALL+XOR+XOR
          calculate.occupancy(evaluate, occupancy.table[4], ack[TIME.STAMP], Wdata.occ)  

          SEQ
            PAR
              Wa!ack     --send ack to WrtCtrl
              WLx!ackw
          clock0:=clock0 +delay[9] --CALL+CALL+SELECT+SELECT+XOR+XOR
          ack[TIME.STAMP]:=clock0
          calculate.occupancy(evaluate, occupancy.table[3], ack[TIME.STAMP],Dec1ctrl )  

          LSMPa!ack  --send ack to Dec1
          debugmsg(report,screen, "ADDINT-AddC rlsmreg sent LSMPa",NULL1)
          WHILE Ntrm=TRUE
            SEQ
              debugmsg(report,screen, "ADDINT-AddC: rlsmreg wait from Dec1-lsmreg",NULL1)
              PAR   
                fromlsreg? Data
                LSMP? Dec1ctrl
              Lsmdata.occ:=Data
              clock0:=max(clock0, Data[TIME.STAMP]) + delay[10]  --MULLERC + XOR
              clock0:=max(clock0, Dec1ctrl[TIME.STAMP]) + delay[11]  --MULLERC+CALL+CALL  
              debugmsg(report,screen, "ADDINT-AddC: rlsmreg received Dec1/lsmreg",NULL1)
              int.to.bool(Dec1ctrl[0],Dec1ctrlb)
              Ntrm:=Dec1ctrlb[0]
              dPc:=Dec1ctrlb[1]

              mklsc()               --use the above two values
              debugmsg(report,screen, "ADDINT-AddC rlsmreg waiting to send to MA",NULL1)
              Data[TIME.STAMP]:=clock0
              Data[STALL]:=(-1)
              PAR
                MA!Data
                MAc!Ctrl
              debugmsg(report,screen, "ADDINT-AddC rlsmreg sent to MA",NULL1)
              debugmsg(report,screen, "ADDINT-AddC rlsmreg waiting for ack from MA",NULL1)
              MAa? ack
              debugmsg(report,screen, "ADDINT-AddC rlsmreg rec ack from MA",NULL1)
              debugmsg(report,screen, "ADDINT-AddC rlsmreg wait to send LSMPa/LSMa",NULL1)
              clock0:=ack[TIME.STAMP]
              clock0:=clock0 +delay[9] --CALL+CALL+SELECT+SELECT+XOR+XOR
              ack[TIME.STAMP]:=clock0
              ack1[TIME.STAMP]:=clock0

              calculate.occupancy(evaluate, occupancy.table[1], ack[TIME.STAMP], Lsmdata.occ)  
              calculate.occupancy(evaluate, occupancy.table[3], ack1[TIME.STAMP],Dec1ctrl )  

              --LSMPa!ack  --send ack to Dec1  --*******************

              PAR
                LSMa!ack
                LSMPa!ack1
              debugmsg(report,screen, "ADDINT-AddC rlsmreg sent LSMPa and LSMa",NULL1)

          --debugmsg(report,screen, "ADDINT-AddC waiting to send to Wa and WLx",NULL1)
          --PAR
            --Wa!ack
           -- WLx!ackw
          --debugmsg(report,screen, "ADDINT-AddC  sent to Wa and WLx",NULL1)
  :
  -----------------------------------------------------------------------
    
  SEQ
    end:=FALSE
    oldPCpar:=FALSE
    PCpar:=FALSE
    Nusr:=FALSE
    Sp:=FALSE
    Lsm:=FALSE
    Opc:=FALSE
    Ntrm:=FALSE
    dPc:=FALSE
    Wen:=FALSE
    Ren:=FALSE
    lsmpc:=FALSE
    dPCc:=FALSE
    ToInc:=FALSE
    LSin:=FALSE
    term:=FALSE
    pcparchanged:=FALSE
    previous.report, preempt.frequency, preempt.magnitude,accum.preempt:=0,0,0,0
    msgnum:=0
    calculate.delays()
    initialize.occup.tables()
    Wdata.occ:=[0,0,0,0]
    Pcdata.occ:=[0,0,0,0]   --initialy
    clock0:=0
    ack[0]:=0
    first:=TRUE

    WHILE NOT end
      SEQ
        IF
          preemption=PREEMPTION.ON
            --------------------------------------------------------------------------------------      
            SEQ
              
              ALT
                W?Data   --read from WriteCtrl
                  SEQ
                    clock?time
                    check.for.preemption(Data, Pcdata.occ, clock0, process.id,report, clock0,
                    previous.report, preempt.frequency,preempt.magnitude,msgnum, accum.preempt,screen, found)


                    Wdata.occ:=Data
                    IF
                      found=FALSE
                        SEQ
                          clock0:=Data[TIME.STAMP]
                      found=TRUE
                        SEQ
                          SKIP

                    debugmsg(report,screen, "ADDINT-AddC: Address received from WriteCtrl ", Data)
                    IF
                      Data[0]<>FINISH
                        SEQ
                          Wc? Ctrl
                          int.to.bool(Ctrl[0], Ctrlb)
                          Sp:=Ctrlb[9]
                          Lsm:=Ctrlb[8]
                          Nusr:=Ctrlb[5]      -- they will be part of pcc
                          oldPCpar:=PCpar
                          PCpar:= Ctrlb[0]                             
     
                          IF                           --ckeck if the pc parity has changed
                            oldPCpar<>PCpar
                              SEQ
                                pcparchanged:=TRUE   
                            TRUE
                              SKIP
                          IF
                            found=FALSE
                              SEQ
                                clock0:=clock0+delay[1] --ARBITER+SELECT
                            found=TRUE
                              SEQ
                                SKIP
                          IF
                            ((Sp=TRUE) AND (Lsm=FALSE))
                              SEQ
                                debugmsg(report,screen, "ADDINT-AddC: call rapipe ", Data)
                                clock0:=clock0+delay[2]  --SELECT
                                rapipe()
                            (Sp=FALSE)
                              SEQ
                                debugmsg(report,screen, "ADDINT-AddC: call rwbus ", Data)
                                IF
                                  found=FALSE
                                    SEQ
                                      clock0:=clock0+ delay[3]  --CALL+CALL
                                  found=TRUE
                                    SEQ
                                      SKIP

                                rwbus()
                            ((Sp=TRUE) AND (Lsm=TRUE))
                              SEQ
                                IF
                                  found=FALSE
                                    SEQ
                                      clock0:=clock0+delay[7]  --SELECT+XOR
                                  found=TRUE
                                    SEQ
                                      SKIP

                                debugmsg(report,screen, "ADDINT-AddC: call rlsmreg ", Data)
                                rlsmreg()
                      TRUE
                        end:=TRUE 
                frompcpipe? Data       --read from pc pipe
                  SEQ
                    clock?time
                    check.for.preemption(Data, Wdata.occ, clock0, process.id,report,clock0,
                    previous.report, preempt.frequency,preempt.magnitude, msgnum, accum.preempt, screen,found)

                    Pcdata.occ:=Data
                    IF
                      found=FALSE
                        SEQ
                          clock0:=Data[TIME.STAMP] + delay[0] --XOR+ARBITER+SELECT
                      found=TRUE
                        SEQ
                          SKIP


                    debugmsg(report,screen, "ADDINT-AddC: Address received from PCpipe ", Data)
                    rpcpipe()
 
            
          preemption=PREEMPTION.OFF
            --------------------------------------------------------------------------------------      
            SEQ
              SKIP   
              --insert code here

    --end sent back with ack from memory
    debugmsg(report,screen, "ADDINT-AddC: end has been received ", Data)

    terminate(evaluate, Data[TIME.STAMP],KILL, NO.FLUSH, occupancy.table, screen, [MA])
:




