--=============================================================================
-- Description: IBIS macro library implemented in Verilog-A(MS)
-- Created: October 2005 by Arpad Muranyi (Intel Corporation)
--
-- Revision history:
--
-- 2005/10/10  Verilog-A rev0.0 completed
-- 2005/10/19  - Fixed IBIS_K to include the Scale parameter in the
--               calculation of M.
--             - Fixed IBIS_T equations
-- 2005/10/27  - Added the 10 PWL sources
-- 2005/11/03  - Changed IBIS_TCVS_PWL and IBIS_TCCS_PWL sources to do HE
--             - Changed the four event controlled PWL sources to have two
--               data tables with independent threshold voltages (one for
--               each triggering edge direction), and to do HE
--
--=============================================================================
-- List of building blocks contained in this library:
--
-- IBIS_R             (p, n);
-- IBIS_VCR           (p, n, ps, ns);
-- IBIS_CCR           (p, n, ps, ns);
--
-- IBIS_C             (p, n);
-- IBIS_VCC           (p, n, ps, ns);
-- IBIS_CCC           (p, n, ps, ns);
--
-- IBIS_L             (p, n);
-- IBIS_VCL           (p, n, ps, ns);
-- IBIS_CCL           (p, n, ps, ns);
-- IBIS_K             (p1, n1, p2, n2);
--
-- IBIS_V             (p, n);
-- IBIS_VCVS          (p, n, ps, ns);
-- IBIS_CCVS          (p, n, ps, ns);
-- IBIS_VCVS_DELAY    (p, n, ps, ns);
-- IBIS_CCVS_DELAY    (p, n, ps, ns);
-- IBIS_VCVS_MIN      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCVS_MIN      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCVS_MAX      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCVS_MAX      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCVS_ABS      (p, n, ps, ns);
-- IBIS_CCVS_ABS      (p, n, ps, ns);
-- IBIS_VCVS_SUM      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCVS_SUM      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCVS_MULT     (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCVS_MULT     (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCVS_DIV      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCVS_DIV      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCVS_PWL      (p, n, ps, ns);
-- IBIS_CCVS_PWL      (p, n, ps, ns);
-- IBIS_TCVS_PWL      (p, n);
-- IBIS_VECVS_PWL     (p, n, ps, ns);
-- IBIS_CECVS_PWL     (p, n, ps, ns);
--
-- IBIS_I             (p, n);
-- IBIS_VCCS          (p, n, ps, ns);
-- IBIS_CCCS          (p, n, ps, ns);
-- IBIS_VCCS_DELAY    (p, n, ps, ns);
-- IBIS_CCCS_DELAY    (p, n, ps, ns);
-- IBIS_VCCS_MIN      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCCS_MIN      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCCS_MAX      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCCS_MAX      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCCS_ABS      (p, n, ps, ns);
-- IBIS_CCCS_ABS      (p, n, ps, ns);
-- IBIS_VCCS_SUM      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCCS_SUM      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCCS_MULT     (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCCS_MULT     (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCCS_DIV      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_CCCS_DIV      (p, n, ps1, ns1, ps2, ns2);
-- IBIS_VCCS_PWL      (p, n, ps, ns);
-- IBIS_CCCS_PWL      (p, n, ps, ns);
-- IBIS_TCCS_PWL      (p, n);
-- IBIS_VECCS_PWL     (p, n, ps, ns);
-- IBIS_CECCS_PWL     (p, n, ps, ns);
--
-- IBIS_T             (n1, ref1, n2, ref2);
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_R is

    generic ( 
      Rval  : real := 1.0;
      Scale : real := 1.0);

    port (terminal p, n : electrical);

  end entity IBIS_R;
  --===========================================================================
  architecture ideal of IBIS_R is

  quantity Vout across Iout through p to n;

  begin

    Vout == Scale * Rval * Iout;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCR is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCR;
  --===========================================================================
  architecture ideal of IBIS_VCR is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Vout == Scale * Vin * Iout;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCR is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCR;
  --===========================================================================
  architecture ideal of IBIS_CCR is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    Vout == Scale * Iin * Iout;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_C is

    generic ( 
      Cval  : real := 1.0;
      V0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n : electrical);

  end entity IBIS_C;
  --===========================================================================
  architecture ideal of IBIS_C is

  quantity Vout across Iout through p to n;

  begin

    if domain = quiescent_domain use
      Vout == V0;
    else
      Iout == Scale * Cval * Vout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCC is

    generic ( 
      V0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCC;
  --===========================================================================
  architecture ideal of IBIS_VCC is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    if domain = quiescent_domain use
      Vout == V0;
    else
      Iout == Vout * Scale * Vin'dot + Scale * Vin * Vout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCC is

    generic ( 
      V0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCC;
  --===========================================================================
  architecture ideal of IBIS_CCC is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    if domain = quiescent_domain use
      Vout == V0;
    else
      Iout == Vout * Scale * Iin'dot + Scale * Iin * Vout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_L is

    generic ( 
      Lval  : real := 1.0;
      I0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n : electrical);

  end entity IBIS_L;
  --===========================================================================
  architecture ideal of IBIS_L is

  quantity Vout across Iout through p to n;

  begin

    if domain = quiescent_domain use
      Iout == I0;
    else
      Vout == Scale * Lval * Iout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCL is

    generic ( 
      I0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCL;
  --===========================================================================
  architecture ideal of IBIS_VCL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    if domain = quiescent_domain use
      Iout == I0;
    else
      Vout == Iout * Scale * Vin'dot + Scale * Vin * Iout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCL is

    generic ( 
      I0    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCL;
  --===========================================================================
  architecture ideal of IBIS_CCL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    if domain = quiescent_domain use
      Iout == I0;
    else
      Vout == Iout * Scale * Iin'dot + Scale * Iin * Iout'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_K is

    generic ( 
      Lval_1 : real := 1.0;
      Lval_2 : real := 1.0;
      Kval   : real := 0.0;
      I0_1   : real := 0.0;
      I0_2   : real := 0.0;
      Scale  : real := 1.0);

    port (terminal p1, n1, p2, n2 : electrical);

  end entity IBIS_K;
  --===========================================================================
  architecture ideal of IBIS_K is

  quantity Vout1 across Iout1 through p1 to n1;
  quantity Vout2 across Iout2 through p2 to n2;
  constant M : real := Scale * Kval * sqrt(Lval_1 * Lval_2);

  begin

    if domain = quiescent_domain use
      Iout1 == I0_1;
      Iout2 == I0_2;
    else
      Vout1 == Scale * Lval_1 * Iout1'dot + M * Iout2'dot;
      Vout2 == Scale * Lval_2 * Iout2'dot + M * Iout1'dot;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_V is

    generic ( 
      Vdc   : real := 1.0;
      Scale : real := 1.0);

    port (terminal p, n : electrical);

  end entity IBIS_V;
  --===========================================================================
  architecture ideal of IBIS_V is

  quantity Vout across Iout through p to n;

  begin

    Vout == Scale * Vdc;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCVS;
  --===========================================================================
  architecture ideal of IBIS_VCVS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Vout == Scale * Vin;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCVS;
  --===========================================================================
  architecture ideal of IBIS_CCVS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    Vout == Scale * Iin;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_DELAY is

    generic ( 
      TD    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCVS_DELAY;
  --===========================================================================
  architecture ideal of IBIS_VCVS_DELAY is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Vout == Scale * Vin'delayed(TD);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_DELAY is

    generic ( 
      TD    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCVS_DELAY;
  --===========================================================================
  architecture ideal of IBIS_CCVS_DELAY is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  quantity Iin_as_real  : real;   -- Delete these two lines when the last line
  quantity Iin_real_del : real;   -- in the code works

  begin

    Vin  == 0.0;
    Iin_as_real  == Iin;
    Iin_real_del == Iin_as_real'delayed(TD);
    Vout == Scale * Iin_real_del;
--  Vout == Scale * Iin'delayed(TD);   -- Delete the above 3 lines if this works

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_VCVS_MIN is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCVS_MIN;
  --===========================================================================
  architecture ideal of IBIS_VCVS_MIN is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Vout == Scale * realmin(Vin1, Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_CCVS_MIN is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCVS_MIN;
  --===========================================================================
  architecture ideal of IBIS_CCVS_MIN is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Vout == Scale * realmin(Iin1, Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_VCVS_MAX is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCVS_MAX;
  --===========================================================================
  architecture ideal of IBIS_VCVS_MAX is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Vout == Scale * realmax(Vin1, Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_CCVS_MAX is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCVS_MAX;
  --===========================================================================
  architecture ideal of IBIS_CCVS_MAX is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Vout == Scale * realmax(Iin1, Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_ABS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCVS_ABS;
  --===========================================================================
  architecture ideal of IBIS_VCVS_ABS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Vout == Scale * abs(Vin);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_ABS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCVS_ABS;
  --===========================================================================
  architecture ideal of IBIS_CCVS_ABS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    Vout == Scale * abs(Iin);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_SUM is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCVS_SUM;
  --===========================================================================
  architecture ideal of IBIS_VCVS_SUM is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Vout == Scale * (Vin1 + Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_SUM is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCVS_SUM;
  --===========================================================================
  architecture ideal of IBIS_CCVS_SUM is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Vout == Scale * (Iin1 + Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_MULT is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCVS_MULT;
  --===========================================================================
  architecture ideal of IBIS_VCVS_MULT is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Vout == Scale * Vin1 * Vin2;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_MULT is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCVS_MULT;
  --===========================================================================
  architecture ideal of IBIS_CCVS_MULT is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Vout == Scale * Iin1 * Iin2;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_DIV is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCVS_DIV;
  --===========================================================================
  architecture ideal of IBIS_VCVS_DIV is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    if Vin2 /= 0.0 use
      Vout == Scale * Vin1 / Vin2;
    else
      Vout == real'high;     -- instead of inf;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_DIV is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCVS_DIV;
  --===========================================================================
  architecture ideal of IBIS_CCVS_DIV is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    if Iin2 /= 0.0 use
      Vout == Scale * Iin1 / Iin2;
    else
      Vout == real'high;     -- instead of inf;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCVS_PWL is

    generic ( 
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (-5.00,  0.00,  5.00, 10.00);
      Y : real_vector := (-0.10,  0.00,  0.10,  0.10));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCVS_PWL;
  --===========================================================================
  architecture ideal of IBIS_VCVS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Vout == Scale * Lookup(Vin, X, Y, "SE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCVS_PWL is

    generic ( 
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (-5.00,  0.00,  5.00, 10.00);
      Y : real_vector := (-0.10,  0.00,  0.10,  0.10));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCVS_PWL;
  --===========================================================================
  architecture ideal of IBIS_CCVS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Vin  == 0.0;
    Vout == Scale * Lookup(Iin, X, Y, "SE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_TCVS_PWL is

    generic ( 
      Scale : real := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      Y : real_vector := (0.00,     0.10,     0.90,     1.00));

    port (terminal p, n : electrical);

  end entity IBIS_TCVS_PWL;
  --===========================================================================
  architecture ideal of IBIS_TCVS_PWL is

  quantity Vout across Iout through p to n;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Vout == Scale * Lookup(now, X, Y, "HE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VECVS_PWL is

    generic ( 
      Vth_R  : real    := 0.0;
      Vth_F  : real    := 0.0;
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      XR : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YR : real_vector := (0.00,     0.10,     0.90,     1.00);
      XF : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YF : real_vector := (1.00,     0.90,     0.10,     0.00));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VECVS_PWL;
  --===========================================================================
  architecture ideal of IBIS_VECVS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;
  signal   T_event    : real    := 0.0;
  signal   EventState : integer := 0;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    ---------------------------------------------------------------------------
    Threshold_crossing : process is
    begin
      if domain = quiescent_domain then
        wait until domain /= quiescent_domain;
        if Vin > Vth_R then            -- high state
          EventState <= 1;
        elsif Vin < Vth_F then         -- low state
          EventState <= -1;
        end if;
      else
        wait on Vin'above(Vth_R), Vin'above(Vth_F);
        if Vin > Vth_R then            -- rising edge
          EventState <= 2;
          T_event    <= now;
        elsif Vin < Vth_F then         -- falling edge
          EventState <= -2;
          T_event    <= now;
        end if;
      end if;
    end process Threshold_crossing;
    ---------------------------------------------------------------------------

    case EventState use
      when -2 =>        -- Executes after falling edge events
        Vout == Scale * Lookup(now-T_event, XF, YF, "HE");
      when -1 =>        -- Executes between t=0 and first threshold crossing
        Vout == Scale * Lookup(0.0, XR, YR, "HE");    -- when input is LOW
      when 1 =>         -- Executes between t=0 and first threshold crossing
        Vout == Scale * Lookup(0.0, XF, YF, "HE");    -- when input is HIGH
      when 2 =>         -- Executes after rising edge events
        Vout == Scale * Lookup(now-T_event, XR, YR, "HE");
      when others =>    -- Executes during DC operating point analysis
        if Vin > Vth_R use
          Vout == Scale * Lookup(0.0, XF, YF, "HE");
        elsif Vin < Vth_F use
          Vout == Scale * Lookup(0.0, XR, YR, "HE");
        else
          Vout == Scale * (Lookup(0.0, XR, YR, "HE") + Lookup(0.0, XF, YF, "HE")) / 2.0;
        end use;
    end case;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CECVS_PWL is

    generic ( 
      Ith_R  : real    := 0.0;
      Ith_F  : real    := 0.0;
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      XR : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YR : real_vector := (0.00,     0.10,     0.90,     1.00);
      XF : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YF : real_vector := (1.00,     0.90,     0.10,     0.00));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CECVS_PWL;
  --===========================================================================
  architecture ideal of IBIS_CECVS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  signal   T_event    : real    := 0.0;
  signal   EventState : integer := 0;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    ---------------------------------------------------------------------------
    Threshold_crossing : process is
    begin
      if domain = quiescent_domain then
        wait until domain /= quiescent_domain;
        if Iin > Ith_R then            -- high state
          EventState <= 1;
        elsif Iin < Ith_F then         -- low state
          EventState <= -1;
        end if;
      else
        wait on Iin'above(Ith_R), Iin'above(Ith_F);
        if Iin > Ith_R then            -- rising edge
          EventState <= 2;
          T_event    <= now;
        elsif Iin < Ith_F then         -- falling edge
          EventState <= -2;
          T_event    <= now;
        end if;
      end if;
    end process Threshold_crossing;
    ---------------------------------------------------------------------------

    Vin == 0.0;
    case EventState use
      when -2 =>        -- Executes after falling edge events
        Vout == Scale * Lookup(now-T_event, XF, YF, "HE");
      when -1 =>        -- Executes between t=0 and first threshold crossing
        Vout == Scale * Lookup(0.0, XR, YR, "HE");    -- when input is LOW
      when 1 =>         -- Executes between t=0 and first threshold crossing
        Vout == Scale * Lookup(0.0, XF, YF, "HE");    -- when input is HIGH
      when 2 =>         -- Executes after rising edge events
        Vout == Scale * Lookup(now-T_event, XR, YR, "HE");
      when others =>    -- Executes during DC operating point analysis
        if Iin > Ith_R use
          Vout == Scale * Lookup(0.0, XF, YF, "HE");
        elsif Iin < Ith_F use
          Vout == Scale * Lookup(0.0, XR, YR, "HE");
        else
          Vout == Scale * (Lookup(0.0, XR, YR, "HE") + Lookup(0.0, XF, YF, "HE")) / 2.0;
        end use;
    end case;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_I is

    generic ( 
      Idc   : real := 1.0;
      Scale : real := 1.0);

    port (terminal p, n : electrical);

  end entity IBIS_I;
  --===========================================================================
  architecture ideal of IBIS_I is

  quantity Vout across Iout through p to n;

  begin

    Iout == Scale * Idc;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCCS;
  --===========================================================================
  architecture ideal of IBIS_VCCS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Iout == Scale * Vin;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCCS;
  --===========================================================================
  architecture ideal of IBIS_CCCS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    Iout == Scale * Iin;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_DELAY is

    generic ( 
      TD    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCCS_DELAY;
  --===========================================================================
  architecture ideal of IBIS_VCCS_DELAY is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Iout == Scale * Vin'delayed(TD);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_DELAY is

    generic ( 
      TD    : real := 0.0;
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCCS_DELAY;
  --===========================================================================
  architecture ideal of IBIS_CCCS_DELAY is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  quantity Iin_as_real  : real;   -- Delete these two lines when the last line
  quantity Iin_real_del : real;   -- in the code works

  begin

    Vin  == 0.0;
    Iin_as_real  == Iin;
    Iin_real_del == Iin_as_real'delayed(TD);
    Iout == Scale * Iin_real_del;
--  Iout == Scale * Iin'delayed(TD);   -- Delete the above 3 lines if this works

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_VCCS_MIN is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCCS_MIN;
  --===========================================================================
  architecture ideal of IBIS_VCCS_MIN is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Iout == Scale * realmin(Vin1, Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_CCCS_MIN is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCCS_MIN;
  --===========================================================================
  architecture ideal of IBIS_CCCS_MIN is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Iout == Scale * realmin(Iin1, Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_VCCS_MAX is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCCS_MAX;
  --===========================================================================
  architecture ideal of IBIS_VCCS_MAX is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Iout == Scale * realmax(Vin1, Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
use IEEE.math_real.all;
--=============================================================================
  entity IBIS_CCCS_MAX is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCCS_MAX;
  --===========================================================================
  architecture ideal of IBIS_CCCS_MAX is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Iout == Scale * realmax(Iin1, Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_ABS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCCS_ABS;
  --===========================================================================
  architecture ideal of IBIS_VCCS_ABS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;

  begin

    Iout == Scale * abs(Vin);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_ABS is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCCS_ABS;
  --===========================================================================
  architecture ideal of IBIS_CCCS_ABS is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;

  begin

    Vin  == 0.0;
    Iout == Scale * abs(Iin);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_SUM is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCCS_SUM;
  --===========================================================================
  architecture ideal of IBIS_VCCS_SUM is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Iout == Scale * (Vin1 + Vin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_SUM is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCCS_SUM;
  --===========================================================================
  architecture ideal of IBIS_CCCS_SUM is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Iout == Scale * (Iin1 + Iin2);

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_MULT is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCCS_MULT;
  --===========================================================================
  architecture ideal of IBIS_VCCS_MULT is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    Iout == Scale * Vin1 * Vin2;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_MULT is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCCS_MULT;
  --===========================================================================
  architecture ideal of IBIS_CCCS_MULT is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    Iout == Scale * Iin1 * Iin2;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_DIV is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_VCCS_DIV;
  --===========================================================================
  architecture ideal of IBIS_VCCS_DIV is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across              ps1 to ns1;
  quantity Vin2 across              ps2 to ns2;

  begin

    if Vin2 /= 0.0 use
      Iout == Scale * Vin1 / Vin2;
    else
      Iout == real'high;     -- instead of inf;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_DIV is

    generic ( 
      Scale : real := 1.0);

    port (terminal p, n, ps1, ns1, ps2, ns2 : electrical);

  end entity IBIS_CCCS_DIV;
  --===========================================================================
  architecture ideal of IBIS_CCCS_DIV is

  quantity Vout across Iout through p   to n;
  quantity Vin1 across Iin1 through ps1 to ns1;
  quantity Vin2 across Iin2 through ps2 to ns2;

  begin

    Vin1 == 0.0;
    Vin2 == 0.0;
    if Iin2 /= 0.0 use
      Iout == Scale * Iin1 / Iin2;
    else
      Iout == real'high;     -- instead of inf;
    end use;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VCCS_PWL is

    generic ( 
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (-5.00,  0.00,  5.00, 10.00);
      Y : real_vector := (-0.10,  0.00,  0.10,  0.10));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VCCS_PWL;
  --===========================================================================
  architecture ideal of IBIS_VCCS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Iout == Scale * Lookup(Vin, X, Y, "SE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CCCS_PWL is

    generic ( 
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (-5.00,  0.00,  5.00, 10.00);
      Y : real_vector := (-0.10,  0.00,  0.10,  0.10));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CCCS_PWL;
  --===========================================================================
  architecture ideal of IBIS_CCCS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Vin  == 0.0;
    Iout == Scale * Lookup(Iin, X, Y, "SE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_TCCS_PWL is

    generic ( 
      Scale : real := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      X : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      Y : real_vector := (0.00,     0.10,     0.90,     1.00));

    port (terminal p, n : electrical);

  end entity IBIS_TCCS_PWL;
  --===========================================================================
  architecture ideal of IBIS_TCCS_PWL is

  quantity Vout across Iout through p to n;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    Iout == Scale * Lookup(now, X, Y, "HE");

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_VECCS_PWL is

    generic ( 
      Vth_R  : real    := 0.0;
      Vth_F  : real    := 0.0;
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      XR : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YR : real_vector := (0.00,     0.10,     0.90,     1.00);
      XF : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YF : real_vector := (1.00,     0.90,     0.10,     0.00));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_VECCS_PWL;
  --===========================================================================
  architecture ideal of IBIS_VECCS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across              ps to ns;
  signal   T_event    : real    := 0.0;
  signal   EventState : integer := 0;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    ---------------------------------------------------------------------------
    Threshold_crossing : process is
    begin
      if domain = quiescent_domain then
        wait until domain /= quiescent_domain;
        if Vin > Vth_R then            -- high state
          EventState <= 1;
        elsif Vin < Vth_F then         -- low state
          EventState <= -1;
        end if;
      else
        wait on Vin'above(Vth_R), Vin'above(Vth_F);
        if Vin > Vth_R then            -- rising edge
          EventState <= 2;
          T_event    <= now;
        elsif Vin < Vth_F then         -- falling edge
          EventState <= -2;
          T_event    <= now;
        end if;
      end if;
    end process Threshold_crossing;
    ---------------------------------------------------------------------------

    case EventState use
      when -2 =>        -- Executes after falling edge events
        Iout == Scale * Lookup(now-T_event, XF, YF, "HE");
      when -1 =>        -- Executes between t=0 and first threshold crossing
        Iout == Scale * Lookup(0.0, XR, YR, "HE");    -- when input is LOW
      when 1 =>         -- Executes between t=0 and first threshold crossing
        Iout == Scale * Lookup(0.0, XF, YF, "HE");    -- when input is HIGH
      when 2 =>         -- Executes after rising edge events
        Iout == Scale * Lookup(now-T_event, XR, YR, "HE");
      when others =>    -- Executes during DC operating point analysis
        if Vin > Vth_R use
          Iout == Scale * Lookup(0.0, XF, YF, "HE");
        elsif Vin < Vth_F use
          Iout == Scale * Lookup(0.0, XR, YR, "HE");
        else
          Iout == Scale * (Lookup(0.0, XR, YR, "HE") + Lookup(0.0, XF, YF, "HE")) / 2.0;
        end use;
    end case;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_CECCS_PWL is

    generic ( 
      Ith_R  : real    := 0.0;
      Ith_F  : real    := 0.0;
      Scale  : real    := 1.0;
      -------------------------------------------------------------------------
      -- Vectors of the PWL table
      -------------------------------------------------------------------------
      XR : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YR : real_vector := (0.00,     0.10,     0.90,     1.00);
      XF : real_vector := (0.50e-9,  1.00e-9,  2.00e-9,  2.50e-9);
      YF : real_vector := (1.00,     0.90,     0.10,     0.00));

    port (terminal p, n, ps, ns : electrical);

  end entity IBIS_CECCS_PWL;
  --===========================================================================
  architecture ideal of IBIS_CECCS_PWL is

  quantity Vout across Iout through p  to n;
  quantity Vin  across Iin  through ps to ns;
  signal   T_event    : real    := 0.0;
  signal   EventState : integer := 0;
  --===========================================================================
  function Lookup (X             : in real;
                   Xdata         : in real_vector;
                   Ydata         : in real_vector;
                   Extrapolation : in 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(0)) then
      m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0));
      yvalue := Ydata(0) + m * (X - Xdata(0));
      return yvalue;

    elsif (Extrapolation = "HE") and (X <= Xdata(0)) then
      yvalue := Ydata(0);
      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:= 0;
      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;
  --===========================================================================

  begin

    ---------------------------------------------------------------------------
    Threshold_crossing : process is
    begin
      if domain = quiescent_domain then
        wait until domain /= quiescent_domain;
        if Iin > Ith_R then            -- high state
          EventState <= 1;
        elsif Iin < Ith_F then         -- low state
          EventState <= -1;
        end if;
      else
        wait on Iin'above(Ith_R), Iin'above(Ith_F);
        if Iin > Ith_R then            -- rising edge
          EventState <= 2;
          T_event    <= now;
        elsif Iin < Ith_F then         -- falling edge
          EventState <= -2;
          T_event    <= now;
        end if;
      end if;
    end process Threshold_crossing;
    ---------------------------------------------------------------------------

    Vin == 0.0;
    case EventState use
      when -2 =>        -- Executes after falling edge events
        Iout == Scale * Lookup(now-T_event, XF, YF, "HE");
      when -1 =>        -- Executes between t=0 and first threshold crossing
        Iout == Scale * Lookup(0.0, XR, YR, "HE");    -- when input is LOW
      when 1 =>         -- Executes between t=0 and first threshold crossing
        Iout == Scale * Lookup(0.0, XF, YF, "HE");    -- when input is HIGH
      when 2 =>         -- Executes after rising edge events
        Iout == Scale * Lookup(now-T_event, XR, YR, "HE");
      when others =>    -- Executes during DC operating point analysis
        if Iin > Ith_R use
          Iout == Scale * Lookup(0.0, XF, YF, "HE");
        elsif Iin < Ith_F use
          Iout == Scale * Lookup(0.0, XR, YR, "HE");
        else
          Iout == Scale * (Lookup(0.0, XR, YR, "HE") + Lookup(0.0, XF, YF, "HE")) / 2.0;
        end use;
    end case;

  end architecture ideal;
--=============================================================================
--=============================================================================
library IEEE;
use IEEE.electrical_systems.all;
--=============================================================================
  entity IBIS_T is

    generic ( 
      Z0 : real := 50.0;
      TD : real := 1.0e-9);

    port (terminal n1, ref1, n2, ref2 : electrical);

  end entity IBIS_T;
  --===========================================================================
  architecture Ideal of IBIS_T is

  quantity Vend1 across Iend1 through n1 to ref1;
  quantity Vend2 across Iend2 through n2 to ref2;

  quantity i12 : real;  -- Current wave traveling from end1 to end2
  quantity i21 : real;  -- Current wave traveling from end2 to end1

  begin

    Iend1 == i12 - i21'delayed(TD);
    Iend2 == i21 - i12'delayed(TD);
    Vend1 == Z0 * (2.0 * i12 - Iend1);
    Vend2 == Z0 * (2.0 * i21 - Iend2);

  end architecture Ideal;
--=============================================================================
--=============================================================================
