diff options
Diffstat (limited to 'testsuite/gna/issue2103/pkg_math_utils.vhdl')
-rw-r--r-- | testsuite/gna/issue2103/pkg_math_utils.vhdl | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/testsuite/gna/issue2103/pkg_math_utils.vhdl b/testsuite/gna/issue2103/pkg_math_utils.vhdl new file mode 100644 index 000000000..4d3804082 --- /dev/null +++ b/testsuite/gna/issue2103/pkg_math_utils.vhdl @@ -0,0 +1,250 @@ +------------------------------------------------------------------------------ +-- ____ _____________ __ -- +-- / __ \/ ____/ ___/\ \/ / _ _ _ -- +-- / / / / __/ \__ \ \ / / \ / \ / \ -- +-- / /_/ / /___ ___/ / / / = ( M | S | K )= -- +-- /_____/_____//____/ /_/ \_/ \_/ \_/ -- +-- -- +------------------------------------------------------------------------------ +--! @copyright Copyright 2022 DESY +--! SPDX-License-Identifier: CERN-OHL-W-2.0 +------------------------------------------------------------------------------ +--! @date 2022-04-01 +--! @author Michael Buechler <michael.buechler@desy.de> +--! @author Lukasz Butkowski <lukasz.butkowski@desy.de> +------------------------------------------------------------------------------ +--! @brief +--! Math utilities +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +--! Package of mathematical utilities and support functions +package math_utils is + + --! Saturation status after an operation. + type t_saturation is (ST_SAT_OK, ST_SAT_OVERFLOWN, ST_SAT_UNDERFLOWN); + + --! The encoding for _t_staturation_ is + --! + --! * ST_SAT_OK = "00" (No saturation) + --! * ST_SAT_OVERFLOWN = "10" (Operation has overflown) + --! * ST_SAT_UNDERFLOWN = "01" (Operation has underflown) + attribute enum_encoding : string; + attribute enum_encoding of t_saturation : type is "00 10 01"; + + --! f_bit_length: + --! Comparable to Python's int.bit_length(), + --! but when arg is negative, calculate for two's complement. + --! Attention: returns 1 for argument -1. + --! When arg is zero, return 0. + function f_bit_length (arg: integer) return integer; + + --! f_unsigned_length: + --! Calculates the minimum unsigned signal length to store **arg**, + --! When arg is zero, return 0. + function f_unsigned_length (arg: natural) return natural; + + --! Calculates the minimum signed signal length to store *arg*, + --! When arg is zero, return 0. + function f_signed_length (arg: integer) return integer; + + --! f_maximum: + --! Porting of 'maximum' from VHDL 08' not present in the + --! 93' standard. + function f_maximum (a, b: integer) return integer; + + --! f_minimum: + --! Porting of 'minimum' from VHDL 08' not present in the + --! 93' standard + function f_minimum (a, b: integer) return integer; + + --! f_max_val_for_length: + --! Returns the maximum value representable by a numeric type of length + --! _length_ and sign _sign_. + function f_max_val_for_length (length: natural; sign : boolean) return integer; + + function f_max_val_of (arg: unsigned) return unsigned; + + --! f_max_val_of: + --! Returns the maximum value representable by a numeric type. + --! Signed and unsigned version. + function f_max_val_of (arg: signed) return signed; + + --! f_max_val_for_length: + --! Returns the maximum value representable by a numeric type of length + --! _length_ and sign _sign_. + function f_min_val_for_length (length: natural; sign : boolean) return integer; + + function f_min_val_of (arg: unsigned) return unsigned; + + --! f_min_val_of: + --! Returns the minimum value representable by a numeric type. + --! Signed and unsigned version. + function f_min_val_of (arg: signed) return signed; + + function f_is_max (arg: unsigned) return boolean; + + --! f_is_max: + --! Checks whether a signal is at its maximum value. + --! Signed and unsigned version. + function f_is_max (arg: signed) return boolean; + + function f_is_min (arg: unsigned) return boolean; + + --! f_is_min: + --! Checks whether a signal is at its minimum value. + --! Signed and unsigned version. + function f_is_min (arg: signed) return boolean; + +end package math_utils; + +--****************************************************************************** + +--****************************************************************************** + +package body math_utils is + + function f_bit_length (arg: integer) return integer is + begin + + if (arg = 0) then + return 0; + elsif (arg > 0) then + return integer(ceil(log2(real(arg + 1)))); + else + return integer(ceil(log2(-real(arg)))) + 1; + end if; + + end function; + + function f_unsigned_length (arg: natural) return natural is + begin + + return natural(f_bit_length(integer(arg))); + + end function; + + function f_signed_length (arg: integer) return integer is + begin + + if (arg >= 0) then + return f_bit_length(arg) + 1; + else + return f_bit_length(arg); + end if; + + end function; + + function f_maximum (a, b: integer) return integer is + begin + + if (a > b) then + return a; + else + return b; + end if; + + end function; + + function f_minimum (a, b: integer) return integer is + begin + + if (a < b) then + return a; + else + return b; + end if; + + end function; + + function f_max_val_for_length (length: natural; sign : boolean) return integer is + + constant C_SMAX : integer := (2 ** (length - 1)) - 1; + constant C_UMAX : integer := (2 ** length) - 1; + + begin + + if (sign) then + return C_SMAX; + else + return C_UMAX; + end if; + + end function; + + function f_max_val_of (arg: unsigned) return unsigned is + begin + + return to_unsigned(f_max_val_for_length(arg'length, false), arg'length); + + end function; + + function f_max_val_of (arg: signed) return signed is + begin + + return to_signed(f_max_val_for_length(arg'length, true), arg'length); + + end function; + + function f_min_val_for_length (length: natural; sign : boolean) return integer is + + constant C_SMIN : integer := - (2 ** (length - 1)); + constant C_UMIN : integer := 0; + + begin + + if (sign) then + return C_SMIN; + else + return C_UMIN; + end if; + + end function; + + function f_min_val_of (arg: unsigned) return unsigned is + begin + + return to_unsigned(f_min_val_for_length(arg'length, false), arg'length); + + end function; + + function f_min_val_of (arg: signed) return signed is + begin + + return to_signed(f_min_val_for_length(arg'length, true), arg'length); + + end function; + + function f_is_max (arg: unsigned) return boolean is + begin + + return arg = f_max_val_of(arg); + + end; + + function f_is_max (arg: signed) return boolean is + begin + + return arg = f_max_val_of(arg); + + end; + + function f_is_min (arg: unsigned) return boolean is + begin + + return arg = f_min_val_of(arg); + + end; + + function f_is_min (arg: signed) return boolean is + begin + + return arg = f_min_val_of(arg); + + end; + +end package body math_utils; |