-- **************************************************
--
--   Entity: GMTHWTestFile.vhd
--
--   Description: Routines to read tets data from
--                ORCA-generated HW testfile
--
--
--   $Date: 2004/05/25 16:48:18 $
--   $Revision: 1.5 $
--
--   Author :
--   H. Sakulin                       HEPHY Vienna
--
-- **************************************************

library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use WORK.GMTTypes.all;
use STD.TEXTIO.all;

package GMTHWTestFile is

type TGMTEvent is record
  DTMuons      : TSyncedMu_vector4;
  CSCMuons     : TSyncedMu_vector4;
  bRPCMuons    : TSyncedMu_vector4;
  fRPCMuons    : TSyncedMu_vector4;
  MIPbits      : TCaloRing_vector(0 to 13);
  Quietbits    : TCaloRing_vector(0 to 13);
  PhiSelBits   : TPhiSelBits_vec(0 to 31);
  EtaSelBits   : TEtaSelBits_vec(0 to 31);
  IsMIPISObits : std_logic_vector(0 to 31);
  GMTMuons     : TGMTMu_vector(0 to 3);
  BrlGMTMuons  : TGMTMu_vector(0 to 3);
  FwdGMTMuons  : TGMTMu_vector(0 to 3);
  GMTSortRanks : TSortRank_vector(0 to 3);
  BrlSortRanks : TSortRank_vector(0 to 3);
  FwdSortRanks : TSortRank_vector(0 to 3);
  PairMatrices : TPairMatrix_vec(0 to 5);
  MQMatrices   : TMQMatrix_vec(0 to 5);
  CancelBits   : TCancelBits_vec(0 to 3);
end record;

type TGMTEvent_vec is array (integer range <>) of TGMTEvent;

procedure ReadEvent (
  file F : text; 
  variable event : out TGMTEvent
  );
  
procedure DumpEvent (
  variable event : in TGMTEvent
  );

end package GMTHWTestFile;

package body GMTHWTestFile is

  function reverse_bits(a: in std_logic_vector)
    return std_logic_vector
  is
    variable a_rev: std_logic_vector(a'REVERSE_RANGE);
  begin
    for i in a'RANGE loop
      a_rev(i) := a(i);
    end loop;
    return a_rev;
  end;


  
  procedure ReadInputMuon (
    variable L : inout line;
    variable Muon : out TSyncedMu) is  -- the muons

    variable dummy           : string(1 to 4);
    variable vch, ch, hf     : bit;
    variable eta, q, pt, phi : integer;
  begin  -- ReadMuons
        read (L, dummy);
        read (L, vch); Muon.ch_valid := to_stdulogic ( vch );
        read (L, ch); Muon.charge    := to_stdulogic ( ch );
        read (L, hf); Muon.finehalo  := to_stdulogic ( hf );
        read (L, eta); Muon.eta      := std_logic_vector( TO_UNSIGNED ( eta, 6 ) );
        read (L, q); Muon.qual       := not ( std_logic_vector( TO_UNSIGNED ( q, 3 ) ) );
        read (L, pt); Muon.pt        := not ( std_logic_vector( TO_UNSIGNED ( pt, 5 ) ));
        read (L, phi); Muon.phi      := std_logic_vector( TO_UNSIGNED ( phi, 8 ) );
  end ReadInputMuon;

  procedure ReadGMTMuon (
    variable L : inout line;
    variable Muon : out TGMTMu;
    variable SortRank : out TSortRank) is  -- the muons

    variable dummy           : string(1 to 4);
    variable mip, iso     : bit;
    variable eta, q, pt, phi,sysign, rank : integer;
  begin  -- ReadMuons
        read (L, dummy);
        read (L, sysign); Muon.sysign:= std_logic_vector( TO_UNSIGNED (sysign, 2));
        read (L, mip); Muon.mip      := to_stdulogic ( mip );
        read (L, iso); Muon.isol     := to_stdulogic ( iso );
        read (L, eta); Muon.eta      := std_logic_vector( TO_UNSIGNED ( eta, 6 ) );
        read (L, q); Muon.qual       := std_logic_vector( TO_UNSIGNED ( q, 3 ) );
        read (L, pt); Muon.pt        := std_logic_vector( TO_UNSIGNED ( pt, 5 ) );
        read (L, phi); Muon.phi      := std_logic_vector( TO_UNSIGNED ( phi, 8 ) );
        read (L, rank); SortRank     := std_logic_vector( TO_UNSIGNED ( rank, 8 ) );
  end ReadGMTMuon;


  procedure ReadMIPISO (
    variable L       : inout line;    -- the line
    variable mipbits : out   TCaloRing_vector (0 to 13);
    constant isMIP   : in boolean) is  -- MIP or ISO bits

    variable dummy          : string(1 to 3);
    variable num, ring, phi : integer;
    variable init           : TCaloRing := "000000000000000000";  -- initial value
    variable set_to         : std_logic := '1';  -- set listed entries to this value
  begin  -- Read MIP or non-Quiet bits
    if (isMIP) then
      init                              := "000000000000000000";  -- init quiet bits to 1
      set_to                            := '1';
    else
      init                              := "111111111111111111";  -- init quiet bits to 1
      set_to                            := '0';
    end if;
    for i in 0 to 13 loop
      mipbits (i)                       := init;
    end loop;
    read (L, dummy);
    read (L, num);
    for i in 0 to num-1 loop
      read (L, ring);
      read (L, phi);
      mipbits(ring)(phi)                := set_to;
    end loop;  -- i
  end ReadMIPISO;


  procedure ReadPhiSelBits (
    variable L          : inout line;    -- the line
    variable phiselbits : out   TPhiSelBits_vec (0 to 31)) is

    variable dummy          : string(1 to 4);
    variable selbits        : integer;
  begin  
    read (L, dummy);
    for i in 0 to 31 loop
      read (L, selbits);
      phiselbits(i) := std_logic_vector( TO_UNSIGNED (selbits, 18) );
    end loop;  -- i
  end ReadPhiSelBits;


  procedure ReadEtaSelBits (
    variable L          : inout line;    -- the line
    variable etaselbits : out   TEtaSelBits_vec (0 to 31)) is

    variable dummy          : string(1 to 4);
    variable selbits        : integer;
  begin  
    read (L, dummy);
    for i in 0 to 31 loop
      read (L, selbits);
      etaselbits(i) := std_logic_vector( TO_UNSIGNED (selbits, 10) );
    end loop;  -- i
  end ReadEtaSelBits;

  procedure ReadIsMIPISOBits (
    variable L            : inout line;    -- the line
    variable IsMIPISObits : out std_logic_vector(0 to 31)) is

    variable dummy        : string(1 to 4);
    variable mibit        : bit;
  begin  
    read (L, dummy);
    for i in 0 to 31 loop
      read (L, mibit);
      IsMIPISObits(i) := to_stdulogic( mibit );
    end loop;  -- i
  end ReadIsMIPISOBits;

  procedure ReadPairMatrix (
    variable L            : inout line;    -- the line
    variable PairMatrix   : out TPairMatrix;
    variable idx : in integer) is

    variable dummy        : string(1 to 4);
    variable i_pair : integer;
    variable pair_bit : bit;
--    variable bla: line ;
  begin  
    read (L, dummy);
    read (L, i_pair);
    if (idx /= i_pair) then
      assert false report "Pair matrices in file out of order." severity failure;
    end if;
    
    for r in 0 to 3 loop
      for c in 0 to 3 loop
        read (L, pair_bit);
--         write(bla,string'("reading bit "));
--         write(bla,pair_bit);
--         writeline(output, bla);
        PairMatrix(r,c) := to_stdulogic( pair_bit );
      end loop;  -- c
    end loop;  -- r
  end ReadPairMatrix;

  procedure ReadMQMatrix (
    variable L            : inout line;    -- the line
    variable MQMatrix   : out TMQMatrix;
    variable idx : in integer) is

    variable dummy        : string(1 to 4);
    variable i,mq : integer;

  begin  
    read (L, dummy);
    read (L, i);
    if (idx /= i) then
      assert false report "MQ matrices in file out of order." severity failure;
    end if;
    
    for r in 0 to 3 loop
      for c in 0 to 3 loop
        read (L, mq);
        MQMatrix(r,c) := std_logic_vector( TO_UNSIGNED ( mq, 6 ) );
      end loop;  -- c
    end loop;  -- r
  end ReadMQMatrix;

  procedure ReadCancelBits (
    variable L          : inout line;    -- the line
    variable cancelbits : out   TCancelBits_vec (0 to 3)) is

    variable dummy          : string(1 to 4);
    variable selbits        : integer;
  begin  
    read (L, dummy);
    for i in 0 to 3 loop
      read (L, selbits);
      cancelbits(i) := reverse_bits ( std_logic_vector( TO_UNSIGNED (selbits, 8) ) );
    end loop;  -- i
  end ReadCancelBits;


  procedure ReadEvent (
    file F : text; 
    variable event : out TGMTEvent
    ) is 
    
    variable L : line;
    variable ndt, ncsc, nbrpc, nfrpc, npairm, nmqm, ngmt, nbgmt, nfgmt : integer ;
    variable runno, evtno : integer;     
    variable bInDataBlock : boolean;
    variable bEventDone: boolean;
    variable dummy : string(1 to 3);

    variable L1 : line;

  begin
    -- reset variables
    for i in 0 to 3 loop
      event.DTMuons(i) := ( '0', '0', '0', "000000", "111", "11111", "11111111" );
      event.CSCMuons(i) := ( '0', '0', '0', "000000", "111", "11111", "11111111" );
      event.BRPCMuons(i) := ( '0', '0', '0', "000000", "111", "11111", "11111111" );
      event.FRPCMuons(i) := ( '0', '0', '0', "000000", "111", "11111", "11111111" );

      event.GMTMuons(i) := ( "00", '0', '0', "000000", "000", "00000", "00000000" );
      event.BrlGMTMuons(i) := ( "00", '0', '0', "000000", "000", "00000", "00000000" );
      event.FwdGMTMuons(i) := ( "00", '0', '0', "000000", "000", "00000", "00000000" );
      event.GMTSortRanks(i) := (others => '0');
      event.BrlSortRanks(i) := (others => '0');
      event.FwdSortRanks(i) := (others => '0');
    end loop;  -- i
    for i in 0 to 13 loop
      event.MIPbits(i) := "000000000000000000";
      event.Quietbits(i) := "000000000000000000";
    end loop;  -- i
    for i in 0 to 31 loop
      event.PhiSelBits(i) := "000000000000000000";
      event.EtaSelBits(i) := "0000000000";
    end loop;  -- i
    for i in 0 to 5 loop
      for r in 0 to 3 loop
        for c in 0 to 3 loop
          event.PairMatrices(i)(r,c) := '0';
        end loop;  -- c
      end loop;  -- r
    end loop;  -- i

    -- reset counters
    ndt  :=0;
    ncsc :=0;
    nbrpc:=0;
    nfrpc:=0;
    npairm :=0;
    nmqm:=0;
    ngmt:=0;
    nbgmt:=0;
    nfgmt:=0;
    bEventDone := false;
    bInDataBlock := false;

    -- read event
    while ( (not bEventDone) and (not endfile(F)) ) loop
      readline (F, L);
      write (L1,string'("read line:"));
      write (L1, L.all);
      writeline(OUTPUT,L1 );
      if (L.all(1 to 2) = "--" ) then
        if (bInDataBlock) then
          bEventDone := true;
        end if;
        next;
      end if;
      if (L.all(1 to 3) = "RUN") then
        read (L, dummy);
        read (L, runno);
        write(L1, string'("run number "));
        write(L1, runno);
        writeline(output, L1);
        next;
      end if;
      if (L.all(1 to 3) = "EVT") then
        read (L, dummy);
        read (L, evtno);
        write(L1, string'("event number "));
        write(L1, evtno);
        writeline(output, L1);
        bInDataBlock := true;
        next;
      end if;
      if (L.all(1 to 2) = "DT") then
        if ndt < 4 then
          ReadInputMuon (L, event.DTMuons(ndt));
          ndt := ndt+1;
        else  
          assert false report "to many DT input muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 3) = "CSC") then
        if ncsc < 4 then
          ReadInputMuon (L, event.CSCMuons(ncsc));
          ncsc := ncsc+1;
        else  
          assert false report "to many CSC input muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 4) = "BRPC") then
        if nbrpc < 4 then
          ReadInputMuon (L, event.bRPCMuons(nbrpc));
          nbrpc := nbrpc+1;
        else  
          assert false report "to many BRPC input muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 4) = "FRPC") then
        if nfrpc < 4 then
          ReadInputMuon (L, event.fRPCMuons(nfrpc));
          nfrpc := nfrpc+1;
        else  
          assert false report "to many FRPC input muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 4) = "GMT ") then
        if ngmt < 4 then
          ReadGMTMuon (L, event.GMTMuons(ngmt), event.GMTSortRanks(ngmt));
          ngmt := ngmt+1;
        else  
          assert false report "to many GMT  muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 4) = "GMTB") then
        if nbgmt < 4 then
          ReadGMTMuon (L, event.BrlGMTMuons(nbgmt), event.BrlSortRanks(nbgmt));
          nbgmt := nbgmt+1;
        else  
          assert false report "to many GMTB muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 4) = "GMTF") then
        if nfgmt < 4 then
          ReadGMTMuon (L, event.FwdGMTMuons(nfgmt), event.FwdSortRanks(nfgmt));
          nfgmt := nfgmt+1;
        else  
          assert false report "to many GMTF muons" severity failure;
        end if;
        next;
      end if;
      if (L.all(1 to 3) = "MIP") then
        ReadMIPISO(L, event.MIPbits, true);
        next;
      end if;
      if (L.all(1 to 2) = "NQ") then
        ReadMIPISO(L, event.Quietbits, false);
        next;
      end if;
      if (L.all(1 to 4) = "PHIS") then
        ReadPhiSelBits(L, event.PhiSelBits);
        next;
      end if;
      if (L.all(1 to 4) = "ETAS") then
        ReadEtaSelBits(L, event.EtaSelBits);
        next;
      end if;
      if (L.all(1 to 2) = "MI") then
        ReadIsMIPISOBits(L, event.IsMIPISObits);
        next;
      end if;
      if (L.all(1 to 4) = "PAIR") then
        ReadPairMatrix(L, event.PairMatrices(npairm),npairm);
        npairm := npairm + 1;
        next;
      end if;
      if (L.all(1 to 2) = "MQ") then
        ReadMQMatrix(L, event.MQMatrices(nmqm),nmqm);
        nmqm := nmqm + 1;
        next;
      end if;
      if (L.all(1 to 4) = "CANC") then
        ReadCancelBits(L, event.CancelBits);
        next;
      end if;
    end loop;

  end ReadEvent;


  procedure DumpEvent (
    variable event : in TGMTEvent
    ) is 
    
    variable L1 : line;

  begin
    for i in 0 to 3 loop
      write (L1,string'("DT   Muon "));
      write (L1,i+1);
      write (L1,string'(" :"));
      write (L1,event.DTMuons(i));
      writeline (OUTPUT, L1);
    end loop;  -- i
    for i in 0 to 3 loop
      write (L1,string'("CSC  Muon "));
      write (L1,i+1);
      write (L1,string'(" :"));
      write (L1,event.CSCMuons(i));
      writeline (OUTPUT, L1);
    end loop;  -- i
    for i in 0 to 3 loop
      write (L1,string'("BRPC Muon "));
      write (L1,i+1);
      write (L1,string'(" :"));
      write (L1,event.bRPCMuons(i));
      writeline (OUTPUT, L1);
    end loop;  -- i
    for i in 0 to 3 loop
      write (L1,string'("FRPC Muon "));
      write (L1,i+1);
      write (L1,string'(" :"));
      write (L1,event.fRPCMuons(i));
      writeline (OUTPUT, L1);
    end loop;  -- i      
    write (L1, string'("MIP bits : "));
    writeline (OUTPUT, L1);
    for i in 0 to 13 loop
      write (L1, TO_BITVECTOR ( event.MIPbits(i) ));
      writeline (OUTPUT, L1);
    end loop;
    write (L1, string'("Quiet bits : "));
    writeline (OUTPUT, L1);
    for i in 0 to 13 loop
      write (L1, TO_BITVECTOR ( event.Quietbits(i) ));
      writeline (OUTPUT, L1);
    end loop;
    write (L1, string'("PHI SELECTBITS:"));
    for i in 0 to 31 loop
      write (L1, string'(" "));
      write (L1, TO_INTEGER (UNSIGNED(event.PhiSelBits(i))));
    end loop;  -- i
    writeline (OUTPUT, L1);
    write (L1, string'("ETA SELECTBITS:"));
    for i in 0 to 31 loop
      write (L1, string'(" "));
      write (L1, TO_INTEGER (UNSIGNED(event.EtaSelBits(i))));
    end loop;  -- i
    writeline (OUTPUT, L1);
    for i in 0 to 3 loop
      write (L1,string'("GMT  Muon "));
      write (L1,i+1);
      write (L1,string'(" :"));
      write (L1,event.GMTMuons(i));
      writeline (OUTPUT, L1);
    end loop;  -- i
    for i in 0 to 5 loop
      write (L1,string'("Pair Matrix "));
      write (L1,i);
      write (L1,string'(" :"));
      for r in 0 to 3 loop
        for c in 0 to 3 loop
          write (L1,string'(" "));
          write (L1, TO_BIT(event.PairMatrices(i)(r,c)));
        end loop;  -- c
      end loop;  -- r
      writeline (OUTPUT, L1);      
    end loop;  -- i
    for i in 0 to 5 loop
      write (L1,string'("MQ Matrix "));
      write (L1,i);
      write (L1,string'(" :"));
      for r in 0 to 3 loop
        for c in 0 to 3 loop
          write (L1,string'(" "));
          write (L1, TO_BITVECTOR(event.MQMatrices(i)(r,c)));
        end loop;  -- c
      end loop;  -- r
      writeline (OUTPUT, L1);      
    end loop;  -- i
    for i in 0 to 3 loop
      write (L1,string'("CANCEL Bits "));
      write (L1,i);
      write (L1,string'(" :"));
      write (L1, TO_BITVECTOR(event.CancelBits(i)));
      writeline (OUTPUT, L1);
    end loop;  -- i
    
  end DumpEvent;
  
end package body GMTHWTestFile;