--=============================================================================
library IEEE, std;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
use std.textio.all;
--=============================================================================

package MacroLib_functions is

--=============================================================================
function Resize (InVec : real_vector; Length : integer) return real_vector;
-------------------------------------------------------------------------------
impure function FileRead (FileName      : string  := "";
                          ParameterName : string  := "";
                          Default       : real    := 0.0) return real;
-------------------------------------------------------------------------------
impure function FileRead (FileName      : string      := "";
                          ParameterName : string      := "";
                          DefaultVec    : real_vector;
                          Elements      : integer) return real_vector;
-------------------------------------------------------------------------------
function Lookup (X             : real;
                 Xdata         : real_vector;
                 Ydata         : real_vector;
                 Extrapolation : string := "SE") return real;
-------------------------------------------------------------------------------
function FindCommonLength (Max_dt : real;
                           T_r1   : real_vector;
                           T_r2   : real_vector;
                           T_f1   : real_vector;
                           T_f2   : real_vector) return integer;
-------------------------------------------------------------------------------
function FindCommonLength (Max_dt : real;
                           T_r1   : real_vector;
                           T_f1   : real_vector) return integer;
-------------------------------------------------------------------------------
function CommonTime (Common_length : integer;
                     Max_dt        : real;
                     T_r1          : real_vector;
                     T_r2          : real_vector;
                     T_f1          : real_vector;
                     T_f2          : real_vector) return real_vector;
-------------------------------------------------------------------------------
function CommonTime (Common_length : integer;
                     Max_dt        : real;
                     T_r1          : real_vector;
                     T_f1          : real_vector) return real_vector;
--=============================================================================

end package MacroLib_functions;

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

package body MacroLib_functions is

--=============================================================================
function Resize (InVec : real_vector; Length : integer) return real_vector is
-------------------------------------------------------------------------------
  variable ReturnVec : real_vector(1 to Length);
  -----------------------------------------------------------------------------
  begin
    for i in 1 to Length loop
      ReturnVec(i) := InVec(InVec'left+i-1);
    end loop;
  return ReturnVec;
  -----------------------------------------------------------------------------
end function Resize;
--=============================================================================
impure function FileRead (FileName      : string  := "";
                          ParameterName : string  := "";
                          Default       : real    := 0.0) return real is 
-------------------------------------------------------------------------------
  file     DataFileObject : text;
  variable FileOpenStatus : file_open_status;
  variable LineText       : line;
  variable FoundFlag      : boolean := false;
  variable ReadOK         : boolean := true;
  variable NotOpen        : boolean := true;
  variable NoFileName     : boolean := true;
  variable ReturnVal      : real    := Default;
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  if not(FileName = "") then
    NoFileName := false;
    file_open(FileOpenStatus, DataFileObject, FileName, read_mode);
    ---------------------------------------------------------------------------
    -- Loop in the file to find the parameter name and then read its value
    ---------------------------------------------------------------------------
    if (FileOpenStatus = open_ok) then
      NotOpen := false;
      while not(endfile(DataFileObject) or FoundFlag) loop
        readline(DataFileObject, LineText);
        if (LineText.all = (ParameterName & CR) or
            LineText.all = (ParameterName & LF) or
            LineText.all = (ParameterName & CR & LF) or
            LineText.all = (ParameterName & LF & CR)) then

          FoundFlag := true;

          readline(DataFileObject, LineText);
          read(LineText, ReturnVal, ReadOK);
        end if;
      end loop;
    end if;
    ---------------------------------------------------------------------------
    file_close(DataFileObject);
  end if;
  -----------------------------------------------------------------------------
  -- Use default vaue if nothing was found
  -----------------------------------------------------------------------------
  if not(FoundFlag) or not(ReadOK) or NotOpen or NoFileName then
    ReturnVal := Default;
  end if;
  -----------------------------------------------------------------------------
  -- Give a little feedback on what happened
  -----------------------------------------------------------------------------
  if NoFileName then
    report "No parameter file name was given.  A default of " & real'image(ReturnVal) & 
           " will be used for " & ParameterName & "."
           severity WARNING;
  elsif NotOpen then
    report "Could not open file '" & FileName &
           "'.  A default of " & real'image(ReturnVal) & " will be used for " & ParameterName & "."
           severity WARNING;
  elsif not(FoundFlag) or not(ReadOK) then
    report "Could not find a value for " & ParameterName & " in file '" & FileName &
           "'.  A default of " & real'image(ReturnVal) & " will be used for " & ParameterName & "."
           severity WARNING;
  end if;
  -----------------------------------------------------------------------------
  return ReturnVal;
  -----------------------------------------------------------------------------
end function FileRead;
--=============================================================================
impure function FileRead (FileName      : string      := "";
                          ParameterName : string      := "";
                          DefaultVec    : real_vector;
                          Elements      : integer) return real_vector is
-------------------------------------------------------------------------------
  file     DataFileObject : text;
  variable FileOpenStatus : file_open_status;
  variable LineText       : line;
  variable FoundFlag      : boolean := false;
  variable ReadOK         : boolean := true;
  variable NotOpen        : boolean := true;
  variable NoFileName     : boolean := true;
  variable Count          : integer := 0;
  variable ReturnVec      : real_vector(1 to Elements);
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  if not(FileName = "") then
    NoFileName := false;
    file_open(FileOpenStatus, DataFileObject, FileName, read_mode);
    ---------------------------------------------------------------------------
    -- Loop in the file to find the parameter name and then read the table
    ---------------------------------------------------------------------------
    if (FileOpenStatus = open_ok) then
      NotOpen := false;
      while not(endfile(DataFileObject) or FoundFlag) loop
        readline(DataFileObject, LineText);
        if (LineText.all = (ParameterName & CR) or
            LineText.all = (ParameterName & LF) or
            LineText.all = (ParameterName & CR & LF) or
            LineText.all = (ParameterName & LF & CR)) then

          FoundFlag := true;

          while ReadOK = true loop
            Count := Count + 1;
            exit when (Count > Elements);
            readline(DataFileObject, LineText);
            read(LineText, ReturnVec(Count), ReadOK);
          end loop;

        end if;
      end loop;
    end if;
    ---------------------------------------------------------------------------
    file_close(DataFileObject);
  end if;
  -----------------------------------------------------------------------------
  -- Use the default vector if nothing was found
  -----------------------------------------------------------------------------
  if not(FoundFlag) or NotOpen or NoFileName then
    Count := 0;
    for i in DefaultVec'range loop
      Count := Count + 1;
      ReturnVec(Count) := DefaultVec(i);
    end loop;
    Count := Count + 1;      -- To make it consistent with WHILE loop going over by one.
  end if;
  -----------------------------------------------------------------------------
  -- Give a little feedback on what happened
  -----------------------------------------------------------------------------
  if NoFileName then
    report "No parameter file name was given.  A short 4-point default table will be used for "
           & ParameterName & "."
           severity WARNING;
  elsif NotOpen then
    report "Could not open file '" & FileName &
           "'.  A short 4-point default table will be used for " & ParameterName & "."
           severity WARNING;
  elsif not(FoundFlag) then
    report "Could not find data table for " & ParameterName & " in file '" & FileName &
           "'.  A short 4-point default table will be used."
           severity WARNING;
  end if;
  -----------------------------------------------------------------------------
  return Resize(ReturnVec, Count-1);
  -----------------------------------------------------------------------------
end function FileRead;
--=============================================================================
function Lookup (X             : real;
                 Xdata         : real_vector;
                 Ydata         : real_vector;
                 Extrapolation : string := "SE") return real is
-------------------------------------------------------------------------------
-- This function returns "Y" that corresponds to "X" in the "Ydata" "Xdata"
-- input pair using linear interpolation.
--
-- If the "X" input value lies outside the range of "Xdata", the returned
-- "Y" value will either be equal to the first or last point in "Ydata",
-- or it will be calculated using the slope between the first or last two
-- points of "Ydata".  The extrapolation method is determined by the string
-- in "Extrapolation".  "HE" stands for "Horizontal Extrapolation" which
-- selects the former method, and "SE" stands for "Slope Extrapolation" which
-- selects the latter method.
--
-- Acknowledgements:  The original version of this function was developed by
-- Mentor Graphics Corporation.  Modifications added by Intel Corporation.
-------------------------------------------------------------------------------
  variable xvalue, yvalue, m : real;
  variable start, fin, mid   : integer; 
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  -- Handle cases when "X" is outside the range of "Xdata"
  -----------------------------------------------------------------------------
  if (Extrapolation = "SE") and (X <= Xdata(Xdata'left)) then
    m := (Ydata(Ydata'left+1) - Ydata(Ydata'left)) / (Xdata(Xdata'left+1) - Xdata(Xdata'left));
    yvalue := Ydata(Ydata'left) + m * (X - Xdata(Xdata'left));
    return yvalue;

  elsif (Extrapolation = "HE") and (X <= Xdata(Xdata'left)) then
    yvalue := Ydata(Ydata'left);
    return yvalue;

  elsif (Extrapolation = "SE") and (X >= Xdata(Xdata'right)) then
    m := (Ydata(Ydata'right) - Ydata(Ydata'right-1)) / (Xdata(Xdata'right) - Xdata(Xdata'right-1));
    yvalue := Ydata(Ydata'right) + m * (X - Xdata(Xdata'right));
    return yvalue;

  elsif (Extrapolation = "HE") and (X >= Xdata(Xdata'right)) then
    yvalue := Ydata(Ydata'right);
    return yvalue;
  -----------------------------------------------------------------------------
  -- Handle cases when "X" is in the range of "Xdata"
  -----------------------------------------------------------------------------
  else
    start:= Xdata'left;
    fin := Xdata'right;

    while  start <= fin  loop
      mid := (start + fin) / 2; 

      if Xdata(mid) < X then
        start := mid + 1;
      else fin := mid - 1;
      end if;  

    end loop; 
                     
    if Xdata(mid) > X then
      mid := mid - 1; 
    end if;
    ---------------------------------------------------------------------------
    -- Find "Y" by linear interpolation
    ---------------------------------------------------------------------------
    yvalue := Ydata(mid) + (X - Xdata(mid)) * (Ydata(mid+1) - Ydata(mid)) / (Xdata(mid+1) - Xdata(mid));
    return yvalue;
  -----------------------------------------------------------------------------
  end if;
  -----------------------------------------------------------------------------
end function Lookup;
--=============================================================================
function FindCommonLength (Max_dt : real;
                           T_r1   : real_vector;
                           T_r2   : real_vector;
                           T_f1   : real_vector;
                           T_f2   : real_vector) return integer is
-------------------------------------------------------------------------------
-- This function finds the total number of points needed for having a
-- common time axis for all Vt curves, such that the maximum delta time
-- between each time point doesn't exceed the value provided in "Max_dt".
-------------------------------------------------------------------------------
  variable T_index      : integer := 1;

  variable Index_r1     : integer := T_r1'left;
  variable Index_r2     : integer := T_r2'left;
  variable Index_f1     : integer := T_f1'left;
  variable Index_f2     : integer := T_f2'left;

  variable New_index_r1 : integer := T_r1'left;
  variable New_index_r2 : integer := T_r2'left;
  variable New_index_f1 : integer := T_f1'left;
  variable New_index_f2 : integer := T_f2'left;

  variable Old_t        : real    := 0.0;
  variable Last_t       : real    := 0.0;
  variable New_t        : real    := 0.0;
-------------------------------------------------------------------------------
begin
  --report "Length R1: " & integer'image(T_r1'right-T_r1'left+1);
  --report "Length R2: " & integer'image(T_r2'right-T_r2'left+1);
  --report "Length F1: " & integer'image(T_f1'right-T_f1'left+1);
  --report "Length F2: " & integer'image(T_f2'right-T_f2'left+1);
  -----------------------------------------------------------------------------
  -- Put the earliest time value of all given time vectors into "Old_t"
  -----------------------------------------------------------------------------
  Old_t := realmin(T_r1(T_r1'left), T_r2(T_r2'left));
  Old_t := realmin(Old_t, T_f1(T_f1'left));
  Old_t := realmin(Old_t, T_f2(T_f2'left));
  -----------------------------------------------------------------------------
  -- Put the latest time value of all given time vectors into "New_t"
  -----------------------------------------------------------------------------
  Last_t := realmax(T_r1(T_r1'right), T_r2(T_r2'right));
  Last_t := realmax(New_t, T_f1(T_f1'right));
  Last_t := realmax(New_t, T_f2(T_f2'right));
  New_t  := Last_t;
  -----------------------------------------------------------------------------
  -- Loop until latest time value is reached in each given time vector
  -----------------------------------------------------------------------------
  while (Old_t < New_t) loop
    T_index := T_index + 1;
    ---------------------------------------------------------------------------
    -- Find which given time vector(s) have the lowest time value and
    -- advance their temporary indexes
    ---------------------------------------------------------------------------
    if (T_r1(Index_r1) <= Old_t) then New_index_r1 := Index_r1 + 1;
    end if;
    if (T_r2(Index_r2) <= Old_t) then New_index_r2 := Index_r2 + 1;
    end if;
    if (T_f1(Index_f1) <= Old_t) then New_index_f1 := Index_f1 + 1;
    end if;
    if (T_f2(Index_f2) <= Old_t) then New_index_f2 := Index_f2 + 1;
    end if;
    ---------------------------------------------------------------------------
    -- Find the lowest value at the new indexes in the given vector(s) and
    -- update indexes for next iteration
    ---------------------------------------------------------------------------
    if (New_index_r1 <= T_r1'right) then
      if (T_r1(New_index_r1) < New_t) then New_t := T_r1(New_index_r1);
      end if;
      Index_r1 := New_index_r1;
    end if;
    if (New_index_r2 <= T_r2'right) then
      if (T_r2(New_index_r2) < New_t) then New_t := T_r2(New_index_r2);
      end if;
      Index_r2 := New_index_r2;
    end if;
    if (New_index_f1 <= T_f1'right) then
      if (T_f1(New_index_f1) < New_t) then New_t := T_f1(New_index_f1);
      end if;
      Index_f1 := New_index_f1;
    end if;
    if (New_index_f2 <= T_f2'right) then
      if (T_f2(New_index_f2) < New_t) then New_t := T_f2(New_index_f2);
      end if;
      Index_f2 := New_index_f2;
    end if;
    ---------------------------------------------------------------------------
    -- Calculate how many additional points are needed between the given
    -- points to satisfy the "Max_dt" separation criteria.
    ---------------------------------------------------------------------------
    if ((New_t-Old_t) > Max_dt) then
      T_index := T_index + integer(ceil((New_t-Old_t)/Max_dt)) - 1;
    end if;
    ---------------------------------------------------------------------------
    -- Update variables for next iteration
    ---------------------------------------------------------------------------
    Old_t := New_t;
    New_t := Last_t;
  -----------------------------------------------------------------------------
  end loop; 
  -----------------------------------------------------------------------------
  --report "Common length: " & integer'image(T_index);
  return T_index;
end function FindCommonLength;
--===========================================================================
function FindCommonLength (Max_dt : real;
                           T_r1   : real_vector;
                           T_f1   : real_vector) return integer is
-------------------------------------------------------------------------------
-- This function finds the total number of points needed for having a
-- common time axis for all Vt curves, such that the maximum delta time
-- between each time point doesn't exceed the value provided in "Max_dt".
-------------------------------------------------------------------------------
  variable T_index      : integer := 1;

  variable Index_r1     : integer := T_r1'left;
  variable Index_f1     : integer := T_f1'left;

  variable New_index_r1 : integer := T_r1'left;
  variable New_index_f1 : integer := T_f1'left;

  variable Old_t        : real    := 0.0;
  variable Last_t       : real    := 0.0;
  variable New_t        : real    := 0.0;
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  -- Put the earliest time value of all given time vectors into "Old_t"
  -----------------------------------------------------------------------------
  Old_t := realmin(T_r1(T_r1'left), T_f1(T_f1'left));
  -----------------------------------------------------------------------------
  -- Put the latest time value of all given time vectors into "New_t"
  -----------------------------------------------------------------------------
  Last_t := realmax(T_r1(T_r1'right), T_f1(T_f1'right));
  New_t  := Last_t;
  -----------------------------------------------------------------------------
  -- Loop until latest time value is reached in each given time vector
  -----------------------------------------------------------------------------
  while (Old_t < New_t) loop
    T_index := T_index + 1;
    ---------------------------------------------------------------------------
    -- Find which given time vector(s) have the lowest time value and
    -- advance their temporary indexes
    ---------------------------------------------------------------------------
    if (T_r1(Index_r1) <= Old_t) then New_index_r1 := Index_r1 + 1;
    end if;
    if (T_f1(Index_f1) <= Old_t) then New_index_f1 := Index_f1 + 1;
    end if;
    ---------------------------------------------------------------------------
    -- Find the lowest value at the new indexes in the given vector(s) and
    -- update indexes for next iteration
    ---------------------------------------------------------------------------
    if (New_index_r1 <= T_r1'right) then
      if (T_r1(New_index_r1) < New_t) then New_t := T_r1(New_index_r1);
      end if;
      Index_r1 := New_index_r1;
    end if;
    if (New_index_f1 <= T_f1'right) then
      if (T_f1(New_index_f1) < New_t) then New_t := T_f1(New_index_f1);
      end if;
      Index_f1 := New_index_f1;
    end if;
    ---------------------------------------------------------------------------
    -- Calculate how many additional points are needed between the given
    -- points to satisfy the "Max_dt" separation criteria.
    ---------------------------------------------------------------------------
    if ((New_t-Old_t) > Max_dt) then
      T_index := T_index + integer(ceil((New_t-Old_t)/Max_dt)) - 1;
    end if;
    ---------------------------------------------------------------------------
    -- Update variables for next iteration
    ---------------------------------------------------------------------------
    Old_t := New_t;
    New_t := Last_t;
  -----------------------------------------------------------------------------
  end loop; 
  -----------------------------------------------------------------------------
  --report "Common length: " & integer'image(T_index);
  return T_index;
end function FindCommonLength;
--=============================================================================
function CommonTime (Common_length : integer;
                     Max_dt        : real;
                     T_r1          : real_vector;
                     T_r2          : real_vector;
                     T_f1          : real_vector;
                     T_f2          : real_vector) return real_vector is
-------------------------------------------------------------------------------
-- This function generates a vector that serves as a common time axis for
-- all Vt curves, such that the maximum delta time between each time point
-- doesn't exceed the value provided in "Max_dt".
-------------------------------------------------------------------------------
  variable T_common       : real_vector(1 to Common_length) := (others => 0.0);
  variable T_index        : integer := 1;

  variable Index_r1       : integer := T_r1'left;
  variable Index_r2       : integer := T_r2'left;
  variable Index_f1       : integer := T_f1'left;
  variable Index_f2       : integer := T_f2'left;

  variable New_index_r1   : integer := T_r1'left;
  variable New_index_r2   : integer := T_r2'left;
  variable New_index_f1   : integer := T_f1'left;
  variable New_index_f2   : integer := T_f2'left;

  variable Old_t          : real    := 0.0;
  variable Last_t         : real    := 0.0;
  variable New_t          : real    := 0.0;

  variable Additional_pts : real    := 0.0;
  variable New_dt         : real    := 0.0;
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  -- Put the earliest time value of all given time vectors into "Old_t"
  -----------------------------------------------------------------------------
  Old_t := realmin(T_r1(T_r1'left), T_r2(T_r2'left));
  Old_t := realmin(Old_t, T_f1(T_f1'left));
  Old_t := realmin(Old_t, T_f2(T_f2'left));
  -----------------------------------------------------------------------------
  -- Put the latest time value of all given time vectors into "New_t"
  -----------------------------------------------------------------------------
  Last_t := realmax(T_r1(T_r1'right), T_r2(T_r2'right));
  Last_t := realmax(New_t, T_f1(T_f1'right));
  Last_t := realmax(New_t, T_f2(T_f2'right));
  New_t  := Last_t;
  -----------------------------------------------------------------------------
  -- Loop until latest time value is reached in each given time vector
  -----------------------------------------------------------------------------
  while (Old_t < New_t) loop
    ---------------------------------------------------------------------------
    -- Save the time value from Old_t in T_common
    -- and increment T_index counter
    ---------------------------------------------------------------------------
    T_common(T_index) := Old_t;
    T_index := T_index + 1;
    ---------------------------------------------------------------------------
    -- Find which given time vector(s) have the lowest time value and
    -- advance their temporary indexes
    ---------------------------------------------------------------------------
    if (T_r1(Index_r1) <= Old_t) then New_index_r1 := Index_r1 + 1;
    end if;
    if (T_r2(Index_r2) <= Old_t) then New_index_r2 := Index_r2 + 1;
    end if;
    if (T_f1(Index_f1) <= Old_t) then New_index_f1 := Index_f1 + 1;
    end if;
    if (T_f2(Index_f2) <= Old_t) then New_index_f2 := Index_f2 + 1;
    end if;
    ---------------------------------------------------------------------------
    -- Find the lowest value at the new indexes in the given vector(s) and
    -- update indexes for next iteration
    ---------------------------------------------------------------------------
    if (New_index_r1 <= T_r1'right) then
      if (T_r1(New_index_r1) < New_t) then New_t := T_r1(New_index_r1);
      end if;
      Index_r1 := New_index_r1;
    end if;
    if (New_index_r2 <= T_r2'right) then
      if (T_r2(New_index_r2) < New_t) then New_t := T_r2(New_index_r2);
      end if;
      Index_r2 := New_index_r2;
    end if;
    if (New_index_f1 <= T_f1'right) then
      if (T_f1(New_index_f1) < New_t) then New_t := T_f1(New_index_f1);
      end if;
      Index_f1 := New_index_f1;
    end if;
    if (New_index_f2 <= T_f2'right) then
      if (T_f2(New_index_f2) < New_t) then New_t := T_f2(New_index_f2);
      end if;
      Index_f2 := New_index_f2;
    end if;
    ---------------------------------------------------------------------------
    -- Calculate how many additional points are needed between the given
    -- points to satisfy the "Max_dt" separation criteria.
    ---------------------------------------------------------------------------
    if ((New_t-Old_t) > Max_dt) then
      Additional_pts := ceil((New_t-Old_t)/Max_dt);
      New_dt := (New_t-Old_t) / Additional_pts;
      for i in 1 to integer(Additional_pts)-1 loop
        T_common(T_index) := T_common(T_index-1) + New_dt;
        T_index := T_index + 1;
      end loop;
    end if;
    ---------------------------------------------------------------------------
    -- Update variables for next iteration
    ---------------------------------------------------------------------------
    Old_t := New_t;
    New_t := Last_t;
  -----------------------------------------------------------------------------
    --report "T_common: " & real'image(T_common(T_index-1));
  end loop; 
  T_common(T_index) := Last_t;
  --report "T_common: " & real'image(T_common(T_index));
  -----------------------------------------------------------------------------
  --report "Length of T_common: " & integer'image(T_index);
  return T_common;
end function CommonTime;
--=============================================================================
function CommonTime (Common_length : integer;
                     Max_dt        : real;
                     T_r1          : real_vector;
                     T_f1          : real_vector) return real_vector is
-------------------------------------------------------------------------------
-- This function generates a vector that serves as a common time axis for
-- all Vt curves, such that the maximum delta time between each time point
-- doesn't exceed the value provided in "Max_dt".
-------------------------------------------------------------------------------
  variable T_common       : real_vector(1 to Common_length) := (others => 0.0);
  variable T_index        : integer := 1;

  variable Index_r1       : integer := T_r1'left;
  variable Index_f1       : integer := T_f1'left;

  variable New_index_r1   : integer := T_r1'left;
  variable New_index_f1   : integer := T_f1'left;

  variable Old_t          : real    := 0.0;
  variable Last_t         : real    := 0.0;
  variable New_t          : real    := 0.0;

  variable Additional_pts : real    := 0.0;
  variable New_dt         : real    := 0.0;
-------------------------------------------------------------------------------
begin
  -----------------------------------------------------------------------------
  -- Put the earliest time value of all given time vectors into "Old_t"
  -----------------------------------------------------------------------------
  Old_t := realmin(T_r1(T_r1'left), T_f1(T_f1'left));
  -----------------------------------------------------------------------------
  -- Put the latest time value of all given time vectors into "New_t"
  -----------------------------------------------------------------------------
  Last_t := realmax(T_r1(T_r1'right), T_f1(T_f1'right));
  New_t  := Last_t;
  -----------------------------------------------------------------------------
  -- Loop until latest time value is reached in each given time vector
  -----------------------------------------------------------------------------
  while (Old_t < New_t) loop
    ---------------------------------------------------------------------------
    -- Save the time value from Old_t in T_common
    -- and increment T_index counter
    ---------------------------------------------------------------------------
    T_common(T_index) := Old_t;
    T_index := T_index + 1;
    ---------------------------------------------------------------------------
    -- Find which given time vector(s) have the lowest time value and
    -- advance their temporary indexes
    ---------------------------------------------------------------------------
    if (T_r1(Index_r1) <= Old_t) then New_index_r1 := Index_r1 + 1;
    end if;
    if (T_f1(Index_f1) <= Old_t) then New_index_f1 := Index_f1 + 1;
    end if;
    ---------------------------------------------------------------------------
    -- Find the lowest value at the new indexes in the given vector(s) and
    -- update indexes for next iteration
    ---------------------------------------------------------------------------
    if (New_index_r1 <= T_r1'right) then
      if (T_r1(New_index_r1) < New_t) then New_t := T_r1(New_index_r1);
      end if;
      Index_r1 := New_index_r1;
    end if;
    if (New_index_f1 <= T_f1'right) then
      if (T_f1(New_index_f1) < New_t) then New_t := T_f1(New_index_f1);
      end if;
      Index_f1 := New_index_f1;
    end if;
    ---------------------------------------------------------------------------
    -- Calculate how many additional points are needed between the given
    -- points to satisfy the "Max_dt" separation criteria.
    ---------------------------------------------------------------------------
    if ((New_t-Old_t) > Max_dt) then
      Additional_pts := ceil((New_t-Old_t)/Max_dt);
      New_dt := (New_t-Old_t) / Additional_pts;
      for i in 1 to integer(Additional_pts)-1 loop
        T_common(T_index) := T_common(T_index-1) + New_dt;
        T_index := T_index + 1;
      end loop;
    end if;
    ---------------------------------------------------------------------------
    -- Update variables for next iteration
    ---------------------------------------------------------------------------
    Old_t := New_t;
    New_t := Last_t;
  -----------------------------------------------------------------------------
    --report "T_common: " & real'image(T_common(T_index-1));
  end loop; 
  T_common(T_index) := Last_t;
  --report "T_common: " & real'image(T_common(T_index));
  -----------------------------------------------------------------------------
  --report "Length of T_common: " & integer'image(T_index);
  return T_common;
end function CommonTime;
--=============================================================================

end package body MacroLib_functions;

--=============================================================================
