---------------------------------------------------------------------------
-- Copyright (c) 2012, TTTech Computertechnik AG
-- Project        : TTP NI
---------------------------------------------------------------------------
-- File           : report_utils_pkg.vhd
-- Author(s)      : Petr Kobiersky
-- Created        : March 12nd, 2012
---------------------------------------------------------------------------
-- Description    : Report Utilities
--
-- Package provides standard functions for reporting.
--
---------------------------------------------------------------------------
-- $Id: report_utils_pkg.vhd 63551 2014-01-24 13:17:37Z kobiersky $
---------------------------------------------------------------------------
library IEEE, STD;
use STD.textio.all;
use IEEE.std_logic_1164.all;


-- -----------------------------------------------------------------------------
-- PACKAGE DECLARATION
-- -----------------------------------------------------------------------------
package report_utils_pkg is
   constant C_MSG_ID_SIZE : natural := 20;
   constant C_TIME_SIZE   : natural := 20;

   -- Operation
   type tVerbosity is (NONE,   -- NONE
                       INFO,   -- INFO verbosity (normal)
                       DEBUG); -- DEBUG Verbosity 

   -- BFM ParameterProtected Type (Used for accessing shared variable)
   ----------------------------------------------------------------------------
   -- Report Statistics
   ----------------------------------------------------------------------------
   type tReportStatistics is protected      
      impure function get_info_count    return natural;
      impure function get_error_count   return natural;
      impure function get_warning_count return natural;
      impure function get_fatal_count   return natural;
      procedure inc_info_counter;
      procedure inc_error_counter;
      procedure inc_warning_counter;
      procedure inc_fatal_counter;
   end protected tReportStatistics;
 
   ----------------------------------------------------------------------------
   -- Report Testcase
   ----------------------------------------------------------------------------
   procedure report_tc(
      tc_id   : in string;                     -- string to print
      tc_name : in string                      -- string to print
   );

   ----------------------------------------------------------------------------
   -- Report Info
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_info(
      msg_id : in string;                     -- string to print
      msg    : in string;                     -- string to print
      msg_verbosity : in tVerbosity := INFO;  -- string to print
      bfm_verbosity : in tVerbosity := DEBUG  -- string to print
   );

   ----------------------------------------------------------------------------
   -- Report Warning
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_warning (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   );

   ----------------------------------------------------------------------------
   -- Report Error
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_error (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   );

   ----------------------------------------------------------------------------
   -- Report Fatal
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_fatal (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   );

   ----------------------------------------------------------------------------
   -- End of Test Procedure
   -- It prints End of Test delimiter to the simulation output
   -- stream (transcript). 
   ----------------------------------------------------------------------------
   procedure report_test_end;

   ----------------------------------------------------------------------------
   -- End of Test Procedure (Timeout)
   -- It prints End of Test delimiter caused by timeout to the simulation
   -- output stream (transcript). 
   ----------------------------------------------------------------------------
   procedure report_test_timeout;

   ----------------------------------------------------------------------------
   -- Function report_error will use severity note instead of error
   -- while after this function is called. Call this functions only in 
   -- justified cases.
   ----------------------------------------------------------------------------
   procedure disable_error_reporting;

   ----------------------------------------------------------------------------
   -- Function report_error behaviour will return to normal.
   ----------------------------------------------------------------------------
   procedure enable_error_reporting;

end report_utils_pkg;

-- -----------------------------------------------------------------------------
-- PACKAGE BODY ----------------------------------------------------------------
-- -----------------------------------------------------------------------------

package body report_utils_pkg is
   
   shared variable disable_all_error_msg : boolean := false;
   
   ----------------------------------------------------------------------------
   -- Report Statistics
   ----------------------------------------------------------------------------
   type tReportStatistics is protected body      
      variable info_count    : natural := 0;
      variable warning_count : natural := 0;
      variable error_count   : natural := 0;
      variable fatal_count   : natural := 0;
      impure function get_info_count    return natural is
      begin
         return info_count;
      end function;
      impure function get_error_count   return natural is
      begin
         return error_count;
      end function;
      impure function get_warning_count return natural is
      begin
         return warning_count;
      end function;
      impure function get_fatal_count   return natural is
      begin
         return fatal_count;
      end function;
      procedure inc_info_counter is
      begin
         info_count := info_count+1;
      end procedure;
      procedure inc_error_counter is
      begin
         error_count := error_count+1;
      end procedure;
      procedure inc_warning_counter is
      begin
         warning_count := warning_count+1;
      end procedure;
      procedure inc_fatal_counter is
      begin
         fatal_count := fatal_count+1;
      end procedure;
   end protected body tReportStatistics;

   shared variable statistics : tReportStatistics;

   ----------------------------------------------------------------------------
   -- Function report_error will use severity note instead of error
   -- while after this function is called. Call this functions only in 
   -- jutified cases.
   ----------------------------------------------------------------------------
   procedure disable_error_reporting is
   begin
      disable_all_error_msg:= true;
   end disable_error_reporting;

   ----------------------------------------------------------------------------
   -- Function report_error behaviour will return to normal.
   ----------------------------------------------------------------------------
   procedure enable_error_reporting is
   begin
      disable_all_error_msg:= false;
   end enable_error_reporting;

   ----------------------------------------------------------------------------
   -- Report Testcase
   ----------------------------------------------------------------------------
   procedure report_tc(
      tc_id   : in string;                     -- string to print
      tc_name : in string                      -- string to print
   ) is
      variable l         : line; -- aux. variable
      variable separator : string(1 to 255) := (others => '-');
   begin
      report_info(tc_id, separator(tc_name'range));
      report_info(tc_id, tc_name);
      report_info(tc_id, separator(tc_name'range));
   end;
  
   ----------------------------------------------------------------------------
   -- Report Info
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_info (
      msg_id : in string; -- string to print
      msg    : in string; -- string to print
      msg_verbosity : in tVerbosity := INFO;  -- string to print
      bfm_verbosity : in tVerbosity := DEBUG  -- string to print      
   ) is
      variable l : line; -- aux. variable
   begin
      if (bfm_verbosity >= msg_verbosity) then
         statistics.inc_info_counter;
         write(l, "** Note: " & justify(msg_id, field => C_MSG_ID_SIZE, justified => left) & " (" 
                              & justify(to_string(now, ns), field => C_TIME_SIZE, justified => left) 
                              & ") : " & msg);
         writeline(output, l);
      end if;
   end;
   ----------------------------------------------------------------------------
   -- Report Warning
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_warning (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   ) is
   begin
      statistics.inc_warning_counter;
      report msg_id & " : " & msg
      severity warning;
      
   end;

   ----------------------------------------------------------------------------
   -- Report Error
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_error (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   ) is
   begin
      if not disable_all_error_msg then
         statistics.inc_error_counter;
         report msg_id & " : " & msg
            severity error;
      else
         statistics.inc_info_counter;
         report msg_id & " : " & msg
            severity note;
      end if;
   end;

   ----------------------------------------------------------------------------
   -- Report Fatal
   -- Report Info Message 
   ----------------------------------------------------------------------------
   procedure report_fatal (
      msg_id : in string; -- string to print
      msg    : in string -- string to print
   ) is
   begin
      statistics.inc_fatal_counter;
      report msg_id & " : " & msg
      severity failure;
   end;

   ----------------------------------------------------------------------------
   -- End of Test Procedure
   -- It prints End of Test delimiter to the simulation output
   -- stream (transcript). 
   ----------------------------------------------------------------------------
   procedure report_test_end 
   is
   begin
     report_info("TEST", "---------------------------");
     report_info("TEST", "Test finished successfully!");
     report_info("TEST", "---------------------------");
     report_info("STATISTICS", "Report Statistics: " & LF &
       "INFO Message Count:     " & justify(to_string(statistics.get_info_count),    field => 4) & LF &
       "WARNING Message Count:  " & justify(to_string(statistics.get_warning_count), field => 4) & LF &
       "ERROR Message Count:    " & justify(to_string(statistics.get_error_count),   field => 4) & LF &
       "FATAL Message Count:    " & justify(to_string(statistics.get_fatal_count),   field => 4));
   end;

   ----------------------------------------------------------------------------
   -- End of Test Procedure (Timeout)
   -- It prints End of Test delimiter caused by timeout to the simulation
   -- output stream (transcript). 
   ----------------------------------------------------------------------------
   procedure report_test_timeout
   is
   begin
     report_info( "TEST", "-------------------------");
     report_error("TEST", "Test finished on timeout!");
     report_info( "TEST", "-------------------------");
   end;

end report_utils_pkg;
