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

PROC Dec1CtrlA(CHAN OF BUNDLE IpToDec1a,IpToDec1b,PCToDec1,
                               FDec3PCp,Ia3,
                               XLtoDec1D, CtrlAB,In,PCAB,Dec1ToIpA,
                               Dec1PCA,Dec1XLA,
                    []CHAN OF DEB.MESSAGE screen,VAL INT report, evaluate,preemption ) --2

  -------------------------------------
  [MESGLEN]INT PCpar,Instr,Flo,PC,Fiq,Irq,Ctrl,Acka,Ackip,Ackpcp,Ackip,Ackpcp,Ackxl, Instr.occ, PC.occ, Data.in, PCpar.occ:

  INT xcpcin,xcpcout, temp, clock:

  BOOL pcp,F, I,new.pcpar,previous.pcpar,Dabt,end,finish1,finish2,found,pcpar.received:
  CHAN OF INT stopper:
  [32]BOOL Pcparb,Flob,Instrb: 

  [9]BOOL xcpcinb:
  [7]BOOL Ctrlb: 
  [6]BOOL xcpcoutb:
  [8][9]INT XcpCmask:
  [8][9]INT XcpCmatch:
  [8][6]INT XcpCout:

  [8]INT delay:

  INT time, previous.report, preempt.frequency, preempt.magnitude, accum.preempt, msgnum :


  [2][OCCT.SIZE][OCCT.COL]INT occupancy.table:  --an array of occupancy tables!!!!
                                        --Ipipe and PCpipe

  VAL INT process.id IS DEC1A.ID:

  
  
  ------------------------------------
  PROC calculate.delays()
    SEQ
      delay[0]:= ARBITERX
      delay[1]:=SELECT+MULLERC
      delay[2]:=XOR
      delay[3]:=SELECT+ XOR
      delay[4]:=((XOR+AND.GATE)+OR.GATE)+EVLATCH
      delay[5]:=SELECT

  :
  ------------------------------------
  PROC  initialize.occup.tables()
    SEQ
      initialize.occup.table(occupancy.table[0], IPIPE,IPIPE.SIZE,  REGISTER.DELAY)  
      initialize.occup.table(occupancy.table[1], PCPIPE, PCPIPE.SIZE, REGISTER.DELAY)  
  :
  ------------------------------------
  PROC pcpar()
    SEQ
      int.to.bool(PCpar[0], Pcparb)
      pcp:=Pcparb[0]
      Dabt:=Pcparb[1]
  :
  ------------------------------------
  --PROC fiq()
  --  SEQ
  --    F:= NOT F
  --:
  ------------------------------------
  --PROC irq()
  --  SEQ
   --   I:=NOT I
  --:
  ------------------------------------
  PROC  XcpCpla(INT In, Out)
    SEQ
      decode(XcpCout, XcpCmatch, XcpCmask, In, Out)    

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

  SEQ
    F:=FALSE
    I:=FALSE
    pcp:=FALSE
    new.pcpar:=FALSE
    previous.pcpar:=FALSE
    Dabt:=FALSE
    end:=FALSE
    XcpCmask:=CXcpCmask
    XcpCmatch:=CXcpCmatch
    XcpCout:=CXcpCout
    calculate.delays()
    initialize.occup.tables()
    PCpar[TIME.STAMP]:=0 --initially
    previous.report, preempt.frequency, preempt.magnitude,accum.preempt:=0,0,0,0
    msgnum:=0
    Data.in:=[0,0,0,0]
    PCpar:=[0,0,0,0]
    PCpar.occ:=[0,0,0,0]
    clock:=0
    SEQ                          --ARBIT-X block
      SEQ

        IpToDec1a? Instr        --Instruction from DataInt(Ipipe)
        IF
          Instr[0]<>FINISH
            SEQ
              PAR
                IpToDec1b? Flo     -- Control from Ipipe [pcpar, abort]
                PCToDec1? PC       --PC from PC pipe
              int.to.bool(Flo[0], Flob)
              previous.pcpar:=Flob[0]       --start with the first PCpar  
              pcp:=previous.pcpar 
              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: For the PC:", PC) 
              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: The instruction is:",Instr)       
          TRUE
            SEQ
              end:=TRUE
 
   
    
    WHILE end=FALSE
      SEQ
        Instr.occ, PC.occ := Instr, PC
        new.pcpar:=Flob[0]
        
        ------------------------------------------------------------------------------
        IF
          new.pcpar<>previous.pcpar    --new instruction sequence!!!!!
            SEQ
              IF
                pcp=previous.pcpar   --ERROR!!! We should have accepted the new pcpar
                  SEQ                  --from the Ctrl3. Read it NOW!!!
                    debugmsg(report,screen[0], "DEC1-DEC1CTRLA: Waiting for new PcPAr from Ctrl3:", PCpar)
                    FDec3PCp? PCpar
                    PCpar.occ:=PCpar
                    ----preemptions???---------------

                    check.for.preemption(PCpar, Data.in, clock, process.id,report, clock,
                    previous.report, preempt.frequency,preempt.magnitude,msgnum, accum.preempt,screen[0], found)





                    pcpar()    --change value of pcp
                    debugmsg(report,screen[0], "DEC1-DEC1CTRLA: Received new PcPAr from Ctrl3:", PCpar)
                TRUE
                  SKIP
              previous.pcpar:=new.pcpar
          TRUE
            SKIP         
        -------------------------------------------------------------------------------
        --***********************************************
        max.proc(Instr[TIME.STAMP], PC[TIME.STAMP], temp)
        max.proc(temp, (PCpar[TIME.STAMP]+delay[0]), clock)
        --***********************************************
        debugmsg(report,screen[0], "DEC1-Dec1CtrlA: clock is",[clock,0,0,0] )  

        ----------------------------------------------------------------------------------------
        --In this case preemption error may occur if the PCpar has not arrived yet.
        --This is due to the time dependent bahaviour of the hardware at this stage I ignore it
        ----------------------------------------------------------------------------------------
        clock:=clock+delay[1]
        IF
          (pcp=new.pcpar)            --OK follow the FALSE path of the select block
            SEQ
              Dabt:=FALSE
              int.to.bool(Instr[0],Instrb)
              xcpcinb[0]:= Flob[1]
              xcpcinb[1]:= Dabt
              xcpcinb[2]:= I
              xcpcinb[3]:= F    
              xcpcinb[4]:=Instrb[4]
              [xcpcinb FROM 5 FOR 4]:=[Instrb FROM 24 FOR 4]         
              init.hex(xcpcin, xcpcinb)
              XcpCpla(xcpcin, xcpcout)
              int.to.bool(xcpcout,xcpcoutb)

              Instr[TIME.STAMP]:=clock+delay[2] --XOR
              PC[TIME.STAMP]:=clock+delay[2] --XOR

              PAR
                SEQ
                  [Ctrlb FROM 0 FOR 6]:= [xcpcoutb FROM 0 FOR 6]
                  Ctrlb[6]:=new.pcpar                
                  init.hex(Ctrl[0], Ctrlb)
                  CtrlAB!Ctrl    --send I, Ctrl, PC tp Dec1CtrlB, wait for Ack
                In!Instr
                PCAB!PC          
              Ia3? Acka
              clock:=Acka[TIME.STAMP]
              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: Instruction has been forwarded to CtrlB",Instr )  
              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: Ack for the Instruction has been received", Acka)  
              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: PCpar OK/Instruction has been forwarded to CtrlB", PC)  

              Ackip[TIME.STAMP]:=Acka[TIME.STAMP]+delay[3] --SELECT+ XOR
              Ackpcp[TIME.STAMP]:=Acka[TIME.STAMP]+delay[3]
    
              calculate.occupancy(evaluate, occupancy.table[0], Ackip[TIME.STAMP], Instr.occ)              
              calculate.occupancy(evaluate, occupancy.table[1], Ackpcp[TIME.STAMP], PC.occ)  

              debugmsg(report,screen[0], "DEC1-Dec1CtrlA: PCpar OK/Instruction has been forwarded to CtrlB", PC)  

              PAR                     --send Ack to PCpipe(AddInt) and Ipipe(DataInt)
                Dec1ToIpA!Ackip   
                Dec1PCA!Ackpcp         
              
  
          (pcp<>new.pcpar)            --PCpar has changed!! Discard instruction
            SEQ
              Ackip[TIME.STAMP]:=clock+delay[2] -- XOR
              Ackpcp[TIME.STAMP]:=clock+delay[2]
              calculate.occupancy(evaluate, occupancy.table[0], Ackip[TIME.STAMP], Instr.occ)              
              calculate.occupancy(evaluate, occupancy.table[1], Ackpcp[TIME.STAMP], PC.occ)  

              PAR
                PAR
                  Dec1ToIpA!Ackip   
                  Dec1PCA!Ackpcp     --sink PC!!
                SEQ
                  ---------------------------------------

                  IF
                    Dabt=TRUE       --PcPar changed due to a Data abort 
                      SEQ
                        Instr[0]:=0     --apparently garbage unless if it used somewhere...
                        int.to.bool(Instr[0],Instrb)
                        xcpcinb[0]:= Flob[1]
                        xcpcinb[1]:= Dabt
                        xcpcinb[2]:= I
                        xcpcinb[3]:= F    
                        xcpcinb[4]:=Instrb[4]
                        [xcpcinb FROM 5 FOR 4]:=[Instrb FROM 24 FOR 4]   
                        init.hex(xcpcin, xcpcinb)                
                        XcpCpla(xcpcin,xcpcout)
                        int.to.bool(xcpcout,xcpcoutb)
                        debugmsg(report,screen[0], "DEC1-Dec1CtrlA: PcPar has changed, wait to read from Xlatch", NULL1)
                        XLtoDec1D? PC  --read from XLatch
                        debugmsg(report,screen[0], "DEC1-Dec1CtrlA: PcPar has changed, received PC from Xlatch", NULL1)

                        Instr[TIME.STAMP]:=clock+delay[4] --XOR+AND+OR+EVLATCH

                        PAR
                          SEQ
                            [Ctrlb FROM 0 FOR 6]:= [xcpcoutb FROM 0 FOR 6]
                            Ctrlb[6]:=new.pcpar
                                     
                            init.hex(Ctrl[0], Ctrlb)
                            CtrlAB!Ctrl    --send I, Ctrl, PC tp Dec1CtrlA, wait for Ack

                          In!Instr
                          PCAB!PC  
                                     
                        Ia3? Acka
                        Dabt:=FALSE 
                        clock:=Acka[TIME.STAMP]

                        Ackxl[TIME.STAMP]:=Acka[TIME.STAMP]+delay[5]  --SELECT                 
                        Dec1XLA!Ackxl
                    Dabt=FALSE
                      SEQ
                        SKIP    

        PAR                       --ARBIT-X block
          SEQ
            IpToDec1a? Instr        --Instruction from DataInt(Ipipe)
            debugmsg(report,screen[0], "DEC1-DEC1CTRLA: Received instruction after:", PC)
            debugmsg(report,screen[0], "DEC1-DEC1CTRLA: The instruction is:", Instr)

            IF
              Instr[0]<>FINISH
                SEQ
                  PAR
                    
                    IpToDec1b? Flo     -- Control from Ipipe [pcpar, abort]
                    SEQ
                      debugmsg(report,screen[0], "DEC1-DEC1CTRLA: Waiting for PC after:", PC)
                      PCToDec1? PC       --PC from PC pipe
                      debugmsg(report,screen[0], "DEC1-DEC1CTRLA: Received  new  PC:", PC)
                  int.to.bool(Flo[0], Flob)  
                  debugmsg(report,screen[0], "DEC1-Dec1CtrlA: For the PC:", PC) 
                  debugmsg(report,screen[0], "DEC1-Dec1CtrlA: The instruction is:",Instr) 

                  -------preemptions????!!!------ 

                  max.proc(Instr[TIME.STAMP], PC[TIME.STAMP], temp)
                  Data.in[TIME.STAMP]:=temp
                  check.for.preemption(Data.in, PCpar.occ, clock, process.id,report, clock,
                  previous.report, preempt.frequency,preempt.magnitude,msgnum, accum.preempt,screen[0], found)
                  --------------------------------

              TRUE
                SEQ
                  end:=TRUE   
          PRI ALT                             --arbiter
            FDec3PCp? PCpar
              SEQ
                pcpar.received:=TRUE

                debugmsg(report,screen[1], "DEC1-DEC1CTRLA: Received(arbiter)new PcPAr from Ctrl3:", PCpar)
                pcpar()
            TRUE & SKIP
              SEQ
                pcpar.received:=FALSE    
                PCpar[TIME.STAMP]:=0 --force the timestamp to 0 for the calculation of clock
                SKIP
        ---
        IF
          pcpar.received=TRUE
            SEQ
              PCpar.occ:=PCpar
              check.for.preemption(PCpar, Data.in, clock, process.id,report, clock,
              previous.report, preempt.frequency,preempt.magnitude,msgnum, accum.preempt,screen[1], found)
          TRUE
            SKIP

              


         ------------------------------------------------------------------------
         -- PRI ALT                             --arbiter
           -- NFiq? Fiq
              --SEQ
                --fiq()
            --TRUE & SKIP
              --SKIP

          --PRI ALT                             --arbiter
            --NIrq? Irq
              --SEQ
                --irq()
            --TRUE & SKIP            
              --SKIP
         ------------------------------------------------------------------------
    debugmsg(report,screen[1], "DEC1-DEC1CTRLA: KILL message has been received", NULL1)
    terminate(evaluate,Instr[TIME.STAMP] ,KILL,FLUSH,occupancy.table, screen[0], [In])
    debugmsg(report,screen[1], "DEC1-DEC1CTRLA: KILL message has been propagated to Dec1CtrlB", NULL1)

    finish1:=FALSE
    finish2:=FALSE
    WHILE (finish1=FALSE) OR (finish2=FALSE)
      SEQ
        ALT
          FDec3PCp? PCpar      --SINK possible PcPars arriving from Ctrl3
            IF
              PCpar[0]=FINISH
                SEQ
                  finish1:=TRUE
              TRUE
                SEQ
                  SKIP
          PCToDec1? PC      --SINK possible PCs arriving from AddInt
            IF
              PC[0]=FINISH
                SEQ
                  finish2:=TRUE
                  debugmsg(report,screen[1], "DEC1-DEC1CTRLA: FINAL FINISH received by ADDINT", NULL1)

              TRUE
                SEQ
                  Dec1PCA!Ackpcp 
                  SKIP
:
