-- *********************************************************
-- ASIC support functions
--
-- Version 0.1   Revised by: Don Gay  On: 10/02/90
--                   This is the initial writing.
--
-- Version 0.2   Revised by: Don Gay  On:  1/23/91
--                   fixed X delay calculation
--
-- Version 0.3   Revised by: Don Gay  On:  2/10/91
--                   Fixed Pulse width error message
--
-- Version 0.4   Revised by: Don Gay  On:  2/26/91
--                   Added delay_init and delay_matrix
--                   and removed Delay
--
-- Version 0.5   Revised by: Don Gay  On: 04/11/91
--                   Changed delay_init for speed increase
--                   Added Constant declarations
--
-- **********************************************************
-- Define the interface to these routines
-- **********************************************************
--
PACKAGE timing IS

type  DELAY_MATRIX is array (0 to 3, 0 to 3) of time;


-- Delay init
--
-- This function is passed timing numbers an it returns a delay matrix
-- that has been initialized
--
function DELAY_INIT (
                  constant TPHL     :  time;
                  constant TPLH     :  time;
                  constant TPHX     :  time;
                  constant TPLX     :  time)
               return DELAY_MATRIX;
         

-- Delay selection
--
--    Selects and returns the correct delay
function DELAY (
                  out_val  :  vlbit;
                  last_val :  vlbit;
                  TPHL     :  time;
                  TPLH     :  time;
                  TPHX     :  time;
                  TPLX     :  time)
               return time;


-- MAX TIME selection
--
--    Returns the largest of two time values
function MAXTIME (
                  constant time1    : time;
                  constant time2    : time)
               return time;


-- MIN TIME selection
--
--    Returns the smallest of two time values
function MINTIME (
                  constant time1    : time;
                  constant time2    : time)
               return time;


-- DELTA TIME selection
--
--    Returns a positive time value that is the difference between
--    the two time values input.
function DELTATIME (
                  constant time1    : time;
                  constant time2    : time)
               return time;


-- Setup Time Checking
--
--    Returns TRUE if setup time violation is detected; FALSE if no
--    violation is detected.
--
--    Called with Setup time, Reference time (Clock change time),
--    Data change time, and the setup being tested for the error report
function CHKSETUP (
                  constant setup    : time;
                  constant clk      : time;
                  constant data     : time;
                  constant setname  : string)
               return BOOLEAN;


-- Hold Time Checking
--
--    Returns TRUE if a hold time violation; FALSE if no
--    violation is detected.
--
--    Called with hold time, Reference time (Clock change time),
--    Data change time, and the hold being tested for the error report
function CHKHOLD (
                  constant hold     : time;
                  constant clk      : time;
                  constant data     : time;
                  constant holdname : string)
               return BOOLEAN;


-- Pulse Width Checking
--
--    Returns TRUE if a pulse width time violation is detected; FALSE if no
--    violation is detected.
--
--    Called with pulse width, First change time, Second change time
--    Data change time, and the signal name being tested for the error report
function CHKPULSEW (
                  constant width       : time;
                  constant edge1       : time;
                  constant edge2       : time;
                  constant pulsename   : string)
               return BOOLEAN;


-- Release time Checking
--
--    Returns TRUE if a release time violation is detected; FALSE if no
--    violation is detected.
--
--    Called with release time, Released time, Clock time,
--    and the signal name being tested for the error report
function CHKRELEASET (
                  constant Spec        : time;
                  constant edge        : time;
                  constant clock       : time;
                  constant valuename   : string)
               return BOOLEAN;


END timing;


-- **********************************************************
-- Define the functions
-- **********************************************************
--
PACKAGE BODY timing IS
--


-- Delay init
--
-- This function is passed timing numbers an it returns a delay matrix
-- that has been initialized
--
function DELAY_INIT (
                  constant TPHL     :  time;
                  constant TPLH     :  time;
                  constant TPHX     :  time;
                  constant TPLX     :  time)
   return DELAY_MATRIX is

   variable matrix      :  DELAY_MATRIX;

   begin


      -- Note: The matrix is a VLBIT width in each direction and the
      --       first variable is the new output value, the second variable
      --       is the last output value
      -- 
      --       The invalid cases are in the matrix are not initialized.


      matrix(0,0) := TPLX;
         -- This is X new value and X old value - startup
      matrix(0,2) := TPLX;
         -- This is X new value and 0 old value
      matrix(0,3) := TPHX;
         -- This is X new value and 1 old value

      matrix(2,0) := TPHL;
         -- This is 0 new value and X old value
      matrix(2,3) := TPHL;
         -- This is 0 new value and 1 old value


      matrix(3,0) := TPLH;
         -- This is 1 new value and X old value
      matrix(3,2) := TPLH;
         -- This is 1 new value and 0 old value

return matrix;

end DELAY_INIT;


-- Delay selection
--
--    Selects and returns the correct delay
function DELAY (
                  constant out_val  :  vlbit;
                  constant last_val :  vlbit;
                  constant TPHL     :  time;
                  constant TPLH     :  time;
                  constant TPHX     :  time;
                  constant TPLX     :  time)
   return time is
   
   begin

       case out_val is
         when '0' => return TPHL;
         when '1' => return TPLH;
         when others =>
            case last_val is
               when '0' => return TPLX;
               when '1' => return TPHX;
               -- When others returns shortest delay to X
               when others =>
                  if (TPLX > TPHX) then return TPHX;
                     else return TPLX;
                  end if;
            end case;
     end case;

end DELAY;


-- MAX TIME selection
--
--    Returns the largest of two time values
function MAXTIME (
                  constant time1    : time;
                  constant time2    : time)
   return time is

begin

   if (time1 > time2) then return time1;
   end if;
   return time2;

end MAXTIME;


-- MIN TIME selection
--
--    Returns the smallest of two time values
function MINTIME (
                  constant time1    : time;
                  constant time2    : time)
   return time is

begin

   if (time1 > time2) then return time2;
   end if;
   return time1;

end MINTIME;


-- DELTA TIME selection
--
--    Returns a positive time value that is the difference between
--    the two time values input.
function DELTATIME (
                  constant time1    : time;
                  constant time2    : time)
   return time is

begin

   return (abs(time1 - time2));

end DELTATIME;


-- Setup Time Checking
--
--    Returns TRUE if a setup time violation; FALSE if no
--    violation is detected.
--
--    Called with Setup time, Reference time (Clock change time),
--    Data change time, and the setup name for the error report
function CHKSETUP (
                  constant setup    : time;
                  constant clk      : time;
                  constant data     : time;
                  constant setname  : string)


   return BOOLEAN is

begin

   -- Suppress Errors at time 0
   if ((now <= 0 ns) or

   -- Check the setup time
   ( (data + setup) <= clk )) then return( false );
   end if;

	-- if got here then error
   putline("Error: Setup time violation at time ",now);
       put("       For clk at ",clk);
   putline(" and Data at ",data);
       put("       Setup of ",(clk - data));
       put(" checked against ",setup);
   putline(" for ",setname);

return( True );

end CHKSETUP;


-- hold Time Checking
--
--    Returns TRUE if a hold time violation is detected; FALSE if no
--    violation is detected.
--
--    Called with hold time, Reference time (Clock change time),
--    Data change time, and the hold name for the error report
function CHKHOLD (
                  constant hold     : time;
                  constant clk      : time;
                  constant data     : time;
                  constant holdname : string)


   return BOOLEAN is

begin

   -- Suppress Errors at time 0
   if ((now <= 0 ns) or

   -- Check the hold time
   ( data >= (clk + hold))) then return( False );
   end if;

	-- if got here then error
   putline("Error: Hold time violation at time ",now);
       put("       For clk at ",clk);
   putline(" and Data at ",data);
       put("       Hold of ",(data - clk));
       put(" checked against ",hold);
   putline(" for ",holdname);
return( TRUE );

end CHKhold;


-- Pulse Width Checking
--
--    Returns TRUE if a pulse width time violation; FALSE if no
--    violation is detected.
--
--    Called with pulse width, First change time, Second change time
--    Data change time, and the signal name being tested for the error report
function CHKPULSEW (
                  constant width       : time;
                  constant edge1       : time;
                  constant edge2       : time;
                  constant pulsename   : string)

   return BOOLEAN is

begin

   -- Suppress Errors at time 0
   if (now <= 0 ns) then return( False );
   end if;

   -- Check the pulse width
   if ( width <= (edge2 - edge1)) then return( False );
   end if;

	-- if got here then error
   putline("Error: Pulse Width violation at time ",now);
   putline("       For signal: ",pulsename);
   return( TRUE );

end CHKPULSEW;


-- Release time Checking
--
--    Returns TRUE if a release time violation is detected; FALSE if no
--    violation is detected.
--
--    Called with release time, Released time, Clock time,
--    and the signal name being tested for the error report
function CHKRELEASET (
                  constant Spec        : time;
                  constant edge        : time;
                  constant clock       : time;
                  constant valuename   : string)

   return BOOLEAN is

begin

   -- Suppress Errors at time 0
   if (now <= 0 ns) then return( False );

   -- Check the release time
   elsif ( (Spec + edge) < clock ) then return( False );
	end if;

	-- if got here then error
   putline("Error: Release time violation at time ",now);
   putline("       For signal: ",valuename);
   return( TRUE );

end CHKRELEASET;

END timing;

