GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/math/math_pkg.vhd Lines: 49 49 100.0 %
Date: 2021-06-12 04:12:08 Branches: 103 196 52.6 %

Line Branch Exec Source
1

16592362
-- -------------------------------------------------------------------------------------------------
2
-- Copyright (c) Lukas Vik. All rights reserved.
3
--
4
-- This file is part of the tsfpga project.
5
-- https://tsfpga.com
6
-- https://gitlab.com/tsfpga/tsfpga
7
-- -------------------------------------------------------------------------------------------------
8
9
library ieee;
10
use ieee.std_logic_1164.all;
11
use ieee.numeric_std.all;
12
use ieee.math_real.all;
13
14
15
package math_pkg is
16
17
  function ceil_log2(value : positive) return natural;
18
  function log2(value : positive) return natural;
19
  function is_power_of_two(value : positive) return boolean;
20
21
  function num_bits_needed(value : natural) return positive;
22
  function num_bits_needed(value : unsigned) return positive;
23
24
  function round_up_to_power_of_two(value : positive) return positive;
25
26
  function lt_0(value  : signed) return boolean;
27
  function geq_0(value : signed) return boolean;
28
29
  function to_gray(value : unsigned) return std_logic_vector;
30
  function from_gray(code : std_logic_vector) return unsigned;
31
32
  function abs_vector(vector : integer_vector) return integer_vector;
33
  function vector_sum(vector : integer_vector) return integer;
34
35
  function greatest_common_divisor(value1, value2 : positive) return positive;
36
  function is_mutual_prime(candidate : positive; check_against : integer_vector) return boolean;
37
38
end package;
39
40
package body math_pkg is
41
42
  function ceil_log2(value : positive) return natural is
43
  begin
44
    -- 2-base logarithm rounded up
45

492
    return natural(ceil(log2(real(value))));
46
  end function;
47
48
  function floor_log2(value : positive) return natural is
49
  begin
50

460
    return natural(log2(real(value)));
51
  end function;
52
53
  function log2(value : positive) return natural is
54
  begin
55
    -- 2-base logarithm where argument must be a power of two
56

242
    assert is_power_of_two(value) report "Must be power of two: " & to_string(value) severity failure;
57
242
    return floor_log2(value);
58
  end function;
59
60
  function is_power_of_two(value : positive) return boolean is
61
678
    constant log2_value : integer := floor_log2(value);
62
  begin
63
678
    return 2 ** log2_value = value;
64
  end function;
65
66
  function num_bits_needed(value : unsigned) return positive is
67
  begin
68
    -- The number of bits needed to express the given value.
69

1178
    assert value'high > value'low report "Use only with descending range" severity failure;
70

1178
    assert value'low = 0 report "Use vector that starts at zero" severity failure;
71
72

1178
    for bit_idx in value'high downto value'low loop
73

62296
      if value(bit_idx) = '1' then
74

62296
        return bit_idx + 1;
75
      end if;
76
    end loop;
77
4
    return 1;
78
  end function;
79
80
  function num_bits_needed(value : natural) return positive is
81
992
    constant value_vector : unsigned(64 - 1 downto 0) := to_unsigned(value, 64);
82
992
    constant result : positive := num_bits_needed(value_vector);
83
  begin
84
    -- The number of bits needed to express the given value in an unsigned vector.
85

992
    assert value <= 2**result - 1 report "Calculated value not correct: " & to_string(value) & " " & to_string(result) severity failure;
86
992
    return result;
87
  end function;
88
89
  function round_up_to_power_of_two(value : positive) return positive is
90
  begin
91
16
    return 2 ** ceil_log2(value);
92
  end function;
93
94
  function lt_0(value : signed) return boolean is
95
  begin
96
    -- The Vivado synthesis engine has been shown to produce a lot of logic (20-30 LUTs) when
97
    -- doing simply "if value < 0 then ...", hence this bit operation is used instead.
98

2406406
    return value(value'left) = '1';
99
  end function;
100
101
  function geq_0(value : signed) return boolean is
102
  begin
103
    -- The Vivado synthesis engine has been shown to produce a lot of logic (20-30 LUTs) when
104
    -- doing simply "if value < 0 then ...", hence this bit operation is used instead.
105

6
    return value(value'left) = '0';
106
  end function;
107
108
  function to_gray(value : unsigned) return std_logic_vector is
109


183447374
    variable value_slv, result : std_logic_vector(value'range);
110
  begin
111
13762766
    value_slv := std_logic_vector(value);
112



13762766
    result := value_slv xor "0" & value_slv(value_slv'high downto 1);
113
13762766
    return result;
114
  end function;
115
116
  function from_gray(code : std_logic_vector) return unsigned is
117

3468950
    variable result : unsigned(code'range);
118
  begin
119



419216
    result(code'high) := code(code'high);
120

419216
    for bit_num in code'high -1 downto 0 loop
121



2630518
      result(bit_num) := result(bit_num + 1) xor code(bit_num);
122
    end loop;
123
124
419216
    return result;
125
  end function;
126
127
  function abs_vector(vector : integer_vector) return integer_vector is
128

10
    variable result : integer_vector(vector'range);
129
  begin
130
2
    for idx in vector'range loop
131



8
      result(idx) := abs(vector(idx));
132
    end loop;
133
2
    return result;
134
  end function;
135
136
  function vector_sum(vector : integer_vector) return integer is
137
4
    variable result : integer := 0;
138
  begin
139
4
    for idx in vector'range loop
140


12
      result := result + vector(idx);
141
    end loop;
142


4
    return result;
143
  end function;
144
145
  function greatest_common_divisor(value1, value2 : positive) return positive is
146
60
    variable tmp, smaller_value, larger_value : natural;
147
  begin
148
    -- Calculate the greatest_common_divisor between two values.
149
    -- Uses the euclidean algorithm
150

60
    smaller_value := minimum(value1, value2);
151

60
    larger_value := maximum(value1, value2);
152
153
162
    while smaller_value /= 0 loop
154
102
      tmp := smaller_value;
155
102
      smaller_value := larger_value mod smaller_value;
156
162
      larger_value := tmp;
157
    end loop;
158
159
60
    return larger_value;
160
  end function;
161
162
  function is_mutual_prime(candidate : positive; check_against : integer_vector) return boolean is
163
  begin
164
    -- Check if a number is a mutual prime (i.e. the greatest common divisor is one)
165
    -- with all numbers in a list.
166
44
    for idx in check_against'range loop
167


52
      if greatest_common_divisor(candidate, check_against(idx)) /= 1 then
168

52
        return false;
169
      end if;
170
    end loop;
171
172
    -- Greatest common divisor was 1 with all other factors, meaning that this
173
    -- factor was a mutual prime with all.
174

378
    return true;
175
  end function;
176
177
end package body;