-------------------------------------------------------------------------------
-- Title        : Standard VITAL_Primitives Package
--              : $Revision$
--              :
-- Library      : VITAL
--              :
-- Developers   : IEEE DASC Timing Working Group (TWG), PAR 1076.4
--              :
-- Purpose      : This packages defines standard types, constants, functions
--              : and procedures for use in developing ASIC models.
--              : Specifically a set of logic primitives are defined.
--              :  
-- ----------------------------------------------------------------------------
--
-- ----------------------------------------------------------------------------
-- Modification History : 
-- ----------------------------------------------------------------------------
-- Version No:|Auth:| Mod.Date:| Changes Made:
--   v95.0 A  |     | 06/02/95 | Initial ballot draft 1995
--   v95.1    |     | 08/31/95 | #204 - glitch detection prior to OutputMap
-- ----------------------------------------------------------------------------

LIBRARY STD;
USE STD.TEXTIO.ALL;

PACKAGE BODY VITAL_Primitives IS
    -- ------------------------------------------------------------------------
    --  Default values for Primitives
    -- ------------------------------------------------------------------------
    --  default values for delay parameters
    CONSTANT VitalDefDelay01  : VitalDelayType01  := VitalZeroDelay01;
    CONSTANT VitalDefDelay01Z : VitalDelayType01Z := VitalZeroDelay01Z;

    TYPE VitalTimeArray IS ARRAY (NATURAL RANGE <>) OF TIME;    

    --  default primitive model operation parameters
    --  Glitch detection/reporting
    TYPE VitalGlitchModeType IS ( MessagePlusX, MessageOnly, XOnly, NoGlitch);
    CONSTANT PrimGlitchMode : VitalGlitchModeType   := XOnly;

    -- ------------------------------------------------------------------------
    -- Local Type and Subtype Declarations
    -- ------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    -- enumeration value representing the transition or level of the signal.
    --  See function 'GetEdge'
    ---------------------------------------------------------------------------
    TYPE EdgeType IS ( 'U',   -- Uninitialized level
                       'X',   -- Unknown level
                       '0',   -- low level
                       '1',   -- high level
                       '\',   -- 1 to 0 falling edge
                       '/',   -- 0 to 1 rising  edge
                       'F',   -- * to 0 falling edge
                       'R',   -- * to 1 rising  edge
                       'f',   -- rising  to X edge
                       'r',   -- falling to X edge
                       'x',   -- Unknown edge (ie U->X)
                       'V'    -- Timing violation edge
                     );
    TYPE EdgeArray  IS ARRAY ( NATURAL RANGE <> ) OF EdgeType;

    TYPE EdgeX1Table IS ARRAY ( EdgeType                          ) OF EdgeType;
    TYPE EdgeX2Table IS ARRAY ( EdgeType, EdgeType                ) OF EdgeType;
    TYPE EdgeX3Table IS ARRAY ( EdgeType, EdgeType, EdgeType      ) OF EdgeType;
    TYPE EdgeX4Table IS ARRAY (EdgeType,EdgeType,EdgeType,EdgeType) OF EdgeType;

    TYPE LogicToEdgeT  IS ARRAY(std_ulogic, std_ulogic) OF EdgeType;
    TYPE LogicToLevelT IS ARRAY(std_ulogic ) OF EdgeType;

    TYPE GlitchDataType IS 
      RECORD 
        SchedTime    : TIME; 
        GlitchTime   : TIME; 
        SchedValue   : std_ulogic;
        CurrentValue    : std_ulogic; 
      END RECORD; 
    TYPE GlitchDataArrayType IS ARRAY (NATURAL RANGE <>) 
         OF GlitchDataType;
 
    -- Enumerated type used in selection of output path delays
    TYPE SchedType  IS
      RECORD
        inp0  : TIME;   -- time (abs) of output change due to input change to 0
        inp1  : TIME;   -- time (abs) of output change due to input change to 1
        InpX  : TIME;   -- time (abs) of output change due to input change to X
        Glch0 : TIME;   -- time (abs) of output glitch due to input change to 0
        Glch1 : TIME;   -- time (abs) of output glitch due to input change to 0
      END RECORD;

    TYPE SchedArray  IS ARRAY ( NATURAL RANGE <> ) OF SchedType;
    CONSTANT DefSchedType : SchedType := (TIME'HIGH, TIME'HIGH, 0 ns,0 ns,0 ns);
    CONSTANT DefSchedAnd  : SchedType := (TIME'HIGH, 0 ns,0 ns, TIME'HIGH,0 ns);

    -- Constrained array declarations (common sizes used by primitives)
    SUBTYPE SchedArray2 IS SchedArray(1 DOWNTO 0);
    SUBTYPE SchedArray3 IS SchedArray(2 DOWNTO 0);
    SUBTYPE SchedArray4 IS SchedArray(3 DOWNTO 0);
    SUBTYPE SchedArray8 IS SchedArray(7 DOWNTO 0);

    SUBTYPE TimeArray2 IS VitalTimeArray(1 DOWNTO 0);
    SUBTYPE TimeArray3 IS VitalTimeArray(2 DOWNTO 0);
    SUBTYPE TimeArray4 IS VitalTimeArray(3 DOWNTO 0);
    SUBTYPE TimeArray8 IS VitalTimeArray(7 DOWNTO 0);

    SUBTYPE GlitchArray2 IS GlitchDataArrayType(1 DOWNTO 0);
    SUBTYPE GlitchArray3 IS GlitchDataArrayType(2 DOWNTO 0);
    SUBTYPE GlitchArray4 IS GlitchDataArrayType(3 DOWNTO 0);
    SUBTYPE GlitchArray8 IS GlitchDataArrayType(7 DOWNTO 0);

    SUBTYPE EdgeArray2 IS EdgeArray(1 DOWNTO 0);
    SUBTYPE EdgeArray3 IS EdgeArray(2 DOWNTO 0);
    SUBTYPE EdgeArray4 IS EdgeArray(3 DOWNTO 0);
    SUBTYPE EdgeArray8 IS EdgeArray(7 DOWNTO 0);

    CONSTANT DefSchedArray2 : SchedArray2 :=
                             (OTHERS=> (0 ns, 0 ns, 0 ns, 0 ns, 0 ns));

    TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic;

    CONSTANT InitialEdge : LogicToLevelT := (
            '1'|'H' => 'R',
            '0'|'L' => 'F',
            OTHERS  => 'x'
     );

    CONSTANT LogicToEdge  : LogicToEdgeT  := (  -- previous, current
    --  old \ new: U    X    0    1    Z    W    L    H    -
        'U' =>  ( 'U', 'x', 'F', 'R', 'x', 'x', 'F', 'R', 'x' ),
        'X' =>  ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ),
        '0' =>  ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ),
        '1' =>  ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ),
        'Z' =>  ( 'x', 'X', 'F', 'R', 'X', 'x', 'F', 'R', 'x' ),
        'W' =>  ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' ),
        'L' =>  ( 'r', 'r', '0', '/', 'r', 'r', '0', '/', 'r' ),
        'H' =>  ( 'f', 'f', '\', '1', 'f', 'f', '\', '1', 'f' ),
        '-' =>  ( 'x', 'X', 'F', 'R', 'x', 'X', 'F', 'R', 'X' )
    );
    CONSTANT LogicToLevel : LogicToLevelT := (
            '1'|'H' => '1',
            '0'|'L' => '0',
            'U'     => 'U',
            OTHERS  => 'X'
     );

    -- -----------------------------------
    -- 3-state logic tables
    -- -----------------------------------
    CONSTANT BufIf0_Table : stdlogic_table :=
        -- enable        data       value
        ( '1'|'H'   => ( OTHERS  => 'Z' ),
          '0'|'L'   => ( '1'|'H' => '1',
                         '0'|'L' => '0',
                         'U'     => 'U',
                         OTHERS  => 'X' ),
          'U'       => ( OTHERS  => 'U' ),
          OTHERS    => ( OTHERS  => 'X' ) );
    CONSTANT BufIf1_Table : stdlogic_table :=
        -- enable        data       value
        ( '0'|'L'   => ( OTHERS  => 'Z' ),
          '1'|'H'   => ( '1'|'H' => '1',
                         '0'|'L' => '0',
                         'U'     => 'U',
                         OTHERS  => 'X' ),
          'U'       => ( OTHERS  => 'U' ),
          OTHERS    => ( OTHERS  => 'X' ) );
    CONSTANT InvIf0_Table : stdlogic_table :=
        -- enable        data       value
        ( '1'|'H'   => ( OTHERS  => 'Z' ),
          '0'|'L'   => ( '1'|'H' => '0',
                         '0'|'L' => '1',
                         'U'     => 'U',
                         OTHERS  => 'X' ),
          'U'       => ( OTHERS  => 'U' ),
          OTHERS    => ( OTHERS  => 'X' ) );
    CONSTANT InvIf1_Table : stdlogic_table :=
        -- enable        data       value
        ( '0'|'L'   => ( OTHERS  => 'Z' ),
          '1'|'H'   => ( '1'|'H' => '0',
                         '0'|'L' => '1',
                         'U'     => 'U',
                         OTHERS  => 'X' ),
          'U'       => ( OTHERS  => 'U' ),
          OTHERS    => ( OTHERS  => 'X' ) );


    TYPE To_StateCharType IS ARRAY (VitalStateSymbolType) OF CHARACTER;
    CONSTANT To_StateChar : To_StateCharType :=
     ( '/', '\', 'P', 'N', 'r', 'f', 'p', 'n', 'R', 'F', '^', 'v',
       'E', 'A', 'D', '*', 'X', '0', '1', '-', 'B', 'Z', 'S' );
    TYPE To_TruthCharType IS ARRAY (VitalTruthSymbolType) OF CHARACTER;
    CONSTANT To_TruthChar : To_TruthCharType :=
     ( 'X', '0', '1', '-', 'B', 'Z' );

    TYPE TruthTableOutMapType IS ARRAY (VitalTruthSymbolType) OF std_ulogic;
    CONSTANT TruthTableOutMap : TruthTableOutMapType :=
       --  'X', '0', '1', '-', 'B', 'Z'
         ( 'X', '0', '1', 'X', '-', 'Z' );

    TYPE StateTableOutMapType IS ARRAY (VitalStateSymbolType) OF std_ulogic;
    -- does conversion to X01Z or '-' if invalid
    CONSTANT StateTableOutMap : StateTableOutMapType :=
     -- '/' '\' 'P' 'N' 'r' 'f' 'p' 'n' 'R' 'F' '^' 'v'
     -- 'E' 'A' 'D' '*' 'X' '0' '1' '-' 'B' 'Z' 'S'
      ( '-','-','-','-','-','-','-','-','-','-','-','-',
        '-','-','-','-','X','0','1','X','-','Z','W');

    -- ------------------------------------------------------------------------
    TYPE ValidTruthTableInputType IS ARRAY (VitalTruthSymbolType) OF BOOLEAN;
    -- checks if a symbol IS valid for the stimulus portion of a truth table
    CONSTANT ValidTruthTableInput : ValidTruthTableInputType :=
       -- 'X'    '0'    '1'    '-'    'B'    'Z'
       (  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  FALSE );

    TYPE TruthTableMatchType IS ARRAY (X01, VitalTruthSymbolType) OF BOOLEAN;
    -- checks if an input matches th corresponding truth table symbol
    -- use: TruthTableMatch(input_converted_to_X01, truth_table_stimulus_symbol)
    CONSTANT TruthTableMatch : TruthTableMatchType  :=  (
       -- X,     0,     1,     -      B      Z
       (  TRUE,  FALSE, FALSE, TRUE,  FALSE, FALSE  ),  -- X
       (  FALSE, TRUE,  FALSE, TRUE,  TRUE,  FALSE  ),  -- 0
       (  FALSE, FALSE, TRUE,  TRUE,  TRUE,  FALSE  )   -- 1
    );

    -- ------------------------------------------------------------------------
    TYPE ValidStateTableInputType IS ARRAY (VitalStateSymbolType) OF BOOLEAN;
    CONSTANT ValidStateTableInput : ValidStateTableInputType :=
       -- '/',   '\',   'P',   'N',   'r',   'f',
      (   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
       -- 'p',   'n',   'R',   'F',   '^',   'v',
          TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
       -- 'E',   'A',    'D',  '*',
          TRUE,  TRUE,  TRUE,  TRUE,
       -- 'X',   '0',   '1',   '-',   'B',   'Z',
          TRUE,  TRUE,  TRUE,  TRUE,  TRUE, FALSE,
       -- 'S'
          TRUE );

    CONSTANT ValidStateTableState : ValidStateTableInputType :=
       -- '/',   '\',   'P',   'N',   'r',   'f',
      (   FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
       -- 'p',   'n',   'R',   'F',   '^',   'v',
          FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
       -- 'E',   'A',    'D',  '*',
          FALSE, FALSE, FALSE, FALSE,
       -- 'X',   '0',   '1',   '-',   'B',   'Z',
          TRUE,  TRUE,  TRUE,  TRUE,  TRUE,  FALSE,
       -- 'S'
          FALSE );

    TYPE StateTableMatchType IS ARRAY (X01,X01,VitalStateSymbolType) OF BOOLEAN;
    -- last value, present value, table symbol
    CONSTANT StateTableMatch : StateTableMatchType :=  (
      ( -- X (lastvalue)
     -- /     \     P     N     r     f
     -- p     n     R     F     ^     v
     -- E     A     D     *
     -- X     0     1     -     B     Z     S
      (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,
       TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE),
      (FALSE,FALSE,FALSE,TRUE, FALSE,FALSE,
       FALSE,FALSE,FALSE,TRUE, FALSE,TRUE,
       TRUE, FALSE,TRUE, TRUE,
       FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE),
      (FALSE,FALSE,TRUE, FALSE,FALSE,FALSE,
       FALSE,FALSE,TRUE, FALSE,TRUE, FALSE,
       TRUE, TRUE, FALSE,TRUE,
       FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE)
      ),

      (-- 0 (lastvalue)
     -- /     \     P     N     r     f
     -- p     n     R     F     ^     v
     -- E     A     D     *
     -- X     0     1     -     B     Z     S
      (FALSE,FALSE,FALSE,FALSE,TRUE, FALSE,
       TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
       FALSE,TRUE, FALSE,TRUE,
       TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE),
      (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,
       FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,TRUE ),
      (TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
       TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,TRUE,
       FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,FALSE)
      ),

      (-- 1 (lastvalue)
     -- /     \     P     N     r     f
     -- p     n     R     F     ^     v
     -- E     A     D     *
     -- X     0     1     -     B     Z     S
      (FALSE,FALSE,FALSE,FALSE,FALSE,TRUE ,
       FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
       FALSE,FALSE,TRUE, TRUE,
       TRUE, FALSE,FALSE,TRUE, FALSE,FALSE,FALSE),
      (FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
       FALSE,TRUE, FALSE,TRUE, FALSE,FALSE,
       FALSE,FALSE,FALSE,TRUE,
       FALSE,TRUE, FALSE,TRUE, TRUE, FALSE,FALSE),
      (FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,FALSE,FALSE,
       FALSE,FALSE,TRUE, TRUE, TRUE, FALSE,TRUE )
      )
      );

    TYPE Logic_UX01Z_Table IS ARRAY (std_ulogic) OF UX01Z;
    ----------------------------------------------------------
    -- table name : cvt_to_x01z
    -- parameters :  std_ulogic  -- some logic value
    -- returns    :  UX01Z       -- state value of logic value
    -- purpose    :  to convert state-strength to state only
    ----------------------------------------------------------
    CONSTANT cvt_to_ux01z : Logic_UX01Z_Table :=
                                ('U','X','0','1','Z','X','0','1','X' );

    TYPE LogicCvtTableType IS ARRAY (std_ulogic) OF CHARACTER; 
    CONSTANT LogicCvtTable : LogicCvtTableType 
                     := ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'); 

    --------------------------------------------------------------------
    -- LOCAL Utilities
    --------------------------------------------------------------------
    -- ------------------------------------------------------------------------
    --  FUNCTION  NAME  :  MINIMUM
    --
    --  PARAMETERS      :  in1, in2  - integer, time
    --
    --  DESCRIPTION     :  return smaller of in1 and in2
    -- ------------------------------------------------------------------------
    FUNCTION Minimum (
            CONSTANT in1, in2 : INTEGER
          ) RETURN INTEGER IS
    BEGIN
       IF (in1 < in2) THEN
          RETURN in1;
       END IF;
       RETURN in2;
    END;
    -- ------------------------------------------------------------------------
    FUNCTION Minimum (
            CONSTANT t1,t2 : IN TIME
          ) RETURN TIME IS
    BEGIN
        IF ( t1 < t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF;
    END Minimum;

    -- ------------------------------------------------------------------------
    --  FUNCTION  NAME  :  MAXIMUM
    --
    --  PARAMETERS      :  in1, in2  - integer, time
    --
    --  DESCRIPTION     :  return larger of in1 and in2
    -- ------------------------------------------------------------------------
    FUNCTION Maximum (
            CONSTANT in1, in2 : INTEGER
          ) RETURN INTEGER IS
    BEGIN
       IF (in1 > in2) THEN
          RETURN in1;
       END IF;
       RETURN in2;
    END;
    -----------------------------------------------------------------------
    FUNCTION Maximum (
            CONSTANT t1,t2 : IN TIME
          ) RETURN TIME IS
    BEGIN
        IF ( t1 > t2 ) THEN RETURN (t1); ELSE RETURN (t2); END IF;
    END Maximum;

    -----------------------------------------------------------------------
    FUNCTION GlitchMinTime (
            CONSTANT Time1, Time2 : IN TIME
          ) RETURN TIME IS
    BEGIN
        IF ( Time1 >= NOW ) THEN
                IF ( Time2 >= NOW ) THEN
                  RETURN Minimum ( Time1, Time2);
                ELSE
                  RETURN Time1;
                END IF;
        ELSE
                IF ( Time2 >= NOW ) THEN
                   RETURN Time2;
                ELSE
                   RETURN 0 ns;
                END IF;
        END IF;
    END;

    --------------------------------------------------------------------
    -- Error Message Types and Tables
    --------------------------------------------------------------------
    TYPE VitalErrorType IS (
        ErrNegDel,
        ErrInpSym,
        ErrOutSym,
        ErrStaSym,
        ErrVctLng,
        ErrTabWidSml,
        ErrTabWidLrg,
        ErrTabResSml,
        ErrTabResLrg
    );

    TYPE VitalErrorSeverityType IS ARRAY (VitalErrorType) OF SEVERITY_LEVEL;
    CONSTANT VitalErrorSeverity : VitalErrorSeverityType := (
        ErrNegDel    => WARNING,
        ErrInpSym    => ERROR,
        ErrOutSym    => ERROR,
        ErrStaSym    => ERROR,
        ErrVctLng    => ERROR,
        ErrTabWidSml => ERROR,
        ErrTabWidLrg => WARNING,
        ErrTabResSml => WARNING,
        ErrTabResLrg => WARNING
    );

    CONSTANT MsgNegDel : STRING :=
      "Negative delay. New output value not scheduled. Output signal is: ";
    CONSTANT MsgInpSym : STRING :=
      "Illegal symbol in the input portion of a Truth/State table.";
    CONSTANT MsgOutSym : STRING :=
      "Illegal symbol in the output portion of a Truth/State table.";
    CONSTANT MsgStaSym : STRING :=
      "Illegal symbol in the state portion of a State table.";
    CONSTANT MsgVctLng : STRING :=
      "Vector (array) lengths not equal. ";
    CONSTANT MsgTabWidSml : STRING :=
      "Width of the Truth/State table is too small.";
    CONSTANT MsgTabWidLrg : STRING :=
      "Width of Truth/State table is too large. Extra elements are ignored.";
    CONSTANT MsgTabResSml : STRING :=
      "Result of Truth/State table has too many elements.";
    CONSTANT MsgTabResLrg : STRING :=
      "Result of Truth/State table has too few elements.";

    CONSTANT MsgUnknown : STRING :=
      "Unknown error message.";

    --------------------------------------------------------------------
    -- LOCAL Utilities
    --------------------------------------------------------------------
    FUNCTION VitalMessage (
            CONSTANT ErrorId : IN VitalErrorType
          ) RETURN STRING IS
    BEGIN
        CASE ErrorId IS
            WHEN ErrNegDel    => RETURN MsgNegDel;
            WHEN ErrInpSym    => RETURN MsgInpSym;
            WHEN ErrOutSym    => RETURN MsgOutSym;
            WHEN ErrStaSym    => RETURN MsgStaSym;
            WHEN ErrVctLng    => RETURN MsgVctLng;
            WHEN ErrTabWidSml => RETURN MsgTabWidSml;
            WHEN ErrTabWidLrg => RETURN MsgTabWidLrg;
            WHEN ErrTabResSml => RETURN MsgTabResSml;
            WHEN ErrTabResLrg => RETURN MsgTabResLrg;
            WHEN OTHERS       => RETURN MsgUnknown;
        END CASE;
    END;

    PROCEDURE VitalError (
            CONSTANT Routine : IN STRING;
            CONSTANT ErrorId : IN VitalErrorType
    ) IS
    BEGIN
        ASSERT FALSE
          REPORT Routine & ": " & VitalMessage(ErrorId)
          SEVERITY VitalErrorSeverity(ErrorId);
    END;

    PROCEDURE VitalError (
            CONSTANT Routine : IN STRING;
            CONSTANT ErrorId : IN VitalErrorType;
            CONSTANT Info    : IN STRING
    ) IS
    BEGIN
        ASSERT FALSE
          REPORT Routine & ": " & VitalMessage(ErrorId) & Info
          SEVERITY VitalErrorSeverity(ErrorId);
    END;

    PROCEDURE VitalError (
            CONSTANT Routine : IN STRING;
            CONSTANT ErrorId : IN VitalErrorType;
            CONSTANT Info    : IN CHARACTER
    ) IS
    BEGIN
        ASSERT FALSE
          REPORT Routine & ": " & VitalMessage(ErrorId) & Info
          SEVERITY VitalErrorSeverity(ErrorId);
    END;

    ---------------------------------------------------------------------------
    PROCEDURE ReportGlitch ( 
            CONSTANT GlitchRoutine  : IN  STRING;
            CONSTANT OutSignalName  : IN  STRING;
            CONSTANT PreemptedTime  : IN  TIME;
            CONSTANT PreemptedValue : IN  std_ulogic;
            CONSTANT NewTime        : IN  TIME;
            CONSTANT NewValue       : IN  std_ulogic;
            CONSTANT Index          : IN  INTEGER := 0;
            CONSTANT IsArraySignal  : IN  BOOLEAN := FALSE;
            CONSTANT MsgSeverity    : IN  SEVERITY_LEVEL := WARNING
    ) IS

        VARIABLE StrPtr1, StrPtr2, StrPtr3, StrPtr4, StrPtr5 : LINE;
    BEGIN

        Write (StrPtr1, PreemptedTime );
        Write (StrPtr2, NewTime);
        Write (StrPtr3, LogicCvtTable(PreemptedValue));
        Write (StrPtr4, LogicCvtTable(NewValue));
        IF IsArraySignal THEN
            Write (StrPtr5, STRING'( "(" ) );
            Write (StrPtr5, Index);
            Write (StrPtr5, STRING'( ")" ) );
        ELSE
            Write (StrPtr5, STRING'( " " ) );
        END IF;

        -- Issue Report only if Preemted value has not been
        --  removed from event queue
        ASSERT PreemptedTime >  NewTime
          REPORT GlitchRoutine & ": GLITCH Detected on port " & 
                 OutSignalName & StrPtr5.ALL &
                 "; Preempted Future Value := " & StrPtr3.ALL &
                 " @ " & StrPtr1.ALL &
                 "; Newly Scheduled Value := " & StrPtr4.ALL &
                 " @ " & StrPtr2.ALL &
                 ";"
          SEVERITY MsgSeverity;

        DEALLOCATE(StrPtr1);
        DEALLOCATE(StrPtr2);
        DEALLOCATE(StrPtr3);
        DEALLOCATE(StrPtr4); 
        DEALLOCATE(StrPtr5); 
        RETURN;
    END ReportGlitch;

    ---------------------------------------------------------------------------
    -- Procedure  : VitalGlitchOnEvent
    --            :
    -- Parameters : OutSignal ........ signal being driven
    --            : OutSignalName..... name of the driven signal
    --            : GlitchData........ internal data required by the procedure
    --            : NewValue.......... new value being assigned
    --            : NewDelay.......... Delay accompanying the assignment
    --            :                    (Note: for vectors, this is an array)
    --            : GlitchMode........ Glitch generation mode
    --            :                     MessagePlusX, MessageOnly, 
    --            :                     XOnly, NoGlitch )
    --            : GlitchDelay....... if <= 0 ns , then there will be no Glitch
    --            :                    if >  NewDelay, then there is no Glitch,
    --            :                    otherwise, this is the time when a FORCED
    --            :                    generation of a glitch will occur. 
    ----------------------------------------------------------------------------
    PROCEDURE VitalGlitchOnEvent (
            SIGNAL   OutSignal        : OUT   std_logic;
            CONSTANT OutSignalName    : IN    STRING;
            VARIABLE GlitchData       : INOUT GlitchDataType;
            CONSTANT NewValue         : IN    std_logic;
            CONSTANT NewDelay         : IN    TIME := 0 ns;
            CONSTANT GlitchMode       : IN    VitalGlitchModeType := MessagePlusX;
            CONSTANT GlitchDelay      : IN    TIME := 0 ns;
            CONSTANT MsgSeverity      : IN    SEVERITY_LEVEL := WARNING
    ) IS
    -- ------------------------------------------------------------------------
        VARIABLE NoGlitchDet  : BOOLEAN := FALSE;
        VARIABLE OldGlitch    : BOOLEAN := FALSE;
        VARIABLE Dly          : TIME    := NewDelay;

    BEGIN
        -- If nothing to schedule, just return
        IF NewDelay < 0 ns THEN
            IF (NewValue /= GlitchData.SchedValue) THEN
                VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName );
            END IF;

        ELSE 
            -- If nothing currently scheduled
            IF GlitchData.SchedTime <= NOW THEN
                GlitchData.CurrentValue := GlitchData.SchedValue;
                IF (GlitchDelay <= 0 ns) THEN
                    IF (NewValue = GlitchData.SchedValue) THEN RETURN; END IF;
                    NoGlitchDet := TRUE;
                END IF;
     
            -- Transaction currently scheduled - if glitch already happened
            ELSIF GlitchData.GlitchTime <= NOW THEN
                GlitchData.CurrentValue := 'X';
                OldGlitch := TRUE;
                IF (GlitchData.SchedValue = NewValue) THEN
                    dly := Minimum( GlitchData.SchedTime-NOW, NewDelay );
                END IF;
     
            -- Transaction currently scheduled (no glitch if same value)
            ELSIF (GlitchData.SchedValue = NewValue) AND
                  (GlitchData.SchedTime = GlitchData.GlitchTime) AND
                  (GlitchDelay <= 0 ns) THEN
                NoGlitchDet := TRUE;
                Dly := Minimum( GlitchData.SchedTime-NOW, NewDelay );

            END IF;
     
            GlitchData.SchedTime := NOW+Dly;
            IF OldGlitch THEN
                OutSignal <= NewValue AFTER Dly;

            ELSIF NoGlitchDet THEN
                GlitchData.GlitchTime := NOW+Dly;
                OutSignal <= NewValue AFTER Dly;

            ELSE -- new glitch
                GlitchData.GlitchTime := GlitchMinTime ( GlitchData.GlitchTime, 
                                                         NOW+GlitchDelay );

                IF (GlitchMode = MessagePlusX) OR
                   (GlitchMode = MessageOnly) THEN
                    ReportGlitch ( "VitalGlitchOnEvent", OutSignalName,
                                   GlitchData.GlitchTime, GlitchData.SchedValue,
                                   (Dly + NOW), NewValue,
                                   MsgSeverity=>MsgSeverity );
                END IF;

                IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN
                    OutSignal <= 'X' AFTER GlitchData.GlitchTime-NOW;
                    OutSignal <=  TRANSPORT NewValue AFTER Dly;
                ELSE
                    OutSignal <= NewValue AFTER Dly;
                END IF;
            END IF;

            GlitchData.SchedValue := NewValue;
        END IF;

        RETURN;
    END;
 
    ----------------------------------------------------------------------------
    PROCEDURE VitalGlitchOnEvent (
            SIGNAL   OutSignal        : OUT   std_logic_vector;
            CONSTANT OutSignalName    : IN    STRING;
            VARIABLE GlitchData       : INOUT GlitchDataArrayType;
            CONSTANT NewValue         : IN    std_logic_vector;
            CONSTANT NewDelay         : IN    VitalTimeArray;
            CONSTANT GlitchMode       : IN    VitalGlitchModeType := MessagePlusX;
            CONSTANT GlitchDelay      : IN    VitalTimeArray;
            CONSTANT MsgSeverity      : IN    SEVERITY_LEVEL := WARNING
    ) IS

        ALIAS GlDataAlias  : GlitchDataArrayType(1 TO GlitchData'LENGTH) 
                                 IS GlitchData;
        ALIAS NewValAlias  : std_logic_vector(1 TO NewValue'LENGTH) IS NewValue;
        ALIAS GlDelayAlias : VitalTimeArray(1 TO GlitchDelay'LENGTH)
              IS GlitchDelay;
        ALIAS NewDelAlias  : VitalTimeArray(1 TO NewDelay'LENGTH) IS NewDelay;
 
        VARIABLE Index       : INTEGER := OutSignal'LEFT;
        VARIABLE Direction   : INTEGER;
        VARIABLE NoGlitchDet : BOOLEAN;
        VARIABLE OldGlitch   : BOOLEAN;
        VARIABLE Dly, GlDly  : TIME;

    BEGIN
        IF (OutSignal'LEFT > OutSignal'RIGHT) THEN
            Direction := -1;
        ELSE
            Direction := 1;
        END IF;

        IF ( (OutSignal'LENGTH /=  GlitchData'LENGTH) OR
             (OutSignal'LENGTH /=    NewValue'LENGTH) OR
             (OutSignal'LENGTH /=    NewDelay'LENGTH) OR
             (OutSignal'LENGTH /= GlitchDelay'LENGTH) ) THEN
          VitalError ( "VitalGlitchOnEvent", ErrVctLng, OutSignalName );
          RETURN;
        END IF;

        -- a call to the scalar function cannot be made since the actual 
        -- name associated with a signal parameter must be locally static
      FOR n IN 1 TO OutSignal'LENGTH LOOP

        NoGlitchDet := FALSE;
        OldGlitch   := FALSE;
        Dly := NewDelAlias(n);

        -- If nothing to schedule, just skip to next loop iteration
        IF NewDelAlias(n) < 0 ns THEN
            IF (NewValAlias(n) /=  GlDataAlias(n).SchedValue) THEN
                VitalError ( "VitalGlitchOnEvent", ErrNegDel, OutSignalName );
            END IF;
        ELSE
            -- If nothing currently scheduled (i.e. last scheduled 
            -- transaction already occurred)
            IF GlDataAlias(n).SchedTime <= NOW THEN
                GlDataAlias(n).CurrentValue := GlDataAlias(n).SchedValue;
                IF (GlDelayAlias(n) <= 0 ns) THEN
                    -- Next iteration if no change in value
                    IF (NewValAlias(n) = GlDataAlias(n).SchedValue) THEN 
                        Index := Index + Direction;
                        NEXT; 
                    END IF; 
                    -- since last transaction already occurred there is no glitch
                    NoGlitchDet := TRUE;
                END IF;

            -- Transaction currently scheduled - if glitch already happened
            ELSIF GlDataAlias(n).GlitchTime <= NOW THEN
                GlDataAlias(n).CurrentValue := 'X';
                OldGlitch := TRUE;
                IF (GlDataAlias(n).SchedValue = NewValAlias(n)) THEN
                    dly := Minimum( GlDataAlias(n).SchedTime-NOW,
                                    NewDelAlias(n) );
                END IF;

            -- Transaction currently scheduled
            ELSIF (GlDataAlias(n).SchedValue = NewValAlias(n)) AND
                  (GlDataAlias(n).SchedTime = GlDataAlias(n).GlitchTime) AND
                  (GlDelayAlias(n) <= 0 ns) THEN
                  NoGlitchDet := TRUE;
                  Dly := Minimum( GlDataAlias(n).SchedTime-NOW, 
                                  NewDelAlias(n) );
            END IF;

            -- update last scheduled transaction
            GlDataAlias(n).SchedTime := NOW+Dly;

            IF OldGlitch THEN
                OutSignal(Index) <= NewValAlias(n) AFTER Dly;
            ELSIF NoGlitchDet THEN
                -- if no glitch then update last glitch time 
                -- and OutSignal(actual_index)
                GlDataAlias(n).GlitchTime := NOW+Dly;
                OutSignal(Index) <= NewValAlias(n) AFTER Dly;
            ELSE   -- new glitch
                GlDataAlias(n).GlitchTime := GlitchMinTime ( 
                                                  GlDataAlias(n).GlitchTime,
                                                  NOW+GlDelayAlias(n) );

                IF (GlitchMode = MessagePlusX) OR
                   (GlitchMode = MessageOnly) THEN
                    ReportGlitch ( "VitalGlitchOnEvent", OutSignalName,
                                   GlDataAlias(n).GlitchTime, 
                                   GlDataAlias(n).SchedValue,
                                   (Dly + NOW), NewValAlias(n), 
                                   Index, TRUE, MsgSeverity );
                END IF;

                IF (GlitchMode = MessagePlusX) OR (GlitchMode = XOnly) THEN
                    GlDly := GlDataAlias(n).GlitchTime - NOW;
                    OutSignal(Index) <= 'X' AFTER GlDly;
                    OutSignal(Index) <= TRANSPORT NewValAlias(n) AFTER Dly;
                ELSE
                    OutSignal(Index) <= NewValAlias(n) AFTER Dly;
                END IF;

            END IF; -- glitch / no-glitch
            GlDataAlias(n).SchedValue := NewValAlias(n);

        END IF; -- NewDelAlias(n) < 0 ns
        Index := Index + Direction;
      END LOOP;

        RETURN;
    END;

    ---------------------------------------------------------------------------
    -- ------------------------------------------------------------------------
    --  PROCEDURE NAME  :  TruthOutputX01Z
    --
    --  PARAMETERS      :  table_out - output of table
    --                     X01Zout   - output converted to X01Z
    --                     err       - true if illegal character is encountered
    --
    --
    --  DESCRIPTION     :  converts the output of a truth table to a valid
    --                     std_ulogic
    -- ------------------------------------------------------------------------
    PROCEDURE TruthOutputX01Z (
            CONSTANT TableOut : IN VitalTruthSymbolType;
            VARIABLE X01Zout   : OUT std_ulogic;
            VARIABLE Err       : OUT BOOLEAN
    ) IS
        VARIABLE TempOut : std_ulogic;
    BEGIN
        Err := FALSE;
        TempOut := TruthTableOutMap(TableOut);
        IF (TempOut = '-') THEN
            Err := TRUE;
            TempOut := 'X';
            VitalError ( "VitalTruthTable", ErrOutSym, To_TruthChar(TableOut));
        END IF;
        X01Zout := TempOut;
    END;

    -- ------------------------------------------------------------------------
    --  PROCEDURE NAME  :  StateOutputX01Z
    --
    --  PARAMETERS      :  table_out - output of table
    --                     prev_out  - previous output value
    --                     X01Zout   - output cojnverted to X01Z
    --                     err       - true if illegal character is encountered
    --
    --  DESCRIPTION     :  converts the output of a state table to a
    --                     valid std_ulogic
    -- ------------------------------------------------------------------------
    PROCEDURE StateOutputX01Z (
            CONSTANT TableOut : IN VitalStateSymbolType;
            CONSTANT PrevOut  : IN std_ulogic;
            VARIABLE X01Zout   : OUT std_ulogic;
            VARIABLE Err       : OUT BOOLEAN
    ) IS
        VARIABLE TempOut : std_ulogic;
    BEGIN
        Err := FALSE;
        TempOut := StateTableOutMap(TableOut);
        IF (TempOut = '-') THEN
            Err := TRUE;
            TempOut := 'X';
            VitalError ( "VitalStateTable", ErrOutSym, To_StateChar(TableOut));
        ELSIF (TempOut = 'W') THEN
            TempOut := To_X01Z(PrevOut);
        END IF;
        X01Zout := TempOut;
    END;

    -- ------------------------------------------------------------------------
    -- PROCEDURE NAME:  StateMatch
    --
    -- PARAMETERS    :  symbol       - symbol from state table
    --                  in2          - input from VitalStateTble procedure
    --                                 to state table
    --                  in2LastValue - previous value of input
    --                  state        - false if the symbol is from the input
    --                                  portion of the table,
    --                                 true if the symbol is from the state
    --                                  portion of the table
    --                  Err          - true if symbol is not a valid input symbol
    --                  ReturnValue  - true if match occurred
    --
    -- DESCRIPTION   :  This procedure sets ReturnValue to true if in2 matches
    --                  symbol (from the state table).  If symbol is an edge
    --                  value edge is set to true and in2 and in2LastValue are
    --                  checked against symbol.  Err is set to true if symbol
    --                  is an invalid value for the input portion of the state
    --                  table.
    --
    -- ------------------------------------------------------------------------
    PROCEDURE StateMatch (
            CONSTANT Symbol       : IN VitalStateSymbolType;
            CONSTANT in2          : IN std_ulogic;
            CONSTANT in2LastValue : IN std_ulogic;
            CONSTANT State        : IN BOOLEAN;
            VARIABLE Err          : OUT BOOLEAN;
            VARIABLE ReturnValue  : OUT BOOLEAN
    ) IS
    BEGIN
        IF (State) THEN
            IF (NOT ValidStateTableState(Symbol)) THEN
                VitalError ( "VitalStateTable", ErrStaSym, To_StateChar(Symbol));
                Err := TRUE;
                ReturnValue := FALSE;
            ELSE
                Err := FALSE;
                ReturnValue := StateTableMatch(in2LastValue, in2, Symbol);
            END IF;
        ELSE
            IF (NOT ValidStateTableInput(Symbol) ) THEN
                VitalError ( "VitalStateTable", ErrInpSym, To_StateChar(Symbol));
                Err := TRUE;
                ReturnValue := FALSE;
            ELSE
                ReturnValue := StateTableMatch(in2LastValue, in2, Symbol);
                Err := FALSE;
            END IF;
        END IF;
    END;

    -- -----------------------------------------------------------------------
    -- FUNCTION NAME:  StateTableLookUp
    --
    -- PARAMETERS   :  StateTable     - state table
    --                 PresentDataIn  - current inputs
    --                 PreviousDataIn - previous inputs and states
    --                 NumStates      - number of state variables
    --                 PresentOutputs - current state and current outputs
    --
    -- DESCRIPTION  :  This function is used to find the output of the
    --                 StateTable corresponding to a given set of inputs.
    --
    -- ------------------------------------------------------------------------
    FUNCTION StateTableLookUp (
            CONSTANT StateTable     : VitalStateTableType;
            CONSTANT PresentDataIn  : std_logic_vector;
            CONSTANT PreviousDataIn : std_logic_vector;
            CONSTANT NumStates      : NATURAL;
            CONSTANT PresentOutputs : std_logic_vector
          ) RETURN std_logic_vector IS

        CONSTANT InputSize    : INTEGER := PresentDataIn'LENGTH;
        CONSTANT NumInputs    : INTEGER := InputSize + NumStates - 1;
        CONSTANT TableEntries : INTEGER := StateTable'LENGTH(1);
        CONSTANT TableWidth   : INTEGER := StateTable'LENGTH(2);
        CONSTANT OutSize      : INTEGER := TableWidth - InputSize - NumStates;
        VARIABLE Inputs       : std_logic_vector(0 TO NumInputs);
        VARIABLE PrevInputs   : std_logic_vector(0 TO NumInputs)
                                := (OTHERS => 'X');
        VARIABLE ReturnValue  : std_logic_vector(0 TO (OutSize-1))
                                := (OTHERS => 'X');
        VARIABLE Temp   : std_ulogic;
        VARIABLE Match  : BOOLEAN;
        VARIABLE Err    : BOOLEAN := FALSE;

        -- This needs to be done since the TableLookup arrays must be
        -- ascending starting with 0
        VARIABLE TableAlias   : VitalStateTableType(0 TO TableEntries - 1,
                                                    0 TO TableWidth - 1)
                                := StateTable;

    BEGIN
        Inputs(0 TO InputSize-1) := PresentDataIn;
        Inputs(InputSize TO NumInputs) := PresentOutputs(0 TO NumStates - 1);
        PrevInputs(0 TO InputSize - 1) := PreviousDataIn(0 TO InputSize - 1);

      ColLoop: -- Compare each entry in the table
        FOR i IN TableAlias'RANGE(1) LOOP

        RowLoop: -- Check each element of the entry
          FOR j IN 0 TO InputSize + NumStates  LOOP

            IF (j = InputSize + NumStates) THEN        -- a match occurred
                FOR k IN 0 TO Minimum(OutSize, PresentOutputs'LENGTH)-1  LOOP
                    StateOutputX01Z (
                            TableAlias(i, TableWidth - k - 1),
                            PresentOutputs(PresentOutputs'LENGTH - k - 1),
                            Temp, Err);
                    ReturnValue(OutSize - k - 1) := Temp;
                    IF (Err) THEN
                        ReturnValue := (OTHERS => 'X');
                        RETURN ReturnValue;
                    END IF;
                END LOOP;
                RETURN ReturnValue;
            END IF;

            StateMatch ( TableAlias(i,j),
                         Inputs(j), PrevInputs(j),
                         j >= InputSize, Err, Match);
            EXIT RowLoop WHEN NOT(Match);
            EXIT ColLoop WHEN Err;
          END LOOP RowLoop;
        END LOOP ColLoop;

        ReturnValue := (OTHERS => 'X');
        RETURN ReturnValue;
    END;

    --------------------------------------------------------------------
    -- to_ux01z
    -------------------------------------------------------------------
    FUNCTION To_UX01Z  ( s : std_ulogic
          ) RETURN  UX01Z IS
    BEGIN
        RETURN cvt_to_ux01z (s);
    END;

    ---------------------------------------------------------------------------
    -- Function  : GetEdge
    -- Purpose   : Converts transitions on a given input signal into a
    --             enumeration value representing the transition or level
    --             of the signal.
    --
    --    previous "value"   current "value"     :=   "edge"
    --   ---------------------------------------------------------
    --     '1' | 'H'          '1' | 'H'                 '1'    level, no edge
    --     '0' | 'L'          '1' | 'H'                 '/'    rising edge
    --      others            '1' | 'H'                 'R'    rising from X
    --
    --     '1' | 'H'          '0' | 'L'                 '\'    falling egde
    --     '0' | 'L'          '0' | 'L'                 '0'    level, no edge
    --      others            '0' | 'L'                 'F'    falling from X
    --
    --     'X' | 'W' | '-'    'X' | 'W' | '-'           'X'    unknown (X) level
    --     'Z'                'Z'                       'X'    unknown (X) level
    --     'U'                'U'                       'U'    'U' level
    --
    --     '1' | 'H'           others                   'f'    falling to X
    --     '0' | 'L'           others                   'r'    rising to X
    --     'X' | 'W' | '-'    'U' | 'Z'                 'x'    unknown (X) edge
    --     'Z'                'X' | 'W' | '-' | 'U'     'x'    unknown (X) edge
    --     'U'                'X' | 'W' | '-' | 'Z'     'x'    unknown (X) edge
    --
    ---------------------------------------------------------------------------
    FUNCTION GetEdge (
            SIGNAL      s : IN    std_logic
          ) RETURN EdgeType IS
    BEGIN
        IF (s'EVENT)
            THEN RETURN LogicToEdge  ( s'LAST_VALUE, s );
            ELSE RETURN LogicToLevel ( s );
        END IF;
    END;

    ---------------------------------------------------------------------------
    PROCEDURE GetEdge (
            SIGNAL       s : IN    std_logic_vector;
            VARIABLE LastS : INOUT std_logic_vector;
            VARIABLE  Edge :   OUT EdgeArray ) IS

        ALIAS     sAlias : std_logic_vector ( 1 TO     s'LENGTH ) IS s;
        ALIAS LastSAlias : std_logic_vector ( 1 TO LastS'LENGTH ) IS LastS;
        ALIAS  EdgeAlias : EdgeArray ( 1 TO  Edge'LENGTH ) IS Edge;
    BEGIN
        IF s'LENGTH /= LastS'LENGTH OR
           s'LENGTH /=  Edge'LENGTH THEN
            VitalError ( "GetEdge", ErrVctLng, "s, LastS, Edge" );
        END IF;

        FOR n IN 1 TO s'LENGTH LOOP
            EdgeAlias(n)  := LogicToEdge( LastSAlias(n), sAlias(n) );
            LastSAlias(n) := sAlias(n);
        END LOOP;
    END;

    ---------------------------------------------------------------------------
    FUNCTION  ToEdge     ( Value         : IN std_logic
          ) RETURN EdgeType IS
    BEGIN
        RETURN LogicToLevel( Value );
    END;

    -- Note: This function will likely be replaced by S'DRIVING_VALUE in VHDL'92
    ----------------------------------------------------------------------------
    FUNCTION CurValue (
            CONSTANT GlitchData : IN  GlitchDataType
          ) RETURN std_logic IS
    BEGIN
        IF NOW >= GlitchData.SchedTime THEN
            RETURN GlitchData.SchedValue;
        ELSIF NOW >= GlitchData.GlitchTime THEN
            RETURN 'X';
        ELSE
            RETURN GlitchData.CurrentValue;
        END IF;
    END;
    ---------------------------------------------------------------------------
    FUNCTION CurValue (
            CONSTANT GlitchData : IN  GlitchDataArrayType
          ) RETURN std_logic_vector IS
        VARIABLE Result : std_logic_vector(GlitchData'RANGE);
    BEGIN
        FOR n IN GlitchData'RANGE LOOP
            IF NOW >= GlitchData(n).SchedTime THEN
                Result(n) := GlitchData(n).SchedValue;
            ELSIF NOW >= GlitchData(n).GlitchTime THEN
                Result(n) := 'X';
            ELSE
                Result(n) := GlitchData(n).CurrentValue;
            END IF;
        END LOOP;
        RETURN Result;
    END;

    ---------------------------------------------------------------------------
    -- function calculation utilities
    ---------------------------------------------------------------------------

    ---------------------------------------------------------------------------
    -- Function   : VitalSame
    -- Returns    : VitalSame compares the state (UX01) of two logic value. A
    --              value of 'X' is returned if the values are different.  The
    --              common value is returned if the values are equal.
    -- Purpose    : When the result of a logic model may be either of two
    --              separate input values (eg. when the select on a MUX is 'X'),
    --              VitalSame may be used to determine if the result needs to
    --              be 'X'.
    -- Arguments  : See the declarations below...
    ---------------------------------------------------------------------------
    FUNCTION VitalSame (
            CONSTANT a, b : IN std_ulogic
          ) RETURN std_ulogic IS
    BEGIN
        IF To_UX01(a) = To_UX01(b)
            THEN RETURN To_UX01(a);
            ELSE RETURN 'X';
        END IF;
    END;

    ---------------------------------------------------------------------------
    -- delay selection utilities
    ---------------------------------------------------------------------------

    ---------------------------------------------------------------------------
    -- Procedure  : BufPath, InvPath
    --
    -- Purpose    : BufPath and InvPath compute output change times, based on
    --              a change on an input port. The computed output change times
    --              returned in the composite parameter 'schd'.
    --
    --              BufPath and InpPath are used together with the delay path
    --              selection functions (GetSchedDelay, VitalAND, VitalOR... )
    --              The 'schd' value from each of the input ports of a model are
    --              combined by the delay selection functions (VitalAND,
    --              VitalOR, ...). The GetSchedDelay procedure converts the
    --              combined output changes times to the single delay (delta
    --              time) value for scheduling the output change (passed to
    --              VitalGlitchOnEvent).
    --
    --              The values in 'schd' are: (absolute times)
    --                inp0  :  time of output change due to input change to 0
    --                inp1  :  time of output change due to input change to 1
    --                inpX  :  time of output change due to input change to X
    --                glch0 :  time of output glitch due to input change to 0
    --                glch1 :  time of output glitch due to input change to 1
    --
    --              The output times are computed from the model INPUT value
    --              and not the final value.  For this reason, 'BufPath' should
    --              be used to compute the output times for a non-inverting
    --              delay paths and 'InvPath' should be used to compute the
    --              ouput times for inverting delay paths. Delay paths which
    --              include both non-inverting and paths require usage of both
    --              'BufPath' and 'InvPath'. (IE this is needed for the
    --              select->output path of a MUX -- See the VitalMUX model).
    --
    --
    -- Parameters : schd....... Computed output result times. (INOUT parameter
    --                          modified only on input edges)
    --              Iedg....... Input port edge/level value.
    --               tpd....... Propagation delays from this input
    --
    ---------------------------------------------------------------------------

    PROCEDURE BufPath (
            VARIABLE Schd : INOUT SchedType;
            CONSTANT Iedg : IN    EdgeType;
            CONSTANT  tpd : IN    VitalDelayType01
    ) IS
    BEGIN
      CASE Iedg IS
        WHEN '0'|'1' => NULL;                   -- no edge: no timing update
        WHEN '/'|'R' => Schd.inp0 := TIME'HIGH;
                        Schd.inp1 := NOW + tpd(tr01);  Schd.Glch1 := Schd.inp1;
                        Schd.InpX := Schd.inp1;
        WHEN '\'|'F' => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := NOW + tpd(tr10);  Schd.Glch0 := Schd.inp0;
                        Schd.InpX := Schd.inp0;
        WHEN 'r'     => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := TIME'HIGH;
                        Schd.InpX := NOW + tpd(tr01);
        WHEN 'f'     => Schd.inp0 := TIME'HIGH;
                        Schd.inp1 := TIME'HIGH;
                        Schd.InpX := NOW + tpd(tr10);
        WHEN 'x'     => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := TIME'HIGH;
                        -- update for X->X change
                        Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
        WHEN OTHERS  => NULL;                   -- no timing change
      END CASE;
    END;

    PROCEDURE BufPath (
            VARIABLE Schd : INOUT SchedArray;
            CONSTANT Iedg : IN    EdgeArray;
            CONSTANT  tpd : IN    VitalDelayArrayType01
    ) IS
    BEGIN
      FOR n IN Schd'RANGE LOOP
        CASE Iedg(n) IS
          WHEN '0'|'1' => NULL;                   -- no edge: no timing update
          WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH;
                          Schd(n).inp1 := NOW + tpd(n)(tr01);
                          Schd(n).Glch1 := Schd(n).inp1;
                          Schd(n).InpX := Schd(n).inp1;
          WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := NOW + tpd(n)(tr10);
                          Schd(n).Glch0 := Schd(n).inp0;
                          Schd(n).InpX := Schd(n).inp0;
          WHEN 'r'     => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := TIME'HIGH;
                          Schd(n).InpX := NOW + tpd(n)(tr01);
          WHEN 'f'     => Schd(n).inp0 := TIME'HIGH;
                          Schd(n).inp1 := TIME'HIGH;
                          Schd(n).InpX := NOW + tpd(n)(tr10);
          WHEN 'x'     => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := TIME'HIGH;
                          -- update for X->X change
                          Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10),
                                                          tpd(n)(tr01) );
          WHEN OTHERS  => NULL;                   -- no timing change
        END CASE;
      END LOOP;
    END;

    PROCEDURE InvPath (
            VARIABLE Schd : INOUT SchedType;
            CONSTANT Iedg : IN    EdgeType;
            CONSTANT  tpd : IN    VitalDelayType01
    ) IS
    BEGIN
      CASE Iedg IS
        WHEN '0'|'1' => NULL;                   -- no edge: no timing update
        WHEN '/'|'R' => Schd.inp0 := TIME'HIGH;
                        Schd.inp1 := NOW + tpd(tr10);  Schd.Glch1 := Schd.inp1;
                        Schd.InpX := Schd.inp1;
        WHEN '\'|'F' => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := NOW + tpd(tr01);  Schd.Glch0 := Schd.inp0;
                        Schd.InpX := Schd.inp0;
        WHEN 'r'     => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := TIME'HIGH;
                        Schd.InpX := NOW + tpd(tr10);
        WHEN 'f'     => Schd.inp0 := TIME'HIGH;
                        Schd.inp1 := TIME'HIGH;
                        Schd.InpX := NOW + tpd(tr01);
        WHEN 'x'     => Schd.inp1 := TIME'HIGH;
                        Schd.inp0 := TIME'HIGH;
                        -- update for X->X change
                        Schd.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
        WHEN OTHERS  => NULL;                   -- no timing change
      END CASE;
    END;

    PROCEDURE InvPath (
            VARIABLE Schd : INOUT SchedArray;
            CONSTANT Iedg : IN    EdgeArray;
            CONSTANT  tpd : IN    VitalDelayArrayType01
    ) IS
    BEGIN
      FOR n IN Schd'RANGE LOOP
        CASE Iedg(n) IS
          WHEN '0'|'1' => NULL;                   -- no edge: no timing update
          WHEN '/'|'R' => Schd(n).inp0 := TIME'HIGH;
                          Schd(n).inp1 := NOW + tpd(n)(tr10);
                          Schd(n).Glch1 := Schd(n).inp1;
                          Schd(n).InpX := Schd(n).inp1;
          WHEN '\'|'F' => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := NOW + tpd(n)(tr01);
                          Schd(n).Glch0 := Schd(n).inp0;
                          Schd(n).InpX := Schd(n).inp0;
          WHEN 'r'     => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := TIME'HIGH;
                          Schd(n).InpX := NOW + tpd(n)(tr10);
          WHEN 'f'     => Schd(n).inp0 := TIME'HIGH;
                          Schd(n).inp1 := TIME'HIGH;
                          Schd(n).InpX := NOW + tpd(n)(tr01);
          WHEN 'x'     => Schd(n).inp1 := TIME'HIGH;
                          Schd(n).inp0 := TIME'HIGH;
                          -- update for X->X change
                          Schd(n).InpX := NOW + Minimum ( tpd(n)(tr10),
                                                          tpd(n)(tr01) );
          WHEN OTHERS  => NULL;                   -- no timing change
        END CASE;
      END LOOP;
    END;

    ---------------------------------------------------------------------------
    -- Procedure  : BufEnab, InvEnab
    --
    -- Purpose    : BufEnab and InvEnab compute output change times, from a
    --              change on an input enable port for a 3-state driver. The
    --              computed output change times are returned in the composite
    --              parameters 'schd1', 'schd0'.
    --
    --              BufEnab and InpEnab are used together with the delay path
    --              selection functions (GetSchedDelay, VitalAND, VitalOR... )
    --              The 'schd' value from each of the non-enable input ports of
    --              a model (See BufPath, InvPath) are combined using the delay
    --              selection functions (VitalAND,  VitalOR, ...). The
    --              GetSchedDelay procedure combines the output times on the
    --              enable path with the output times from the data path(s) and
    --              computes the single delay (delta time) value for scheduling
    --              the output change (passed to VitalGlitchOnEvent)
    --
    --              The values in 'schd*' are: (absolute times)
    --                inp0  :  time of output change due to input change to 0
    --                inp1  :  time of output change due to input change to 1
    --                inpX  :  time of output change due to input change to X
    --                glch0 :  time of output glitch due to input change to 0
    --                glch1 :  time of output glitch due to input change to 1
    --
    --              'schd1' contains output times for 1->Z, Z->1 transitions.
    --              'schd0' contains output times for 0->Z, Z->0 transitions.
    --
    --              'BufEnab' is used for computing the output times for an
    --              high asserted enable (output 'Z' for enable='0').
    --              'InvEnab' is used for computing the output times for an
    --              low asserted enable (output 'Z' for enable='1').
    --
    --              Note: separate 'schd1', 'schd0' parameters are generated
    --                    so that the combination of the delay paths from
    --                    multiple enable signals may be combined using the
    --                    same functions/operators used in combining separate
    --                    data paths. (See exampe 2 below)
    --
    --
    -- Parameters : schd1...... Computed output result times for 1->Z, Z->1
    --                          transitions. This parameter is modified only on
    --                          input edge values (events).
    --              schd0...... Computed output result times for 0->Z, 0->1
    --                          transitions. This parameter is modified only on
    --                          input edge values (events).
    --              Iedg....... Input port edge/level value.
    --               tpd....... Propagation delays for the enable -> output path.
    --
    ---------------------------------------------------------------------------
    PROCEDURE BufEnab (
            VARIABLE Schd1 : INOUT SchedType;
            VARIABLE Schd0 : INOUT SchedType;
            CONSTANT  Iedg : IN    EdgeType;
            CONSTANT   tpd : IN    VitalDelayType01Z
    ) IS
    BEGIN
      CASE Iedg IS
        WHEN '0'|'1' => NULL;                   -- no edge: no timing update
        WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := NOW + tpd(trz1);
                        Schd1.Glch1 := Schd1.inp1;
                        Schd1.InpX := Schd1.inp1;
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := NOW + tpd(trz0);
                        Schd0.Glch1 := Schd0.inp1;
                        Schd0.InpX := Schd0.inp1;
        WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH;
                        Schd1.inp0 := NOW + tpd(tr1z);
                        Schd1.Glch0 := Schd1.inp0;
                        Schd1.InpX := Schd1.inp0;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.inp0 := NOW + tpd(tr0z);
                        Schd0.Glch0 := Schd0.inp0;
                        Schd0.InpX := Schd0.inp0;
        WHEN 'r'     => Schd1.inp1 := TIME'HIGH;
                        Schd1.inp0 := TIME'HIGH;
                        Schd1.InpX := NOW + tpd(trz1);
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.InpX := NOW + tpd(trz0);
        WHEN 'f'     => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := TIME'HIGH;
                        Schd1.InpX := NOW + tpd(tr1z);
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.InpX := NOW + tpd(tr0z);
        WHEN 'x'     => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := TIME'HIGH;
                        Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
        WHEN OTHERS  => NULL;                   -- no timing change
      END CASE;
    END;

    PROCEDURE InvEnab (
            VARIABLE Schd1 : INOUT SchedType;
            VARIABLE Schd0 : INOUT SchedType;
            CONSTANT  Iedg : IN    EdgeType;
            CONSTANT   tpd : IN    VitalDelayType01Z
    ) IS
    BEGIN
      CASE Iedg IS
        WHEN '0'|'1' => NULL;                   -- no edge: no timing update
        WHEN '/'|'R' => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := NOW + tpd(tr1z);
                        Schd1.Glch1 := Schd1.inp1;
                        Schd1.InpX := Schd1.inp1;
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := NOW + tpd(tr0z);
                        Schd0.Glch1 := Schd0.inp1;
                        Schd0.InpX := Schd0.inp1;
        WHEN '\'|'F' => Schd1.inp1 := TIME'HIGH;
                        Schd1.inp0 := NOW + tpd(trz1);
                        Schd1.Glch0 := Schd1.inp0;
                        Schd1.InpX := Schd1.inp0;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.inp0 := NOW + tpd(trz0);
                        Schd0.Glch0 := Schd0.inp0;
                        Schd0.InpX := Schd0.inp0;
        WHEN 'r'     => Schd1.inp1 := TIME'HIGH;
                        Schd1.inp0 := TIME'HIGH;
                        Schd1.InpX := NOW + tpd(tr1z);
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.InpX := NOW + tpd(tr0z);
        WHEN 'f'     => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := TIME'HIGH;
                        Schd1.InpX := NOW + tpd(trz1);
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.InpX := NOW + tpd(trz0);
        WHEN 'x'     => Schd1.inp0 := TIME'HIGH;
                        Schd1.inp1 := TIME'HIGH;
                        Schd1.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
                        Schd0.inp0 := TIME'HIGH;
                        Schd0.inp1 := TIME'HIGH;
                        Schd0.InpX := NOW + Minimum(tpd(tr10),tpd(tr01));
        WHEN OTHERS  => NULL;                   -- no timing change
      END CASE;
    END;

    ---------------------------------------------------------------------------
    -- Procedure  : GetSchedDelay
    --
    -- Purpose    : GetSchedDelay computes the final delay (incremental) for
    --              for scheduling an output signal.  The delay is computed
    --              from the absolute output times in the 'NewSched' parameter.
    --              (See BufPath, InvPath).
    --
    --              Computation of the output delay for non-3_state outputs
    --              consists of selection the appropriate output time based
    --              on the new output value 'NewValue' and subtracting 'NOW'
    --              to convert to an incremental delay value.
    --
    --              The Computation of the output delay for 3_state output
    --              also includes combination of the enable path delay with
    --              the date path delay.
    --
    -- Parameters : NewDelay... Returned output delay value.
    --              GlchDelay.. Returned output delay for the start of a glitch.
    --              NewValue... New output value.
    --              CurValue... Current value of the output.
    --              NewSched... Composite containing the combined absolute
    --                          output times from the data inputs.
    --              EnSched1... Composite containing the combined absolute
    --                          output times from the enable input(s).
    --                          (for a 3_state output transitions 1->Z, Z->1)
    --              EnSched0... Composite containing the combined absolute
    --                          output times from the enable input(s).
    --                          (for a 3_state output transitions 0->Z, Z->0)
    --
    ---------------------------------------------------------------------------
    PROCEDURE GetSchedDelay (
            VARIABLE   NewDelay : OUT TIME;
            VARIABLE  GlchDelay : OUT TIME;
            CONSTANT   NewValue : IN  std_ulogic;
            CONSTANT   CurValue : IN  std_ulogic;
            CONSTANT   NewSched : IN  SchedType
    ) IS
        VARIABLE Tim, Glch : TIME;
    BEGIN

        CASE To_UX01(NewValue) IS
          WHEN '0'    => Tim  := NewSched.inp0;
                         Glch := NewSched.Glch1;
          WHEN '1'    => Tim  := NewSched.inp1;
                         Glch := NewSched.Glch0;
          WHEN OTHERS => Tim  := NewSched.InpX;
                         Glch := -1 ns;
        END CASE;
        IF (CurValue /= NewValue)
          THEN Glch := -1 ns;
        END IF;

        NewDelay  := Tim  - NOW;
        IF Glch < 0 ns
            THEN GlchDelay := Glch;
            ELSE GlchDelay := Glch - NOW;
        END IF; -- glch < 0 ns
    END;

    PROCEDURE GetSchedDelay (
            VARIABLE   NewDelay : OUT VitalTimeArray;
            VARIABLE  GlchDelay : OUT VitalTimeArray;
            CONSTANT   NewValue : IN  std_logic_vector;
            CONSTANT   CurValue : IN  std_logic_vector;
            CONSTANT   NewSched : IN  SchedArray
    ) IS
        VARIABLE Tim, Glch : TIME;
        ALIAS  NewDelayAlias : VitalTimeArray( NewDelay'LENGTH DOWNTO 1)
               IS NewDelay;
        ALIAS GlchDelayAlias : VitalTimeArray(GlchDelay'LENGTH DOWNTO 1)
               IS GlchDelay;
        ALIAS  NewSchedAlias : SchedArray( NewSched'LENGTH DOWNTO 1)
               IS NewSched;
        ALIAS  NewValueAlias : std_logic_vector (  NewValue'LENGTH DOWNTO 1 )
                                IS  NewValue;
        ALIAS  CurValueAlias : std_logic_vector (  CurValue'LENGTH DOWNTO 1 )
                                IS  CurValue;
    BEGIN
      FOR n IN NewDelay'LENGTH DOWNTO 1 LOOP
        CASE To_UX01(NewValueAlias(n)) IS
          WHEN '0'    => Tim  := NewSchedAlias(n).inp0;
                         Glch := NewSchedAlias(n).Glch1;
          WHEN '1'    => Tim  := NewSchedAlias(n).inp1;
                         Glch := NewSchedAlias(n).Glch0;
          WHEN OTHERS => Tim  := NewSchedAlias(n).InpX;
                         Glch := -1 ns;
        END CASE;
        IF (CurValueAlias(n) /= NewValueAlias(n))
          THEN Glch := -1 ns;
        END IF;

        NewDelayAlias(n) := Tim  - NOW;
        IF Glch < 0 ns
            THEN GlchDelayAlias(n) := Glch;
            ELSE GlchDelayAlias(n) := Glch - NOW;
        END IF; -- glch < 0 ns
      END LOOP;
      RETURN;
    END;

    PROCEDURE GetSchedDelay (
            VARIABLE   NewDelay : OUT TIME;
            VARIABLE  GlchDelay : OUT TIME;
            CONSTANT   NewValue : IN  std_ulogic;
            CONSTANT   CurValue : IN  std_ulogic;
            CONSTANT   NewSched : IN  SchedType;
            CONSTANT   EnSched1 : IN  SchedType;
            CONSTANT   EnSched0 : IN  SchedType
    ) IS
        SUBTYPE v2 IS std_logic_vector(0 TO 1);
        VARIABLE Tim, Glch : TIME;
    BEGIN

        CASE v2'(To_X01Z(CurValue) & To_X01Z(NewValue)) IS
          WHEN "00"    => Tim  := Maximum (NewSched.inp0, EnSched0.inp1);
                          Glch := GlitchMinTime(NewSched.Glch1,EnSched0.Glch0);
          WHEN "01"    => Tim  := Maximum (NewSched.inp1, EnSched1.inp1);
                          Glch := EnSched1.Glch0;
          WHEN "0Z"    => Tim  := EnSched0.inp0;
                          Glch := NewSched.Glch1;
          WHEN "0X"    => Tim  := Maximum (NewSched.InpX, EnSched1.InpX);
                          Glch := 0 ns;
          WHEN "10"    => Tim  := Maximum (NewSched.inp0, EnSched0.inp1);
                          Glch := EnSched0.Glch0;
          WHEN "11"    => Tim  := Maximum (NewSched.inp1, EnSched1.inp1);
                          Glch := GlitchMinTime(NewSched.Glch0,EnSched1.Glch0);
          WHEN "1Z"    => Tim  := EnSched1.inp0;
                          Glch := NewSched.Glch0;
          WHEN "1X"    => Tim  := Maximum (NewSched.InpX, EnSched0.InpX);
                          Glch := 0 ns;
          WHEN "Z0"    => Tim  := Maximum (NewSched.inp0, EnSched0.inp1);
                          IF NewSched.Glch0 > NOW
                            THEN Glch := Maximum(NewSched.Glch1,EnSched1.inp1);
                            ELSE Glch := 0 ns;
                          END IF;
          WHEN "Z1"    => Tim  := Maximum (NewSched.inp1, EnSched1.inp1);
                          IF NewSched.Glch1 > NOW
                            THEN Glch := Maximum(NewSched.Glch0,EnSched0.inp1);
                            ELSE Glch := 0 ns;
                          END IF;
          WHEN "ZX"    => Tim  := Maximum (NewSched.InpX, EnSched1.InpX);
                          Glch := 0 ns;
          WHEN "ZZ"    => Tim  := Maximum (EnSched1.InpX, EnSched0.InpX);
                          Glch := 0 ns;
          WHEN "X0"    => Tim  := Maximum (NewSched.inp0, EnSched0.inp1);
                          Glch := 0 ns;
          WHEN "X1"    => Tim  := Maximum (NewSched.inp1, EnSched1.inp1);
                          Glch := 0 ns;
          WHEN "XZ"    => Tim  := Maximum (EnSched1.InpX, EnSched0.InpX);
                          Glch := 0 ns;
          WHEN OTHERS  => Tim  := Maximum (NewSched.InpX, EnSched1.InpX);
                          Glch := 0 ns;

        END CASE;
        NewDelay  := Tim  - NOW;
        IF Glch < 0 ns
            THEN GlchDelay := Glch;
            ELSE GlchDelay := Glch - NOW;
        END IF; -- glch < 0 ns
    END;

    ---------------------------------------------------------------------------
    -- Operators and Functions for combination (selection) of path delays
    -- > These functions support selection of the "appripriate" path delay
    --   dependent on the logic function.
    -- > These functions only "select" from the possable output times. No
    --   calculation (addition) of delays is performed.
    -- > See description of 'BufPath', 'InvPath' and 'GetSchedDelay'
    -- > See primitive PROCEDURE models for examples.
    ---------------------------------------------------------------------------

    FUNCTION "not"  (
            CONSTANT a : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        z.inp1  := a.inp0 ;
        z.inp0  := a.inp1 ;
        z.InpX  := a.InpX ;
        z.Glch1 := a.Glch0;
        z.Glch0 := a.Glch1;
        RETURN (z);
    END;

    FUNCTION "and"  (
            CONSTANT a, b : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        z.inp1  := Maximum   ( a.inp1 , b.inp1  );
        z.inp0  := Minimum   ( a.inp0 , b.inp0  );
        z.InpX  := GlitchMinTime ( a.InpX , b.InpX  );
        z.Glch1 := Maximum   ( a.Glch1, b.Glch1 );
        z.Glch0 := GlitchMinTime ( a.Glch0, b.Glch0 );
        RETURN (z);
    END;

    FUNCTION "or"   (
            CONSTANT a, b : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        z.inp0  := Maximum   ( a.inp0 , b.inp0  );
        z.inp1  := Minimum   ( a.inp1 , b.inp1  );
        z.InpX  := GlitchMinTime ( a.InpX , b.InpX  );
        z.Glch0 := Maximum   ( a.Glch0, b.Glch0 );
        z.Glch1 := GlitchMinTime ( a.Glch1, b.Glch1 );
        RETURN (z);
    END;

    FUNCTION "nand" (
            CONSTANT a, b : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        z.inp0  := Maximum   ( a.inp1 , b.inp1  );
        z.inp1  := Minimum   ( a.inp0 , b.inp0  );
        z.InpX  := GlitchMinTime ( a.InpX , b.InpX  );
        z.Glch0 := Maximum   ( a.Glch1, b.Glch1 );
        z.Glch1 := GlitchMinTime ( a.Glch0, b.Glch0 );
        RETURN (z);
    END;

    FUNCTION "nor"  (
            CONSTANT a, b : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        z.inp1  := Maximum   ( a.inp0 , b.inp0  );
        z.inp0  := Minimum   ( a.inp1 , b.inp1  );
        z.InpX  := GlitchMinTime ( a.InpX , b.InpX  );
        z.Glch1 := Maximum   ( a.Glch0, b.Glch0 );
        z.Glch0 := GlitchMinTime ( a.Glch1, b.Glch1 );
        RETURN (z);
    END;

    -- ------------------------------------------------------------------------
    -- Delay Calculation for 2-bit Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalXOR2   (
            CONSTANT ab,ai, bb,bi : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        -- z = (a AND b) NOR (a NOR b)
        z.inp1  :=   Maximum (  Minimum (ai.inp0 , bi.inp0 ),
                                Minimum (ab.inp1 , bb.inp1 ) );
        z.inp0  :=   Minimum (  Maximum (ai.inp1 , bi.inp1 ),
                                Maximum (ab.inp0 , bb.inp0 ) );
        z.InpX  :=   Maximum (  Maximum (ai.InpX , bi.InpX ),
                                Maximum (ab.InpX , bb.InpX ) );
        z.Glch1 :=   Maximum (GlitchMinTime (ai.Glch0, bi.Glch0),
                              GlitchMinTime (ab.Glch1, bb.Glch1) );
        z.Glch0 := GlitchMinTime (  Maximum (ai.Glch1, bi.Glch1),
                                Maximum (ab.Glch0, bb.Glch0) );
        RETURN (z);
    END;

    FUNCTION VitalXNOR2  (
            CONSTANT ab,ai, bb,bi : IN SchedType
          ) RETURN SchedType IS
        VARIABLE z : SchedType;
    BEGIN
        -- z = (a AND b) OR (a NOR b)
        z.inp0  :=   Maximum (  Minimum (ab.inp0 , bb.inp0 ),
                                Minimum (ai.inp1 , bi.inp1 ) );
        z.inp1  :=   Minimum (  Maximum (ab.inp1 , bb.inp1 ),
                                Maximum (ai.inp0 , bi.inp0 ) );
        z.InpX  :=   Maximum (  Maximum (ab.InpX , bb.InpX ),
                                Maximum (ai.InpX , bi.InpX ) );
        z.Glch0 :=   Maximum (GlitchMinTime (ab.Glch0, bb.Glch0),
                              GlitchMinTime (ai.Glch1, bi.Glch1) );
        z.Glch1 := GlitchMinTime (  Maximum (ab.Glch1, bb.Glch1),
                                Maximum (ai.Glch0, bi.Glch0) );
        RETURN (z);
    END;

    -- ------------------------------------------------------------------------
    -- Delay Calculation for 3-bit Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalXOR3   (
            CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType )
      RETURN SchedType IS
    BEGIN
        RETURN VitalXOR2 ( VitalXOR2 (ab,ai, bb,bi),
                           VitalXOR2 (ai,ab, bi,bb),
                           cb, ci );
    END;

    FUNCTION VitalXNOR3  (
            CONSTANT ab,ai, bb,bi, cb,ci : IN SchedType )
      RETURN SchedType IS
    BEGIN
        RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ),
                            VitalXOR2 ( ai,ab, bi,bb ),
                            cb, ci );
    END;

    -- ------------------------------------------------------------------------
    -- Delay Calculation for 4-bit Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalXOR4   (
            CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType )
      RETURN SchedType IS
    BEGIN
        RETURN VitalXOR2 ( VitalXOR2 ( ab,ai, bb,bi ),
                           VitalXOR2 ( ai,ab, bi,bb ),
                           VitalXOR2 ( cb,ci, db,di ),
                           VitalXOR2 ( ci,cb, di,db ) );
    END;

    FUNCTION VitalXNOR4  (
            CONSTANT ab,ai, bb,bi, cb,ci, db,di : IN SchedType )
      RETURN SchedType IS
    BEGIN
        RETURN VitalXNOR2 ( VitalXOR2 ( ab,ai, bb,bi ),
                            VitalXOR2 ( ai,ab, bi,bb ),
                            VitalXOR2 ( cb,ci, db,di ),
                            VitalXOR2 ( ci,cb, di,db ) );
    END;

    -- ------------------------------------------------------------------------
    -- Delay Calculation for N-bit Logical gates.
    -- ------------------------------------------------------------------------
    -- Note: index range on datab,datai assumed to be 1 TO length.
    --       This is enforced by internal only usage of this Function
    FUNCTION VitalXOR   (
            CONSTANT DataB, DataI : IN SchedArray
          ) RETURN SchedType IS
            CONSTANT Leng : INTEGER := DataB'LENGTH;
    BEGIN
        IF Leng = 2 THEN
            RETURN VitalXOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) );
        ELSE
            RETURN VitalXOR2 ( VitalXOR ( DataB(1 TO Leng-1),
                                          DataI(1 TO Leng-1) ),
                               VitalXOR ( DataI(1 TO Leng-1),
                                          DataB(1 TO Leng-1) ),
                               DataB(Leng),DataI(Leng) );
        END IF;
    END;

    -- Note: index range on datab,datai assumed to be 1 TO length.
    --       This is enforced by internal only usage of this Function
    FUNCTION VitalXNOR  (
            CONSTANT DataB, DataI : IN SchedArray
          ) RETURN SchedType IS
            CONSTANT Leng : INTEGER := DataB'LENGTH;
    BEGIN
        IF Leng = 2 THEN
            RETURN VitalXNOR2 ( DataB(1),DataI(1), DataB(2),DataI(2) );
        ELSE
            RETURN VitalXNOR2 ( VitalXOR ( DataB(1 TO Leng-1),
                                           DataI(1 TO Leng-1) ),
                                VitalXOR ( DataI(1 TO Leng-1),
                                           DataB(1 TO Leng-1) ),
                                DataB(Leng),DataI(Leng) );
        END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Multiplexor
    --   MUX   .......... result := data(dselect)
    --   MUX2  .......... 2-input mux; result := data0 when (dselect = '0'),
    --                                           data1 when (dselect = '1'),
    --                        'X' when (dselect = 'X') and (data0 /= data1)
    --   MUX4  .......... 4-input mux; result := data(dselect)
    --   MUX8  .......... 8-input mux; result := data(dselect)
    -- ------------------------------------------------------------------------
    FUNCTION VitalMUX2  (
            CONSTANT d1, d0 : IN SchedType;
            CONSTANT sb, SI : IN SchedType
          ) RETURN SchedType IS
    BEGIN
        RETURN (d1 AND sb) OR (d0 AND (NOT SI) );
    END;
--
    FUNCTION VitalMUX4  (
            CONSTANT Data : IN SchedArray4;
            CONSTANT sb   : IN SchedArray2;
            CONSTANT SI   : IN SchedArray2
          ) RETURN SchedType IS
    BEGIN
        RETURN    (      sb(1)  AND VitalMUX2(Data(3),Data(2), sb(0), SI(0)) )
               OR ( (NOT SI(1)) AND VitalMUX2(Data(1),Data(0), sb(0), SI(0)) );
    END;

    FUNCTION VitalMUX8  (
            CONSTANT Data : IN SchedArray8;
            CONSTANT sb   : IN SchedArray3;
            CONSTANT SI   : IN SchedArray3
          ) RETURN SchedType IS
    BEGIN
        RETURN    ( (    sb(2)) AND VitalMUX4 (Data(7 DOWNTO 4),
                                           sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) )
               OR ( (NOT SI(2)) AND VitalMUX4 (Data(3 DOWNTO 0),
                                           sb(1 DOWNTO 0), SI(1 DOWNTO 0) ) );
    END;
--
    FUNCTION VInterMux   (
            CONSTANT Data : IN SchedArray;
            CONSTANT sb   : IN SchedArray;
            CONSTANT SI   : IN SchedArray
          ) RETURN SchedType IS
        CONSTANT sMsb : INTEGER := sb'LENGTH;
        CONSTANT dMsbHigh : INTEGER := Data'LENGTH;
        CONSTANT dMsbLow  : INTEGER := Data'LENGTH/2;
    BEGIN
        IF sb'LENGTH = 1 THEN
          RETURN VitalMUX2( Data(2), Data(1), sb(1), SI(1) );
        ELSIF sb'LENGTH = 2 THEN
          RETURN VitalMUX4( Data, sb, SI );
        ELSIF sb'LENGTH = 3 THEN
          RETURN VitalMUX8( Data, sb, SI );
        ELSIF sb'LENGTH > 3 THEN
          RETURN ((    sb(sMsb)) AND VInterMux( Data(dMsbLow  DOWNTO  1),
                                                  sb(sMsb-1 DOWNTO 1),
                                                  SI(sMsb-1 DOWNTO 1) ))
              OR ((NOT SI(sMsb)) AND VInterMux( Data(dMsbHigh DOWNTO dMsbLow+1),
                                                  sb(sMsb-1 DOWNTO 1),
                                                  SI(sMsb-1 DOWNTO 1) ));
        ELSE
          RETURN (0 ns, 0 ns, 0 ns, 0 ns, 0 ns); -- dselect'LENGTH < 1
        END IF;
    END;
--
    FUNCTION VitalMUX   (
            CONSTANT Data : IN SchedArray;
            CONSTANT sb   : IN SchedArray;
            CONSTANT SI   : IN SchedArray
          ) RETURN SchedType IS
        CONSTANT msb : INTEGER := 2**sb'LENGTH;
        VARIABLE    lDat : SchedArray(msb DOWNTO 1);
        ALIAS DataAlias : SchedArray ( Data'LENGTH DOWNTO 1 ) IS Data;
        ALIAS   sbAlias : SchedArray (   sb'LENGTH DOWNTO 1 ) IS sb;
        ALIAS   siAlias : SchedArray (   SI'LENGTH DOWNTO 1 ) IS SI;
    BEGIN
        IF Data'LENGTH <= msb THEN
            FOR i IN Data'LENGTH DOWNTO 1 LOOP
                lDat(i) := DataAlias(i);
            END LOOP;
            FOR i IN msb DOWNTO Data'LENGTH+1 LOOP
                lDat(i) := DefSchedAnd;
            END LOOP;
        ELSE
            FOR i IN msb DOWNTO 1 LOOP
                lDat(i) := DataAlias(i);
            END LOOP;
        END IF;
        RETURN VInterMux( lDat, sbAlias, siAlias );
    END;

    -- ------------------------------------------------------------------------
    -- Decoder
    --          General Algorithm :
    --              (a) Result(...) := '0' when (enable = '0')
    --              (b) Result(data) := '1'; all other subelements = '0'
    --              ... Result array is decending (n-1 downto 0)
    --
    --          DECODERn  .......... n:2**n decoder
    -- ------------------------------------------------------------------------
    FUNCTION VitalDECODER2  (
            CONSTANT DataB  : IN SchedType;
            CONSTANT DataI  : IN SchedType;
            CONSTANT Enable : IN SchedType
          ) RETURN SchedArray IS
        VARIABLE Result : SchedArray2;
    BEGIN
        Result(1) := Enable AND (    DataB);
        Result(0) := Enable AND (NOT DataI);
        RETURN Result;
    END;

    FUNCTION VitalDECODER4  (
            CONSTANT DataB  : IN SchedArray2;
            CONSTANT DataI  : IN SchedArray2;
            CONSTANT Enable : IN SchedType
          ) RETURN SchedArray IS
        VARIABLE Result : SchedArray4;
    BEGIN
        Result(3) := Enable AND (    DataB(1)) AND (    DataB(0));
        Result(2) := Enable AND (    DataB(1)) AND (NOT DataI(0));
        Result(1) := Enable AND (NOT DataI(1)) AND (    DataB(0));
        Result(0) := Enable AND (NOT DataI(1)) AND (NOT DataI(0));
        RETURN Result;
    END;

    FUNCTION VitalDECODER8  (
            CONSTANT DataB  : IN SchedArray3;
            CONSTANT DataI  : IN SchedArray3;
            CONSTANT Enable : IN SchedType
          ) RETURN SchedArray IS
        VARIABLE Result : SchedArray8;
    BEGIN
        Result(7):= Enable AND (    DataB(2))AND(    DataB(1))AND(    DataB(0));
        Result(6):= Enable AND (    DataB(2))AND(    DataB(1))AND(NOT DataI(0));
        Result(5):= Enable AND (    DataB(2))AND(NOT DataI(1))AND(    DataB(0));
        Result(4):= Enable AND (    DataB(2))AND(NOT DataI(1))AND(NOT DataI(0));
        Result(3):= Enable AND (NOT DataI(2))AND(    DataB(1))AND(    DataB(0));
        Result(2):= Enable AND (NOT DataI(2))AND(    DataB(1))AND(NOT DataI(0));
        Result(1):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND(    DataB(0));
        Result(0):= Enable AND (NOT DataI(2))AND(NOT DataI(1))AND(NOT DataI(0));
        RETURN Result;
    END;


    FUNCTION VitalDECODER   (
            CONSTANT DataB  : IN SchedArray;
            CONSTANT DataI  : IN SchedArray;
            CONSTANT Enable : IN SchedType
          ) RETURN SchedArray IS
        CONSTANT DMsb : INTEGER := DataB'LENGTH - 1;
        ALIAS DataBAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataB;
        ALIAS DataIAlias : SchedArray ( DMsb DOWNTO 0 ) IS DataI;
    BEGIN
        IF DataB'LENGTH = 1 THEN
            RETURN  VitalDECODER2 ( DataBAlias(    0     ),
                                    DataIAlias(    0     ), Enable );
        ELSIF DataB'LENGTH = 2 THEN
            RETURN  VitalDECODER4 ( DataBAlias(1 DOWNTO 0),
                                    DataIAlias(1 DOWNTO 0), Enable );
        ELSIF DataB'LENGTH = 3 THEN
            RETURN  VitalDECODER8 ( DataBAlias(2 DOWNTO 0),
                                    DataIAlias(2 DOWNTO 0), Enable );
        ELSIF DataB'LENGTH > 3 THEN
            RETURN  VitalDECODER  ( DataBAlias(DMsb-1 DOWNTO 0),
                                    DataIAlias(DMsb-1 DOWNTO 0),
                                    Enable AND (    DataBAlias(DMsb)) )
                  & VitalDECODER  ( DataBAlias(DMsb-1 DOWNTO 0),
                                    DataIAlias(DMsb-1 DOWNTO 0),
                                    Enable AND (NOT DataIAlias(DMsb)) );
        ELSE
            RETURN DefSchedArray2;
        END IF;
    END;


-------------------------------------------------------------------------------
-- PRIMITIVES
-------------------------------------------------------------------------------
    -- ------------------------------------------------------------------------
    -- N-bit wide Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalAND    (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '1';
        FOR i IN Data'RANGE LOOP
            Result := Result AND Data(i);
        END LOOP;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VitalOR     (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '0';
        FOR i IN Data'RANGE LOOP
            Result := Result OR Data(i);
        END LOOP;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VitalXOR    (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '0';
        FOR i IN Data'RANGE LOOP
            Result := Result XOR Data(i);
        END LOOP;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VitalNAND   (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '1';
        FOR i IN Data'RANGE LOOP
            Result := Result AND Data(i);
        END LOOP;
        RETURN ResultMap(NOT Result);
    END;
--
    FUNCTION VitalNOR    (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '0';
        FOR i IN Data'RANGE LOOP
            Result := Result OR Data(i);
        END LOOP;
        RETURN ResultMap(NOT Result);
    END;
--
    FUNCTION VitalXNOR   (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        Result := '0';
        FOR i IN Data'RANGE LOOP
            Result := Result XOR Data(i);
        END LOOP;
        RETURN ResultMap(NOT Result);
    END;

    -- ------------------------------------------------------------------------
    -- Commonly used 2-bit Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalAND2   (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a AND b);
    END;
--
    FUNCTION VitalOR2    (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a OR b);
    END;
--
    FUNCTION VitalXOR2   (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a XOR b);
    END;
--
    FUNCTION VitalNAND2  (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a NAND b);
    END;
--
    FUNCTION VitalNOR2   (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a NOR b);
    END;
--
    FUNCTION VitalXNOR2  (
            CONSTANT       a, b :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a XOR b));
    END;
--
    -- ------------------------------------------------------------------------
    -- Commonly used 3-bit Logical gates.
    -- ------------------------------------------------------------------------
    FUNCTION VitalAND3   (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a AND b AND c);
    END;
--
    FUNCTION VitalOR3    (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a OR b OR c);
    END;
--
    FUNCTION VitalXOR3   (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a XOR b XOR c);
    END;
--
    FUNCTION VitalNAND3  (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a AND b AND c));
    END;
--
    FUNCTION VitalNOR3   (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a OR b OR c));
    END;
--
    FUNCTION VitalXNOR3  (
            CONSTANT    a, b, c :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a XOR b XOR c));
    END;

    -- ---------------------------------------------------------------------------
    -- Commonly used 4-bit Logical gates.
    -- ---------------------------------------------------------------------------
    FUNCTION VitalAND4   (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a AND b AND c AND d);
    END;
--
    FUNCTION VitalOR4    (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a OR b OR c OR d);
    END;
--
    FUNCTION VitalXOR4   (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(a XOR b XOR c XOR d);
    END;
--
    FUNCTION VitalNAND4  (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a AND b AND c AND d));
    END;
--
    FUNCTION VitalNOR4   (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a OR b OR c OR d));
    END;
--
    FUNCTION VitalXNOR4  (
            CONSTANT a, b, c, d :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                      := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT (a XOR b XOR c XOR d));
    END;

    -- ------------------------------------------------------------------------
    -- Buffers
    --   BUF    ....... standard non-inverting buffer
    --   BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0')
    --   BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1')
    -- ------------------------------------------------------------------------
    FUNCTION VitalBUF    (
            CONSTANT         Data :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(To_UX01(Data));
    END;
--
    FUNCTION VitalBUFIF0 (
            CONSTANT Data, Enable :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(BufIf0_Table(Enable,Data));
    END;
--
    FUNCTION VitalBUFIF1 (
            CONSTANT Data, Enable :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(BufIf1_Table(Enable,Data));
    END;
    FUNCTION VitalIDENT  (
            CONSTANT         Data :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(To_UX01Z(Data));
    END;

    -- ------------------------------------------------------------------------
    -- Invertors
    --   INV    ......... standard inverting buffer
    --   INVIF0 ......... inverting buffer Data passes thru if (Enable = '0')
    --   INVIF1 ......... inverting buffer Data passes thru if (Enable = '1')
    -- ------------------------------------------------------------------------
    FUNCTION VitalINV    (
            CONSTANT         Data :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(NOT Data);
    END;
--
    FUNCTION VitalINVIF0 (
            CONSTANT Data, Enable :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(InvIf0_Table(Enable,Data));
    END;
--
    FUNCTION VitalINVIF1 (
            CONSTANT Data, Enable :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
          ) RETURN std_ulogic IS
    BEGIN
        RETURN ResultMap(InvIf1_Table(Enable,Data));
    END;

    -- ------------------------------------------------------------------------
    -- Multiplexor
    --   MUX   .......... result := data(dselect)
    --   MUX2  .......... 2-input mux; result := data0 when (dselect = '0'),
    --                                           data1 when (dselect = '1'),
    --                        'X' when (dselect = 'X') and (data0 /= data1)
    --   MUX4  .......... 4-input mux; result := data(dselect)
    --   MUX8  .......... 8-input mux; result := data(dselect)
    -- ------------------------------------------------------------------------
    FUNCTION VitalMUX2  (
            CONSTANT Data1, Data0 :  IN std_ulogic;
            CONSTANT      dSelect :  IN std_ulogic;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        CASE To_X01(dSelect) IS
          WHEN '0'    => Result := To_UX01(Data0);
          WHEN '1'    => Result := To_UX01(Data1);
          WHEN OTHERS => Result := VitalSame( Data1, Data0 );
        END CASE;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VitalMUX4  (
            CONSTANT       Data :  IN std_logic_vector4;
            CONSTANT    dSelect :  IN std_logic_vector2;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Slct : std_logic_vector2;
        VARIABLE Result : UX01;
    BEGIN
        Slct := To_X01(dSelect);
        CASE Slct IS
          WHEN "00"   => Result := To_UX01(Data(0));
          WHEN "01"   => Result := To_UX01(Data(1));
          WHEN "10"   => Result := To_UX01(Data(2));
          WHEN "11"   => Result := To_UX01(Data(3));
          WHEN "0X"   => Result := VitalSame( Data(1), Data(0) );
          WHEN "1X"   => Result := VitalSame( Data(2), Data(3) );
          WHEN "X0"   => Result := VitalSame( Data(2), Data(0) );
          WHEN "X1"   => Result := VitalSame( Data(3), Data(1) );
          WHEN OTHERS => Result := VitalSame( VitalSame(Data(3),Data(2)),
                                              VitalSame(Data(1),Data(0)));
        END CASE;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VitalMUX8  (
            CONSTANT       Data :  IN std_logic_vector8;
            CONSTANT    dSelect :  IN std_logic_vector3;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        VARIABLE Result : UX01;
    BEGIN
        CASE To_X01(dSelect(2)) IS
          WHEN '0'    => Result := VitalMUX4( Data(3 DOWNTO 0),
                                              dSelect(1 DOWNTO 0));
          WHEN '1'    => Result := VitalMUX4( Data(7 DOWNTO 4),
                                              dSelect(1 DOWNTO 0));
          WHEN OTHERS => Result := VitalSame( VitalMUX4( Data(3 DOWNTO 0),
                                                         dSelect(1 DOWNTO 0)),
                                              VitalMUX4( Data(7 DOWNTO 4),
                                                         dSelect(1 DOWNTO 0)));
        END CASE;
        RETURN ResultMap(Result);
    END;
--
    FUNCTION VInterMux    (
            CONSTANT Data    : IN std_logic_vector;
            CONSTANT dSelect : IN std_logic_vector
          ) RETURN std_ulogic IS

        CONSTANT sMsb     : INTEGER := dSelect'LENGTH;
        CONSTANT dMsbHigh : INTEGER := Data'LENGTH;
        CONSTANT dMsbLow  : INTEGER := Data'LENGTH/2;
        ALIAS DataAlias : std_logic_vector (   Data'LENGTH DOWNTO 1) IS Data;
        ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect;

        VARIABLE Result : UX01;
    BEGIN
        IF dSelect'LENGTH = 1 THEN
            Result := VitalMUX2( DataAlias(2), DataAlias(1), dSelAlias(1) );
        ELSIF dSelect'LENGTH = 2 THEN
            Result := VitalMUX4( DataAlias, dSelAlias );
        ELSIF dSelect'LENGTH > 2 THEN
          CASE To_X01(dSelect(sMsb)) IS
            WHEN '0'    =>
              Result := VInterMux( DataAlias(dMsbLow  DOWNTO          1),
                                   dSelAlias(sMsb-1 DOWNTO 1) );
            WHEN '1'    =>
              Result := VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1),
                                   dSelAlias(sMsb-1 DOWNTO 1) );
            WHEN OTHERS =>
              Result := VitalSame(
                              VInterMux( DataAlias(dMsbLow  DOWNTO          1),
                                         dSelAlias(sMsb-1 DOWNTO 1) ),
                              VInterMux( DataAlias(dMsbHigh DOWNTO dMsbLow+1),
                                         dSelAlias(sMsb-1 DOWNTO 1) )
                              );
          END CASE;
        ELSE
          Result := 'X'; -- dselect'LENGTH < 1
        END IF;
        RETURN Result;
    END;
--
    FUNCTION VitalMUX   (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT    dSelect :  IN std_logic_vector;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_ulogic IS
        CONSTANT msb    : INTEGER := 2**dSelect'LENGTH;
        ALIAS DataAlias : std_logic_vector (   Data'LENGTH DOWNTO 1) IS Data;
        ALIAS dSelAlias : std_logic_vector (dSelect'LENGTH DOWNTO 1) IS dSelect;
        VARIABLE lDat   : std_logic_vector(msb DOWNTO 1) := (OTHERS=>'X');
        VARIABLE Result : UX01;
    BEGIN
        IF Data'LENGTH <= msb THEN
            FOR i IN Data'LENGTH DOWNTO 1 LOOP
                lDat(i) := DataAlias(i);
            END LOOP;
        ELSE
            FOR i IN msb DOWNTO 1 LOOP
                lDat(i) := DataAlias(i);
            END LOOP;
        END IF;
        Result := VInterMux( lDat, dSelAlias );
        RETURN ResultMap(Result);
    END;

    -- ------------------------------------------------------------------------
    -- Decoder
    --          General Algorithm :
    --              (a) Result(...) := '0' when (enable = '0')
    --              (b) Result(data) := '1'; all other subelements = '0'
    --              ... Result array is decending (n-1 downto 0)
    --
    --          DECODERn  .......... n:2**n decoder
    -- ------------------------------------------------------------------------
    FUNCTION VitalDECODER2  (
            CONSTANT       Data :  IN std_ulogic;
            CONSTANT     Enable :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_logic_vector2 IS
        VARIABLE Result : std_logic_vector2;
    BEGIN
        Result(1) := ResultMap(Enable AND (    Data));
        Result(0) := ResultMap(Enable AND (NOT Data));
        RETURN Result;
    END;
--
    FUNCTION VitalDECODER4  (
            CONSTANT       Data :  IN std_logic_vector2;
            CONSTANT     Enable :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_logic_vector4 IS
        VARIABLE Result : std_logic_vector4;
    BEGIN
        Result(3) := ResultMap(Enable AND (    Data(1)) AND (    Data(0)));
        Result(2) := ResultMap(Enable AND (    Data(1)) AND (NOT Data(0)));
        Result(1) := ResultMap(Enable AND (NOT Data(1)) AND (    Data(0)));
        Result(0) := ResultMap(Enable AND (NOT Data(1)) AND (NOT Data(0)));
        RETURN Result;
    END;
--
    FUNCTION VitalDECODER8  (
            CONSTANT       Data :  IN std_logic_vector3;
            CONSTANT     Enable :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_logic_vector8 IS
        VARIABLE Result : std_logic_vector8;
    BEGIN
        Result(7) := (    Data(2)) AND (    Data(1)) AND (    Data(0));
        Result(6) := (    Data(2)) AND (    Data(1)) AND (NOT Data(0));
        Result(5) := (    Data(2)) AND (NOT Data(1)) AND (    Data(0));
        Result(4) := (    Data(2)) AND (NOT Data(1)) AND (NOT Data(0));
        Result(3) := (NOT Data(2)) AND (    Data(1)) AND (    Data(0));
        Result(2) := (NOT Data(2)) AND (    Data(1)) AND (NOT Data(0));
        Result(1) := (NOT Data(2)) AND (NOT Data(1)) AND (    Data(0));
        Result(0) := (NOT Data(2)) AND (NOT Data(1)) AND (NOT Data(0));

        Result(0) := ResultMap ( Enable AND Result(0) );
        Result(1) := ResultMap ( Enable AND Result(1) );
        Result(2) := ResultMap ( Enable AND Result(2) );
        Result(3) := ResultMap ( Enable AND Result(3) );
        Result(4) := ResultMap ( Enable AND Result(4) );
        Result(5) := ResultMap ( Enable AND Result(5) );
        Result(6) := ResultMap ( Enable AND Result(6) );
        Result(7) := ResultMap ( Enable AND Result(7) );

        RETURN Result;
    END;
--
    FUNCTION VitalDECODER   (
            CONSTANT       Data :  IN std_logic_vector;
            CONSTANT     Enable :  IN std_ulogic;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
          ) RETURN std_logic_vector IS

        CONSTANT DMsb : INTEGER := Data'LENGTH - 1;
        ALIAS DataAlias : std_logic_vector ( DMsb DOWNTO 0 ) IS Data;
    BEGIN
        IF    Data'LENGTH = 1 THEN
            RETURN VitalDECODER2 (DataAlias(    0     ), Enable, ResultMap );
        ELSIF Data'LENGTH = 2 THEN
            RETURN VitalDECODER4 (DataAlias(1 DOWNTO 0), Enable, ResultMap );
        ELSIF Data'LENGTH = 3 THEN
            RETURN VitalDECODER8 (DataAlias(2 DOWNTO 0), Enable, ResultMap );
        ELSIF Data'LENGTH > 3 THEN
            RETURN VitalDECODER  (DataAlias(DMsb-1 DOWNTO 0),
                                  Enable AND (    DataAlias(DMsb)), ResultMap )
                 & VitalDECODER  (DataAlias(DMsb-1 DOWNTO 0),
                                  Enable AND (NOT DataAlias(DMsb)), ResultMap );
        ELSE RETURN "X";
        END IF;
    END;

    -- ------------------------------------------------------------------------
    -- N-bit wide Logical gates.
    -- ------------------------------------------------------------------------
    PROCEDURE VitalAND   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge :  EdgeArray(Data'RANGE);
        VARIABLE Data_Schd : SchedArray(Data'RANGE);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalAND(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := '1';
        new_schd := Data_Schd(Data_Schd'LEFT);
        FOR i IN Data'RANGE LOOP
            NewValue  := NewValue  AND Data(i);
            new_schd := new_schd AND Data_Schd(i);
        END LOOP;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF; --SN
    END;
--
    PROCEDURE VitalOR    (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge :  EdgeArray(Data'RANGE);
        VARIABLE Data_Schd : SchedArray(Data'RANGE);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalOR(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := '0';
        new_schd := Data_Schd(Data_Schd'LEFT);
        FOR i IN Data'RANGE LOOP
            NewValue  := NewValue  OR Data(i);
            new_schd := new_schd OR Data_Schd(i);
        END LOOP;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF; --SN
    END;
--
    PROCEDURE VitalXOR   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge   :  EdgeArray(Data'RANGE);
        VARIABLE DataB_Schd  : SchedArray(1 TO Data'LENGTH);
        VARIABLE DataI_Schd  : SchedArray(1 TO Data'LENGTH);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd;
        ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalXOR(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
            InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( DataB_Schd, Data_Edge, Atpd_data_q );
        InvPath ( DataI_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := VitalXOR ( Data );
        new_schd := VitalXOR ( DataB_Schd, DataI_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF; --SN
    END;
--
    PROCEDURE VitalNAND  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge :  EdgeArray(Data'RANGE);
        VARIABLE Data_Schd : SchedArray(Data'RANGE);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalNAND(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        InvPath ( Data_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := '1';
        new_schd := Data_Schd(Data_Schd'LEFT);
        FOR i IN Data'RANGE LOOP
            NewValue  := NewValue  AND Data(i);
            new_schd := new_schd AND Data_Schd(i);
        END LOOP;
        NewValue  := NOT NewValue;
        new_schd := NOT new_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF;
    END;
--
    PROCEDURE VitalNOR   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge :  EdgeArray(Data'RANGE);
        VARIABLE Data_Schd : SchedArray(Data'RANGE);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalNOR(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            InvPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        InvPath ( Data_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := '0';
        new_schd := Data_Schd(Data_Schd'LEFT);
        FOR i IN Data'RANGE LOOP
            NewValue  := NewValue  OR Data(i);
            new_schd := new_schd OR Data_Schd(i);
        END LOOP;
        NewValue  := NOT NewValue;
        new_schd := NOT new_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF; --SN
    END;
--
    PROCEDURE VitalXNOR  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData    : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE Data_Edge   :  EdgeArray(Data'RANGE);
        VARIABLE DataB_Schd  : SchedArray(1 TO Data'LENGTH);
        VARIABLE DataI_Schd  : SchedArray(1 TO Data'LENGTH);
        VARIABLE NewValue     : UX01;
        VARIABLE Glitch_Data : GlitchDataType;
        VARIABLE new_schd    : SchedType;
        VARIABLE Dly, Glch   : TIME;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        ALIAS ADataB_Schd : SchedArray(Data'RANGE) IS DataB_Schd;
        ALIAS ADataI_Schd : SchedArray(Data'RANGE) IS DataI_Schd;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalXNOR(Data, ResultMap);
          WAIT ON Data;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( ADataB_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
            InvPath ( ADataI_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( DataB_Schd, Data_Edge, Atpd_data_q );
        InvPath ( DataI_Schd, Data_Edge, Atpd_data_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := VitalXNOR ( Data );
        new_schd := VitalXNOR ( DataB_Schd, DataI_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data;
      END LOOP;
      END IF; --SN
    END;
--

    -- ------------------------------------------------------------------------
    -- Commonly used 2-bit Logical gates.
    -- ------------------------------------------------------------------------
    PROCEDURE VitalAND2  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalAND2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := a AND b;
        new_schd := a_schd AND b_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalOR2   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalOR2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := a OR b;
        new_schd := a_schd OR b_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNAND2 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNAND2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := a NAND b;
        new_schd := a_schd NAND b_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNOR2  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNOR2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := a NOR b;
        new_schd := a_schd NOR b_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXOR2  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd : SchedType;
        VARIABLE ai_schd, bi_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXOR2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );
        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a XOR b;
        new_schd := VitalXOR2 ( ab_schd,ai_schd, bb_schd,bi_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXNOR2 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         a, b :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd : SchedType;
        VARIABLE ai_schd, bi_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF ((tpd_a_q = VitalZeroDelay01) AND (tpd_b_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXNOR2 ( a, b, ResultMap );
        WAIT ON a, b;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );
        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := NOT (a XOR b);
        new_schd := VitalXNOR2 ( ab_schd,ai_schd, bb_schd,bi_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b;
      END LOOP;
    END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Commonly used 3-bit Logical gates.
    -- ------------------------------------------------------------------------
    PROCEDURE VitalAND3  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN
--
    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalAND3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );
        BufPath ( c_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );
        BufPath ( c_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a AND b AND c;
        new_schd := a_schd AND b_schd AND c_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalOR3   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalOR3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );
        BufPath ( c_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );
        BufPath ( c_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a OR b OR c;
        new_schd := a_schd OR b_schd OR c_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNAND3 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNAND3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );
        InvPath ( c_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );
        InvPath ( c_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := (a AND b) NAND c;
        new_schd := (a_schd AND b_schd) NAND c_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNOR3  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNOR3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );
        InvPath ( c_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );
        InvPath ( c_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := (a OR b) NOR c;
        new_schd := (a_schd OR b_schd) NOR c_schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXOR3  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd, cb_schd : SchedType;
        VARIABLE ai_schd, bi_schd, ci_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXOR3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );
        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );
        BufPath ( cb_schd, InitialEdge(c), tpd_c_q );
        InvPath ( ci_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        BufPath ( cb_schd, GetEdge(c), tpd_c_q );
        InvPath ( ci_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a XOR b XOR c;
        new_schd := VitalXOR3 ( ab_schd,ai_schd,
                                bb_schd,bi_schd,
                                cb_schd,ci_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXNOR3 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL      a, b, c :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd, cb_schd : SchedType;
        VARIABLE ai_schd, bi_schd, ci_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXNOR3 ( a, b, c, ResultMap );
        WAIT ON a, b, c;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );
        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );
        BufPath ( cb_schd, InitialEdge(c), tpd_c_q );
        InvPath ( ci_schd, InitialEdge(c), tpd_c_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        BufPath ( cb_schd, GetEdge(c), tpd_c_q );
        InvPath ( ci_schd, GetEdge(c), tpd_c_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := NOT (a XOR b XOR c);
        new_schd := VitalXNOR3 ( ab_schd, ai_schd,
                                 bb_schd, bi_schd,
                                 cb_schd, ci_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c;
      END LOOP;
    END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Commonly used 4-bit Logical gates.
    -- ------------------------------------------------------------------------
    PROCEDURE VitalAND4  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalAND4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );
        BufPath ( c_schd, InitialEdge(c), tpd_c_q );
        BufPath ( d_Schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );
        BufPath ( c_schd, GetEdge(c), tpd_c_q );
        BufPath ( d_Schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a AND b AND c AND d;
        new_schd := a_schd AND b_schd AND c_schd AND d_Schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalOR4   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalOR4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( a_schd, InitialEdge(a), tpd_a_q );
        BufPath ( b_schd, InitialEdge(b), tpd_b_q );
        BufPath ( c_schd, InitialEdge(c), tpd_c_q );
        BufPath ( d_Schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( a_schd, GetEdge(a), tpd_a_q );
        BufPath ( b_schd, GetEdge(b), tpd_b_q );
        BufPath ( c_schd, GetEdge(c), tpd_c_q );
        BufPath ( d_Schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a OR b OR c OR d;
        new_schd := a_schd OR b_schd OR c_schd OR d_Schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNAND4 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNAND4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );
        InvPath ( c_schd, InitialEdge(c), tpd_c_q );
        InvPath ( d_Schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );
        InvPath ( c_schd, GetEdge(c), tpd_c_q );
        InvPath ( d_Schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := (a AND b) NAND (c AND d);
        new_schd := (a_schd AND b_schd) NAND (c_schd AND d_Schd);

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalNOR4  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE a_schd, b_schd, c_schd, d_Schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalNOR4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( a_schd, InitialEdge(a), tpd_a_q );
        InvPath ( b_schd, InitialEdge(b), tpd_b_q );
        InvPath ( c_schd, InitialEdge(c), tpd_c_q );
        InvPath ( d_Schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( a_schd, GetEdge(a), tpd_a_q );
        InvPath ( b_schd, GetEdge(b), tpd_b_q );
        InvPath ( c_schd, GetEdge(c), tpd_c_q );
        InvPath ( d_Schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := (a OR b) NOR (c OR d);
        new_schd := (a_schd OR b_schd) NOR (c_schd OR d_Schd);

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXOR4  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType;
        VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXOR4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );

        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );

        BufPath ( cb_schd, InitialEdge(c), tpd_c_q );
        InvPath ( ci_schd, InitialEdge(c), tpd_c_q );

        BufPath ( DB_Schd, InitialEdge(d), tpd_d_q );
        InvPath ( di_schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        BufPath ( cb_schd, GetEdge(c), tpd_c_q );
        InvPath ( ci_schd, GetEdge(c), tpd_c_q );

        BufPath ( DB_Schd, GetEdge(d), tpd_d_q );
        InvPath ( di_schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := a XOR b XOR c XOR d;
        new_schd := VitalXOR4 ( ab_schd,ai_schd, bb_schd,bi_schd,
                                cb_schd,ci_schd, DB_Schd,di_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalXNOR4 (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL   a, b, c, d :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_b_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_c_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    tpd_d_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE ab_schd, bb_schd, cb_schd, DB_Schd : SchedType;
        VARIABLE ai_schd, bi_schd, ci_schd, di_schd : SchedType;
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_a_q = VitalZeroDelay01)
         AND (tpd_b_q = VitalZeroDelay01)
         AND (tpd_c_q = VitalZeroDelay01)
         AND (tpd_d_q = VitalZeroDelay01)) THEN
      LOOP
        q <= VitalXNOR4 ( a, b, c, d, ResultMap );
        WAIT ON a, b, c, d;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( ab_schd, InitialEdge(a), tpd_a_q );
        InvPath ( ai_schd, InitialEdge(a), tpd_a_q );

        BufPath ( bb_schd, InitialEdge(b), tpd_b_q );
        InvPath ( bi_schd, InitialEdge(b), tpd_b_q );

        BufPath ( cb_schd, InitialEdge(c), tpd_c_q );
        InvPath ( ci_schd, InitialEdge(c), tpd_c_q );

        BufPath ( DB_Schd, InitialEdge(d), tpd_d_q );
        InvPath ( di_schd, InitialEdge(d), tpd_d_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( ab_schd, GetEdge(a), tpd_a_q );
        InvPath ( ai_schd, GetEdge(a), tpd_a_q );

        BufPath ( bb_schd, GetEdge(b), tpd_b_q );
        InvPath ( bi_schd, GetEdge(b), tpd_b_q );

        BufPath ( cb_schd, GetEdge(c), tpd_c_q );
        InvPath ( ci_schd, GetEdge(c), tpd_c_q );

        BufPath ( DB_Schd, GetEdge(d), tpd_d_q );
        InvPath ( di_schd, GetEdge(d), tpd_d_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := NOT (a XOR b XOR c XOR d);
        new_schd := VitalXNOR4 ( ab_schd,ai_schd, bb_schd,bi_schd,
                                 cb_schd,ci_schd, DB_Schd,di_schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON a, b, c, d;
      END LOOP;
    END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Buffers
    --   BUF    ....... standard non-inverting buffer
    --   BUFIF0 ....... non-inverting buffer Data passes thru if (Enable = '0')
    --   BUFIF1 ....... non-inverting buffer Data passes thru if (Enable = '1')
    -- ------------------------------------------------------------------------
    PROCEDURE VitalBUF   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL            a :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE NewValue      : UX01;
        VARIABLE Glitch_Data  : GlitchDataType;
        VARIABLE Dly, Glch    : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (tpd_a_q = VitalZeroDelay01) THEN
      LOOP
        q <= ResultMap(To_UX01(a));
        WAIT ON a;
      END LOOP;

    ELSE
      LOOP
        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := To_UX01(a);     -- convert to forcing strengths
        CASE EdgeType'(GetEdge(a)) IS
          WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr01);
          WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr10);
          WHEN OTHERS          => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10));
        END CASE;

        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode );

        WAIT ON a;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalBUFIF1 (
            SIGNAL              q : OUT std_ulogic;
            SIGNAL           Data :  IN std_ulogic;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01Z   := VitalDefDelay01Z;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
    ) IS
        VARIABLE NewValue        : UX01Z;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType;
        VARIABLE Dly, Glch      : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_data_q   = VitalZeroDelay01 )
         AND (tpd_enable_q = VitalZeroDelay01Z)) THEN
      LOOP
        q <= VitalBUFIF1( Data, Enable, ResultMap );
        WAIT ON Data, Enable;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( d_Schd, InitialEdge(Data), tpd_data_q );
        BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( d_Schd, GetEdge(Data), tpd_data_q );
        BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := VitalBUFIF1( Data, Enable );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data),
                        d_Schd, e1_Schd, e0_Schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalBUFIF0 (
            SIGNAL              q : OUT std_ulogic;
            SIGNAL           Data :  IN std_ulogic;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01Z   := VitalDefDelay01Z;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
    ) IS
        VARIABLE NewValue        : UX01Z;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType;
        VARIABLE ne1_schd, ne0_schd : SchedType;
        VARIABLE Dly, Glch      : TIME;
  BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_data_q   = VitalZeroDelay01 )
         AND (tpd_enable_q = VitalZeroDelay01Z)) THEN
      LOOP
        q <= VitalBUFIF0( Data, Enable, ResultMap );
        WAIT ON Data, Enable;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( d_Schd, InitialEdge(Data), tpd_data_q );
        InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( d_Schd, GetEdge(Data), tpd_data_q );
        InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := VitalBUFIF0( Data, Enable );
        ne1_schd := NOT e1_Schd;
        ne0_schd := NOT e0_Schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data),
                        d_Schd, ne1_schd, ne0_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
    END IF;
    END;

    PROCEDURE VitalIDENT (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL            a :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01Z   := VitalDefDelay01Z;
            CONSTANT  ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
    ) IS
        SUBTYPE v2 IS std_logic_vector(0 TO 1);
        VARIABLE NewValue      : UX01Z;
        VARIABLE Glitch_Data  : GlitchDataType;
        VARIABLE Dly, Glch    : TIME;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (tpd_a_q = VitalZeroDelay01Z) THEN
      LOOP
        q <= ResultMap(To_UX01Z(a));
        WAIT ON a;
      END LOOP;

    ELSE
      LOOP
        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        CASE v2'(To_X01Z(NewValue) & To_X01Z(a)) IS
          WHEN "00"   => Dly := tpd_a_q(tr10);
          WHEN "01"   => Dly := tpd_a_q(tr01);
          WHEN "0Z"   => Dly := tpd_a_q(tr0z);
          WHEN "0X"   => Dly := tpd_a_q(tr01);
          WHEN "10"   => Dly := tpd_a_q(tr10);
          WHEN "11"   => Dly := tpd_a_q(tr01);
          WHEN "1Z"   => Dly := tpd_a_q(tr1z);
          WHEN "1X"   => Dly := tpd_a_q(tr10);
          WHEN "Z0"   => Dly := tpd_a_q(trz0);
          WHEN "Z1"   => Dly := tpd_a_q(trz1);
          WHEN "ZZ"   => Dly := 0 ns;
          WHEN "ZX"   => Dly := Minimum (tpd_a_q(trz1), tpd_a_q(trz0));
          WHEN "X0"   => Dly := tpd_a_q(tr10);
          WHEN "X1"   => Dly := tpd_a_q(tr01);
          WHEN "XZ"   => Dly := Minimum (tpd_a_q(tr0z), tpd_a_q(tr1z));
          WHEN OTHERS => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10));
        END CASE;
        NewValue  := To_UX01Z(a);

        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode );

        WAIT ON a;
      END LOOP;
    END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Invertors
    --   INV    ......... standard inverting buffer
    --   INVIF0 ......... inverting buffer Data passes thru if (Enable = '0')
    --   INVIF1 ......... inverting buffer Data passes thru if (Enable = '1')
    -- ------------------------------------------------------------------------
    PROCEDURE VitalINV   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL            a :  IN std_ulogic   ;
            CONSTANT    tpd_a_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE NewValue      : UX01;
        VARIABLE Glitch_Data  : GlitchDataType;
        VARIABLE new_schd     : SchedType;
        VARIABLE Dly, Glch    : TIME;
    BEGIN
    IF (tpd_a_q = VitalZeroDelay01) THEN
      LOOP
        q <= ResultMap(NOT a);
        WAIT ON a;
      END LOOP;

    ELSE
      LOOP
        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue  := NOT a;
        CASE EdgeType'(GetEdge(a)) IS
          WHEN '1'|'/'|'R'|'r' => Dly := tpd_a_q(tr10);
          WHEN '0'|'\'|'F'|'f' => Dly := tpd_a_q(tr01);
          WHEN OTHERS          => Dly := Minimum (tpd_a_q(tr01), tpd_a_q(tr10));
        END CASE;

        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode );

        WAIT ON a;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalINVIF1 (
            SIGNAL              q : OUT std_ulogic;
            SIGNAL           Data :  IN std_ulogic;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01Z   := VitalDefDelay01Z;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
    ) IS
        VARIABLE NewValue        : UX01Z;
        VARIABLE new_schd       : SchedType;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType;
        VARIABLE Dly, Glch      : TIME;
  BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_data_q   = VitalZeroDelay01 )
         AND (tpd_enable_q = VitalZeroDelay01Z)) THEN
      LOOP
        q <= VitalINVIF1( Data, Enable, ResultMap );
        WAIT ON Data, Enable;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( d_Schd, InitialEdge(Data), tpd_data_q );
        BufEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( d_Schd, GetEdge(Data), tpd_data_q );
        BufEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := VitalINVIF1( Data, Enable );
        new_schd := NOT d_Schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data),
                        new_schd, e1_Schd, e0_Schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalINVIF0 (
            SIGNAL              q : OUT std_ulogic;
            SIGNAL           Data :  IN std_ulogic;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01Z   := VitalDefDelay01Z;
            CONSTANT    ResultMap :  IN VitalResultZMapType
                                        := VitalDefaultResultZMap
    ) IS
        VARIABLE NewValue        : UX01Z;
        VARIABLE new_schd       : SchedType;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE d_Schd, e1_Schd, e0_Schd : SchedType;
        VARIABLE ne1_schd, ne0_schd : SchedType := DefSchedType;
        VARIABLE Dly, Glch      : TIME;
  BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_data_q   = VitalZeroDelay01 )
         AND (tpd_enable_q = VitalZeroDelay01Z)) THEN
      LOOP
        q <= VitalINVIF0( Data, Enable, ResultMap );
        WAIT ON Data, Enable;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        InvPath ( d_Schd, InitialEdge(Data), tpd_data_q );
        InvEnab ( e1_Schd, e0_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        InvPath ( d_Schd, GetEdge(Data), tpd_data_q );
        InvEnab ( e1_Schd, e0_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delay
        -- ------------------------------------
        NewValue := VitalINVIF0( Data, Enable );
        ne1_schd := NOT e1_Schd;
        ne0_schd := NOT e0_Schd;
        new_schd := NOT d_Schd;

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data),
                        new_schd, ne1_schd, ne0_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
    END IF;
    END;

    -- ------------------------------------------------------------------------
    -- Multiplexor
    --   MUX   .......... result := data(dselect)
    --   MUX2  .......... 2-input mux; result := data0 when (dselect = '0'),
    --                                           data1 when (dselect = '1'),
    --                        'X' when (dselect = 'X') and (data0 /= data1)
    --   MUX4  .......... 4-input mux; result := data(dselect)
    --   MUX8  .......... 8-input mux; result := data(dselect)
    -- ------------------------------------------------------------------------
    PROCEDURE VitalMUX2  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL       d1, d0 :  IN std_ulogic;
            SIGNAL         dSel :  IN std_ulogic;
            CONSTANT   tpd_d1_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT   tpd_d0_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_dsel_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
        VARIABLE d1_Schd,  d0_Schd  : SchedType;
        VARIABLE dSel_bSchd, dSel_iSchd : SchedType;
        VARIABLE d1_Edge, d0_Edge, dSel_Edge : EdgeType;
    BEGIN

    -- ------------------------------------------------------------------------
    --  For ALL zero delay paths, use simple model
    --   ( No delay selection, glitch detection required )
    -- ------------------------------------------------------------------------
    IF (     (tpd_d1_q   = VitalZeroDelay01)
         AND (tpd_d0_q   = VitalZeroDelay01)
         AND (tpd_dsel_q = VitalZeroDelay01) ) THEN
      LOOP
        q <= VitalMUX2 ( d1, d0, dSel, ResultMap );
        WAIT ON d1, d0, dSel;
      END LOOP;

    ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( d1_Schd, InitialEdge(d1), tpd_d1_q );
        BufPath ( d0_Schd, InitialEdge(d0), tpd_d0_q );
        BufPath ( dSel_bSchd, InitialEdge(dSel), tpd_dsel_q );
        InvPath ( dSel_iSchd, InitialEdge(dSel), tpd_dsel_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( d1_Schd, GetEdge(d1), tpd_d1_q );
        BufPath ( d0_Schd, GetEdge(d0), tpd_d0_q );
        BufPath ( dSel_bSchd, GetEdge(dSel), tpd_dsel_q );
        InvPath ( dSel_iSchd, GetEdge(dSel), tpd_dsel_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalMUX2 ( d1, d0, dSel );
        new_schd := VitalMUX2 ( d1_Schd, d0_Schd, dSel_bSchd, dSel_iSchd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON d1, d0, dSel;
      END LOOP;
    END IF;
    END;
--
    PROCEDURE VitalMUX4  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector4;
            SIGNAL         dSel :  IN std_logic_vector2;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_dsel_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE LastdSel  : std_logic_vector(dSel'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
        VARIABLE Data_Schd      : SchedArray4;
        VARIABLE Data_Edge      : EdgeArray4;
        VARIABLE dSel_Edge      : EdgeArray2;
        VARIABLE dSel_bSchd     : SchedArray2;
        VARIABLE dSel_iSchd     : SchedArray2;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN dSel'RANGE LOOP
          IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN
          FOR i IN Data'RANGE LOOP
              IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
                  AllZeroDelay := FALSE;
                  EXIT;
              END IF;
          END LOOP;

          IF (AllZeroDelay) THEN LOOP
              q <= VitalMUX(Data, dSel, ResultMap);
              WAIT ON Data, dSel;
          END LOOP;
          END IF;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        FOR n IN dSel'RANGE LOOP
            BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
            InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_Schd, Data_Edge, Atpd_data_q );

        GetEdge ( dSel, LastdSel, dSel_Edge );
        BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q );
        InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalMUX4 ( Data, dSel );
        new_schd := VitalMUX4 ( Data_Schd, dSel_bSchd, dSel_iSchd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, dSel;
      END LOOP;
      END IF; --SN
    END;

    PROCEDURE VitalMUX8  (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector8;
            SIGNAL         dSel :  IN std_logic_vector3;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_dsel_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType  := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE LastdSel  : std_logic_vector(dSel'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
        VARIABLE Data_Schd      : SchedArray8;
        VARIABLE Data_Edge      : EdgeArray8;
        VARIABLE dSel_Edge      : EdgeArray3;
        VARIABLE dSel_bSchd     : SchedArray3;
        VARIABLE dSel_iSchd     : SchedArray3;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN dSel'RANGE LOOP
          IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN
          FOR i IN Data'RANGE LOOP
              IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
                  AllZeroDelay := FALSE;
                  EXIT;
              END IF;
          END LOOP;

          IF (AllZeroDelay) THEN LOOP
              q <= VitalMUX(Data, dSel, ResultMap);
              WAIT ON Data, dSel;
          END LOOP;
          END IF;
       ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        FOR n IN dSel'RANGE LOOP
            BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
            InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_Schd, Data_Edge, Atpd_data_q );

        GetEdge ( dSel, LastdSel, dSel_Edge );
        BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q );
        InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalMUX8 ( Data, dSel );
        new_schd := VitalMUX8 ( Data_Schd, dSel_bSchd, dSel_iSchd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, dSel;
      END LOOP;
      END IF;
    END;
--
    PROCEDURE VitalMUX   (
            SIGNAL            q : OUT std_ulogic;
            SIGNAL         Data :  IN std_logic_vector;
            SIGNAL         dSel :  IN std_logic_vector;
            CONSTANT tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_dsel_q :  IN VitalDelayArrayType01;
            CONSTANT  ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE LastdSel  : std_logic_vector(dSel'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : UX01;
        VARIABLE Glitch_Data    : GlitchDataType;
        VARIABLE new_schd       : SchedType;
        VARIABLE Dly, Glch      : TIME;
        VARIABLE Data_Schd      : SchedArray(Data'RANGE);
        VARIABLE Data_Edge      : EdgeArray(Data'RANGE);
        VARIABLE dSel_Edge      : EdgeArray(dSel'RANGE);
        VARIABLE dSel_bSchd     : SchedArray(dSel'RANGE);
        VARIABLE dSel_iSchd     : SchedArray(dSel'RANGE);
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        ALIAS Atpd_dsel_q : VitalDelayArrayType01(dSel'RANGE) IS tpd_dsel_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      FOR i IN dSel'RANGE LOOP
          IF (Atpd_dsel_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
      END LOOP;
      IF (AllZeroDelay) THEN
          FOR i IN Data'RANGE LOOP
              IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
                  AllZeroDelay := FALSE;
                  EXIT;
              END IF;
          END LOOP;

          IF (AllZeroDelay) THEN LOOP
              q <= VitalMUX(Data, dSel, ResultMap);
              WAIT ON Data, dSel;
          END LOOP;
          END IF;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_Schd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        FOR n IN dSel'RANGE LOOP
            BufPath ( dSel_bSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
            InvPath ( dSel_iSchd(n), InitialEdge(dSel(n)), Atpd_dsel_q(n) );
        END LOOP;

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_Schd, Data_Edge, Atpd_data_q );

        GetEdge ( dSel, LastdSel, dSel_Edge );
        BufPath ( dSel_bSchd, dSel_Edge, Atpd_dsel_q );
        InvPath ( dSel_iSchd, dSel_Edge, Atpd_dsel_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalMUX ( Data, dSel );
        new_schd := VitalMUX ( Data_Schd, dSel_bSchd, dSel_iSchd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, ResultMap(NewValue), Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, dSel;
      END LOOP;
     END IF; --SN
    END;

    -- ------------------------------------------------------------------------
    -- Decoder
    --          General Algorithm :
    --              (a) Result(...) := '0' when (enable = '0')
    --              (b) Result(data) := '1'; all other subelements = '0'
    --              ... Result array is decending (n-1 downto 0)
    --
    --          DECODERn  .......... n:2**n decoder
    -- Caution: If 'ResultMap' defines other than strength mapping, the
    --          delay selection is not defined.
    -- ------------------------------------------------------------------------
    PROCEDURE VitalDECODER2  (
            SIGNAL              q : OUT std_logic_vector2;
            SIGNAL           Data :  IN std_ulogic;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE NewValue        : std_logic_vector2;
        VARIABLE Glitch_Data    : GlitchArray2;
        VARIABLE new_schd       : SchedArray2;
        VARIABLE Dly, Glch      : TimeArray2;
        VARIABLE Enable_Schd  : SchedType := DefSchedType;
        VARIABLE Data_BSchd, Data_ISchd : SchedType;
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      IF (tpd_enable_q = VitalZeroDelay01) AND (tpd_data_q = VitalZeroDelay01) THEN
      LOOP
          q <= VitalDECODER2(Data, Enable, ResultMap);
          WAIT ON Data, Enable;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        BufPath ( Data_BSchd, InitialEdge(Data), tpd_data_q );
        InvPath ( Data_ISchd, InitialEdge(Data), tpd_data_q );
        BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        BufPath ( Data_BSchd, GetEdge(Data), tpd_data_q );
        InvPath ( Data_ISchd, GetEdge(Data), tpd_data_q );

        BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalDECODER2 ( Data, Enable, ResultMap );
        new_schd := VitalDECODER2 ( Data_BSchd, Data_ISchd, Enable_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
      END IF; -- SN
    END;
--
    PROCEDURE VitalDECODER4  (
            SIGNAL              q : OUT std_logic_vector4;
            SIGNAL           Data :  IN std_logic_vector2;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    ResultMap :  IN VitalResultMapType       := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : std_logic_vector4;
        VARIABLE Glitch_Data    : GlitchArray4;
        VARIABLE new_schd       : SchedArray4;
        VARIABLE Dly, Glch      : TimeArray4;
        VARIABLE Enable_Schd    : SchedType;
        VARIABLE Enable_Edge    : EdgeType;
        VARIABLE Data_Edge      : EdgeArray2;
        VARIABLE Data_BSchd, Data_ISchd : SchedArray2;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      IF (tpd_enable_q /= VitalZeroDelay01) THEN
          AllZeroDelay := FALSE;
      ELSE
          FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
          END LOOP;
      END IF;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalDECODER4(Data, Enable, ResultMap);
          WAIT ON Data, Enable;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
            InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_BSchd, Data_Edge, Atpd_data_q );
        InvPath ( Data_ISchd, Data_Edge, Atpd_data_q );

        BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalDECODER4 ( Data, Enable, ResultMap );
        new_schd := VitalDECODER4 ( Data_BSchd, Data_ISchd, Enable_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
      END IF;
    END;
--
    PROCEDURE VitalDECODER8  (
            SIGNAL              q : OUT std_logic_vector8;
            SIGNAL           Data :  IN std_logic_vector3;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : std_logic_vector8;
        VARIABLE Glitch_Data    : GlitchArray8;
        VARIABLE new_schd       : SchedArray8;
        VARIABLE Dly, Glch      : TimeArray8;
        VARIABLE Enable_Schd    : SchedType;
        VARIABLE Enable_Edge    : EdgeType;
        VARIABLE Data_Edge      : EdgeArray3;
        VARIABLE Data_BSchd, Data_ISchd : SchedArray3;
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE; --SN
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      IF (tpd_enable_q /= VitalZeroDelay01) THEN
          AllZeroDelay := FALSE;
      ELSE
          FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
          END LOOP;
      END IF;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalDECODER(Data, Enable, ResultMap);
          WAIT ON Data, Enable;
      END LOOP;
      ELSE

        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
            InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_BSchd, Data_Edge, Atpd_data_q );
        InvPath ( Data_ISchd, Data_Edge, Atpd_data_q );

        BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalDECODER8 ( Data, Enable, ResultMap );
        new_schd := VitalDECODER8 ( Data_BSchd, Data_ISchd, Enable_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
      END IF; --SN
    END;
--
    PROCEDURE VitalDECODER   (
            SIGNAL              q : OUT std_logic_vector;
            SIGNAL           Data :  IN std_logic_vector;
            SIGNAL         Enable :  IN std_ulogic;
            CONSTANT   tpd_data_q :  IN VitalDelayArrayType01;
            CONSTANT tpd_enable_q :  IN VitalDelayType01    := VitalDefDelay01;
            CONSTANT    ResultMap :  IN VitalResultMapType
                                        := VitalDefaultResultMap
    ) IS
        VARIABLE LastData  : std_logic_vector(Data'RANGE) := (OTHERS=>'U');
        VARIABLE NewValue        : std_logic_vector(q'RANGE);
        VARIABLE Glitch_Data    : GlitchDataArrayType(q'RANGE);
        VARIABLE new_schd       : SchedArray(q'RANGE);
        VARIABLE Dly, Glch      : VitalTimeArray(q'RANGE);
        VARIABLE Enable_Schd    : SchedType;
        VARIABLE Enable_Edge    : EdgeType;
        VARIABLE Data_Edge      : EdgeArray(Data'RANGE);
        VARIABLE Data_BSchd, Data_ISchd : SchedArray(Data'RANGE);
        ALIAS Atpd_data_q : VitalDelayArrayType01(Data'RANGE) IS tpd_data_q;
        VARIABLE AllZeroDelay  : BOOLEAN := TRUE;
    BEGIN
      -- ------------------------------------------------------------------------
      --  Check if ALL zero delay paths, use simple model
      --   ( No delay selection, glitch detection required )
      -- ------------------------------------------------------------------------
      IF (tpd_enable_q /= VitalZeroDelay01) THEN
          AllZeroDelay := FALSE;
      ELSE
          FOR i IN Data'RANGE LOOP
          IF (Atpd_data_q(i) /= VitalZeroDelay01) THEN
              AllZeroDelay := FALSE;
              EXIT;
          END IF;
          END LOOP;
      END IF;
      IF (AllZeroDelay) THEN LOOP
          q <= VitalDECODER(Data, Enable, ResultMap);
          WAIT ON Data, Enable;
      END LOOP;
      ELSE
        -- --------------------------------------
        -- Initialize delay schedules
        -- --------------------------------------
        FOR n IN Data'RANGE LOOP
            BufPath ( Data_BSchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
            InvPath ( Data_ISchd(n), InitialEdge(Data(n)), Atpd_data_q(n) );
        END LOOP;
        BufPath ( Enable_Schd, InitialEdge(Enable), tpd_enable_q );

      LOOP
        -- --------------------------------------
        -- Process input signals
        --   get edge values
        --   re-evaluate output schedules
        -- --------------------------------------
        GetEdge ( Data, LastData, Data_Edge );
        BufPath ( Data_BSchd, Data_Edge, Atpd_data_q );
        InvPath ( Data_ISchd, Data_Edge, Atpd_data_q );

        BufPath ( Enable_Schd, GetEdge(Enable), tpd_enable_q );

        -- ------------------------------------
        -- Compute function and propation delaq
        -- ------------------------------------
        NewValue  := VitalDECODER ( Data, Enable, ResultMap );
        new_schd := VitalDECODER ( Data_BSchd, Data_ISchd, Enable_Schd );

        -- ------------------------------------------------------
        -- Assign Outputs
        --  get delays to new value and possable glitch
        --  schedule output change with On Event glitch detection
        -- ------------------------------------------------------
        GetSchedDelay ( Dly, Glch, NewValue, CurValue(Glitch_Data), new_schd );
        VitalGlitchOnEvent ( q, "q", Glitch_Data, NewValue, Dly,
                             PrimGlitchMode, GlitchDelay=>Glch );

        WAIT ON Data, Enable;
      END LOOP;
      END IF;
    END;

    -- ------------------------------------------------------------------------
    FUNCTION VitalTruthTable  (
            CONSTANT TruthTable   : IN VitalTruthTableType;
            CONSTANT DataIn       : IN std_logic_vector
          ) RETURN std_logic_vector IS

        CONSTANT InputSize   : INTEGER := DataIn'LENGTH;
        CONSTANT OutSize     : INTEGER := TruthTable'LENGTH(2) - InputSize;
        VARIABLE ReturnValue : std_logic_vector(OutSize - 1 DOWNTO 0)
                               := (OTHERS => 'X');
        VARIABLE DataInAlias : std_logic_vector(0 TO InputSize - 1)
                               :=  To_X01(DataIn);
        VARIABLE Index       : INTEGER;
        VARIABLE Err         : BOOLEAN := FALSE;

        -- This needs to be done since the TableLookup arrays must be
        -- ascending starting with 0
        VARIABLE TableAlias  : VitalTruthTableType(0 TO (TruthTable'LENGTH(1)-1),
                                                   0 TO (TruthTable'LENGTH(2)-1))
                                := TruthTable;

    BEGIN
        -- search through each row of the truth table
        IF OutSize > 0 THEN
          ColLoop:
            FOR i IN TableAlias'RANGE(1) LOOP

            RowLoop: -- Check each input element of the entry
              FOR j IN 0 TO InputSize LOOP

                IF (j = InputSize) THEN -- This entry matches
                    -- Return the Result
                    Index := 0;
                    FOR k IN TruthTable'LENGTH(2) - 1 DOWNTO InputSize LOOP
                        TruthOutputX01Z ( TableAlias(i,k),
                                          ReturnValue(Index), Err);
                        EXIT WHEN Err;
                        Index := Index + 1;
                    END LOOP;

                    IF Err THEN
                        ReturnValue := (OTHERS => 'X');
                    END IF;
                    RETURN ReturnValue;
                END IF;
                IF NOT ValidTruthTableInput(TableAlias(i,j)) THEN
                    VitalError ( "VitalTruthTable", ErrInpSym,
                                 To_TruthChar(TableAlias(i,j)) );
                    EXIT ColLoop;
                END IF;
                EXIT RowLoop WHEN NOT ( TruthTableMatch( DataInAlias(j),
                                                         TableAlias(i, j)));
              END LOOP RowLoop;
            END LOOP ColLoop;

        ELSE
            VitalError ( "VitalTruthTable", ErrTabWidSml );
        END IF;
        RETURN ReturnValue;
    END VitalTruthTable;

    FUNCTION VitalTruthTable  (
            CONSTANT TruthTable   : IN VitalTruthTableType;
            CONSTANT DataIn       : IN std_logic_vector
          ) RETURN std_logic IS

        CONSTANT InputSize  : INTEGER := DataIn'LENGTH;
        CONSTANT OutSize    : INTEGER := TruthTable'LENGTH(2) - InputSize;
        VARIABLE TempResult : std_logic_vector(OutSize - 1 DOWNTO 0)
                              := (OTHERS => 'X');
    BEGIN
        IF (OutSize > 0) THEN
            TempResult := VitalTruthTable(TruthTable, DataIn);
            IF ( 1 > OutSize) THEN
                VitalError ( "VitalTruthTable", ErrTabResSml );
            ELSIF ( 1 < OutSize) THEN
                VitalError ( "VitalTruthTable", ErrTabResLrg );
            END IF;
            RETURN (TempResult(0));
        ELSE
            VitalError ( "VitalTruthTable", ErrTabWidSml );
            RETURN 'X';
        END IF;
    END VitalTruthTable;

    PROCEDURE VitalTruthTable (
            SIGNAL   Result     : OUT std_logic_vector;
            CONSTANT TruthTable : IN  VitalTruthTableType;
            CONSTANT DataIn     : IN  std_logic_vector
    ) IS
        CONSTANT ResLeng     : INTEGER := Result'LENGTH;
        CONSTANT ActResLen   : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH;
        CONSTANT FinalResLen : INTEGER := Minimum(ActResLen, ResLeng);
        VARIABLE TempResult  : std_logic_vector(ActResLen - 1 DOWNTO 0)
                                := (OTHERS => 'X');

    BEGIN
        TempResult := VitalTruthTable(TruthTable, DataIn);

        IF (ResLeng > ActResLen) THEN
            VitalError ( "VitalTruthTable", ErrTabResSml );
        ELSIF (ResLeng < ActResLen) THEN
            VitalError ( "VitalTruthTable", ErrTabResLrg );
        END IF;
        TempResult(FinalResLen-1 DOWNTO 0) := TempResult(FinalResLen-1 DOWNTO 0);
        Result <= TempResult;

    END VitalTruthTable;

    PROCEDURE VitalTruthTable (
            SIGNAL   Result     : OUT std_logic;
            CONSTANT TruthTable : IN VitalTruthTableType;
            CONSTANT DataIn     : IN std_logic_vector
    ) IS

        CONSTANT ActResLen  : INTEGER := TruthTable'LENGTH(2) - DataIn'LENGTH;
        VARIABLE TempResult : std_logic_vector(ActResLen - 1 DOWNTO 0)
                              := (OTHERS => 'X');

    BEGIN
        TempResult := VitalTruthTable(TruthTable, DataIn);

        IF ( 1 > ActResLen) THEN
            VitalError ( "VitalTruthTable", ErrTabResSml );
        ELSIF ( 1 < ActResLen) THEN
            VitalError ( "VitalTruthTable", ErrTabResLrg );
        END IF;
        IF (ActResLen >  0) THEN
            Result <= TempResult(0);
        END IF;

    END VitalTruthTable;

    -- ------------------------------------------------------------------------
    PROCEDURE VitalStateTable (
            VARIABLE Result         : INOUT std_logic_vector;
            VARIABLE PreviousDataIn : INOUT std_logic_vector;
            CONSTANT StateTable     : IN VitalStateTableType;
            CONSTANT DataIn         : IN std_logic_vector;
            CONSTANT NumStates      : IN NATURAL
    ) IS

        CONSTANT InputSize     : INTEGER := DataIn'LENGTH;
        CONSTANT OutSize       : INTEGER
                                 := StateTable'LENGTH(2) - InputSize - NumStates;
        CONSTANT ResLeng       : INTEGER := Result'LENGTH;
        VARIABLE DataInAlias   : std_logic_vector(0 TO DataIn'LENGTH-1)
                                 := To_X01(DataIn);
        VARIABLE PrevDataAlias : std_logic_vector(0 TO PreviousDataIn'LENGTH-1)
                                 := To_X01(PreviousDataIn);
        VARIABLE ResultAlias   : std_logic_vector(0 TO ResLeng-1)
                                 := To_X01(Result);
        VARIABLE ExpResult     : std_logic_vector(0 TO OutSize-1);

    BEGIN
        IF (PreviousDataIn'LENGTH < DataIn'LENGTH) THEN
            VitalError ( "VitalStateTable", ErrVctLng, "PreviousDataIn<DataIn");

            ResultAlias := (OTHERS => 'X');
            Result := ResultAlias;

        ELSIF (OutSize <= 0) THEN
            VitalError ( "VitalStateTable", ErrTabWidSml );

            ResultAlias := (OTHERS => 'X');
            Result := ResultAlias;

        ELSE
            IF (ResLeng > OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResSml );
            ELSIF (ResLeng < OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResLrg );
            END IF;

            ExpResult := StateTableLookUp ( StateTable, DataInAlias,
                                            PrevDataAlias, NumStates,
                                            ResultAlias);
            ResultAlias := (OTHERS => 'X');
            ResultAlias ( Maximum(0, ResLeng - OutSize) TO ResLeng - 1)
                   := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1);

            Result := ResultAlias;
            PrevDataAlias(0 TO InputSize - 1) := DataInAlias;
            PreviousDataIn := PrevDataAlias;

        END IF;
    END VitalStateTable;


    PROCEDURE VitalStateTable (
            VARIABLE Result         : INOUT std_logic;        -- states
            VARIABLE PreviousDataIn : INOUT std_logic_vector; -- previous inputs and states
            CONSTANT StateTable     : IN VitalStateTableType; -- User's StateTable data
            CONSTANT DataIn         : IN std_logic_vector     -- Inputs
    ) IS

        VARIABLE ResultAlias : std_logic_vector(0 TO 0);
    BEGIN
        ResultAlias(0) := Result;
        VitalStateTable ( StateTable     => StateTable,
                          DataIn         => DataIn,
                          NumStates      => 1,
                          Result         => ResultAlias,
                          PreviousDataIn => PreviousDataIn
                        );
        Result := ResultAlias(0);

    END VitalStateTable;

    PROCEDURE VitalStateTable (
            SIGNAL   Result     : INOUT std_logic_vector;
            CONSTANT StateTable : IN VitalStateTableType;
            SIGNAL   DataIn     : IN std_logic_vector;
            CONSTANT NumStates  : IN NATURAL
    ) IS

        CONSTANT InputSize   : INTEGER := DataIn'LENGTH;
        CONSTANT OutSize     : INTEGER
                               := StateTable'LENGTH(2) - InputSize - NumStates;
        CONSTANT ResLeng     : INTEGER := Result'LENGTH;

        VARIABLE PrevData    : std_logic_vector(0 TO DataIn'LENGTH-1)
                               := (OTHERS => 'X');
        VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1);
        VARIABLE ResultAlias : std_logic_vector(0 TO ResLeng-1);
        VARIABLE ExpResult   : std_logic_vector(0 TO OutSize-1);

    BEGIN
        IF (OutSize <= 0) THEN
            VitalError ( "VitalStateTable", ErrTabWidSml );

            ResultAlias  := (OTHERS => 'X');
            Result <= ResultAlias;

        ELSE
            IF (ResLeng > OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResSml );
            ELSIF (ResLeng < OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResLrg );
            END IF;

            LOOP
                DataInAlias := To_X01(DataIn);
                ResultAlias := To_X01(Result);
                ExpResult   := StateTableLookUp ( StateTable, DataInAlias,
                                                  PrevData, NumStates,
                                                  ResultAlias);
                ResultAlias := (OTHERS => 'X');
                ResultAlias(Maximum(0, ResLeng - OutSize) TO ResLeng-1)
                       := ExpResult(Maximum(0, OutSize - ResLeng) TO OutSize-1);

                Result   <= ResultAlias;
                PrevData := DataInAlias;

                WAIT ON DataIn;
            END LOOP;

        END IF;

    END VitalStateTable;

    PROCEDURE VitalStateTable (
            SIGNAL   Result     : INOUT std_logic;
            CONSTANT StateTable : IN VitalStateTableType;
            SIGNAL   DataIn     : IN std_logic_vector
    ) IS

        CONSTANT InputSize   : INTEGER := DataIn'LENGTH;
        CONSTANT OutSize     : INTEGER := StateTable'LENGTH(2) - InputSize-1;

        VARIABLE PrevData    : std_logic_vector(0 TO DataIn'LENGTH-1)
                               := (OTHERS => 'X');
        VARIABLE DataInAlias : std_logic_vector(0 TO DataIn'LENGTH-1);
        VARIABLE ResultAlias : std_logic_vector(0 TO 0);
        VARIABLE ExpResult   : std_logic_vector(0 TO OutSize-1);

    BEGIN
        IF (OutSize <= 0) THEN
            VitalError ( "VitalStateTable", ErrTabWidSml );

            Result <= 'X';

        ELSE
            IF ( 1 > OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResSml );
            ELSIF ( 1 < OutSize) THEN
                VitalError ( "VitalStateTable", ErrTabResLrg );
            END IF;

            LOOP
                ResultAlias(0) := To_X01(Result);
                DataInAlias := To_X01(DataIn);
                ExpResult   := StateTableLookUp ( StateTable, DataInAlias,
                                                  PrevData, 1, ResultAlias);

                Result   <= ExpResult(OutSize-1);
                PrevData := DataInAlias;

                WAIT ON DataIn;
            END LOOP;
        END IF;

    END VitalStateTable;

    -- ------------------------------------------------------------------------
    -- std_logic resolution primitive
    -- ------------------------------------------------------------------------
    PROCEDURE VitalResolve (
            SIGNAL              q : OUT std_ulogic;
            CONSTANT         Data :  IN std_logic_vector
    ) IS
        VARIABLE uData : std_ulogic_vector(Data'RANGE);
    BEGIN
        FOR i IN Data'RANGE LOOP
            uData(i) := Data(i);
        END LOOP;
        q <= resolved(uData);
    END;

END VITAL_Primitives;
