1--
2--  File Name:         ResolutionPkg.vhd
3--  Design Unit Name:  ResolutionPkg
4--  Revision:          STANDARD VERSION
5--
6--  Maintainer:        Jim Lewis      email:  jim@SynthWorks.com
7--  Contributor(s):
8--     Jim Lewis      email:  jim@SynthWorks.com
9--
10--  Package Defines
11--      resolved resolution functions for integer, real, and time
12--      types resolved_integer, resolved_real, resolved_time
13--
14--  Developed for:
15--        SynthWorks Design Inc.
16--        VHDL Training Classes
17--        11898 SW 128th Ave.  Tigard, Or  97223
18--        http://www.SynthWorks.com
19--
20--  Revision History:
21--    Date      Version    Description
22--    09/2006:  0.1        Initial revision
23--                         Numerous revisions for VHDL Testbenches and Verification
24--    02/2009:  1.0        VHDL-2008 STANDARD VERSION
25--    05/2015   2015.05    Added Alerts
26--    --                   Replaced Alerts with asserts as alerts are illegal in pure functions
27--    11/2016   2016.11    Removed Asserts as they are not working as intended.
28--                         See ResolutionPkg_debug as it uses Alerts to correctly detect errors
29--
30--
31--  Copyright (c) 2005 - 2016 by SynthWorks Design Inc.  All rights reserved.
32--
33--  Verbatim copies of this source file may be used and
34--  distributed without restriction.
35--
36--  This source file may be modified and distributed under
37--  the terms of the ARTISTIC License as published by
38--  The Perl Foundation; either version 2.0 of the License,
39--  or (at your option) any later version.
40--
41--  This source is distributed in the hope that it will be
42--  useful, but WITHOUT ANY WARRANTY; without even the implied
43--  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
44--  PURPOSE. See the Artistic License for details.
45--
46--  You should have received a copy of the license with this source.
47--  If not download it from,
48--     http://www.perlfoundation.org/artistic_license_2_0
49--
50
51library ieee ;
52use ieee.std_logic_1164.all ;
53use ieee.numeric_std.all ;
54
55--library osvvm ;
56--use osvvm.AlertLogPkg.all ;
57
58package ResolutionPkg is
59  constant MULTIPLE_DRIVER_SEVERITY : severity_level := ERROR ;
60
61--
62-- Note that not all simulators support resolution functions of the form:
63--    subtype  std_logic_vector_max is (resolved_max) std_ulogic_vector ;
64--
65-- Hence, types of the form are offered as a temporary workaround until they do:
66--    std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008
67--
68
69  -- resolved_max
70  --   return maximum value.
71  --   No initializations required on ports, default of type'left is ok
72  function resolved_max ( s : std_ulogic_vector) return std_ulogic ;
73  subtype  std_logic_max is resolved_max std_ulogic ;
74  subtype  std_logic_vector_max is (resolved_max) std_ulogic_vector ;
75  type     std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008
76
77  subtype  unsigned_max is (resolved_max) unresolved_unsigned ;
78  type     unsigned_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008
79  subtype  signed_max   is (resolved_max) unresolved_signed ;
80  type     signed_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008
81
82  function resolved_max ( s : bit_vector) return bit ;
83  subtype  bit_max is resolved_max bit ;
84  subtype  bit_vector_max is (resolved_max) bit_vector ;
85  type     bit_vector_max_c is array (natural range <>) of bit_max ; -- for non VHDL-2008
86
87  function resolved_max ( s : integer_vector ) return integer ;
88  subtype  integer_max is resolved_max integer ;
89  subtype  integer_vector_max is (resolved_max) integer_vector ;
90  type     integer_vector_max_c is array (natural range <>) of integer_max ; -- for non VHDL-2008
91
92  function resolved_max ( s : time_vector ) return time ;
93  subtype  time_max is resolved_max time ;
94  subtype  time_vector_max is (resolved_max) time_vector ;
95  type     time_vector_max_c is array (natural range <>) of time_max ; -- for non VHDL-2008
96
97  function resolved_max ( s : real_vector ) return real ;
98  subtype  real_max is resolved_max real ;
99  subtype  real_vector_max is (resolved_max) real_vector ;
100  type     real_vector_max_c is array (natural range <>) of real_max ; -- for non VHDL-2008
101
102  function resolved_max ( s : string) return character ;
103  subtype  character_max is resolved_max character ;
104  subtype  string_max is (resolved_max) string ;
105  type     string_max_c is array (positive range <>) of character_max ; -- for non VHDL-2008
106
107  function resolved_max ( s : boolean_vector) return boolean ;
108  subtype  boolean_max is resolved_max boolean ;
109  subtype  boolean_vector_max is (resolved_max) boolean_vector ;
110  type     boolean_vector_max_c is array (natural range <>) of boolean_max ; -- for non VHDL-2008
111
112
113  -- return sum of values that /= type'left
114  -- No initializations required on ports, default of type'left is ok
115  function resolved_sum ( s : integer_vector ) return integer ;
116  subtype  integer_sum is resolved_sum integer ;
117  subtype  integer_vector_sum is (resolved_sum) integer_vector ;
118  type     integer_vector_sum_c is array (natural range <>) of integer_sum ; -- for non VHDL-2008
119
120  function resolved_sum ( s : time_vector ) return time ;
121  subtype  time_sum is resolved_sum time ;
122  subtype  time_vector_sum is (resolved_sum) time_vector ;
123  type     time_vector_sum_c is array (natural range <>) of time_sum ; -- for non VHDL-2008
124
125  function resolved_sum ( s : real_vector ) return real ;
126  subtype  real_sum is resolved_sum real ;
127  subtype  real_vector_sum is (resolved_sum) real_vector ;
128  type     real_vector_sum_c is array (natural range <>) of real_sum ; -- for non VHDL-2008
129
130
131  -- resolved_weak
132  -- Special just for std_ulogic
133  -- No initializations required on ports, default of type'left is ok
134  function resolved_weak (s : std_ulogic_vector) return std_ulogic ;  -- no init, type'left
135  subtype  std_logic_weak is resolved_weak std_ulogic ;
136  subtype  std_logic_vector_weak is (resolved_weak) std_ulogic_vector ;
137
138
139  -- legacy stuff
140  -- requires ports to be initialized to 0 in the appropriate type.
141  function resolved ( s : integer_vector ) return integer ;
142  subtype  resolved_integer is resolved integer ;
143
144  function resolved ( s : time_vector ) return time ;
145  subtype  resolved_time is resolved time ;
146
147  function resolved ( s : real_vector ) return real ;
148  subtype  resolved_real is resolved real ;
149
150  function resolved (s : string) return character ;      -- same as resolved_max
151  subtype  resolved_character is resolved character ;
152  -- subtype  resolved_string is (resolved) string ;  -- subtype will replace type later
153  type resolved_string is array (positive range <>) of resolved_character;  -- will change to subtype -- assert but no init
154
155  function resolved ( s : boolean_vector) return boolean ;  --same as resolved_max
156  subtype  resolved_boolean is resolved boolean ;
157
158end package ResolutionPkg ;
159package body ResolutionPkg is
160
161  -- resolved_max
162  -- return maximum value.  Assert FAILURE if more than 1 /= type'left
163  -- No initializations required on ports, default of type'left is ok
164
165  -- Optimized version is just the following:
166  --  ------------------------------------------------------------
167  --  function resolved_max ( s : <array_type> ) return <element_type> is
168  --  ------------------------------------------------------------
169  --  begin
170  --    return maximum(s) ;
171  --  end function resolved_max ;
172
173  ------------------------------------------------------------
174  function resolved_max (s : std_ulogic_vector) return std_ulogic is
175  ------------------------------------------------------------
176  begin
177    return maximum(s) ;
178  end function resolved_max ;
179
180  ------------------------------------------------------------
181  function resolved_max ( s : bit_vector ) return bit is
182  ------------------------------------------------------------
183  begin
184    return maximum(s) ;
185  end function resolved_max ;
186
187  ------------------------------------------------------------
188  function resolved_max ( s : integer_vector ) return integer is
189  ------------------------------------------------------------
190  begin
191    return maximum(s) ;
192  end function resolved_max ;
193
194  ------------------------------------------------------------
195  function resolved_max ( s : time_vector ) return time is
196  ------------------------------------------------------------
197  begin
198    return maximum(s) ;
199  end function resolved_max ;
200
201  ------------------------------------------------------------
202  function resolved_max ( s : real_vector ) return real is
203  ------------------------------------------------------------
204  begin
205    return maximum(s) ;
206  end function resolved_max ;
207
208  ------------------------------------------------------------
209  function resolved_max ( s : string ) return character is
210  ------------------------------------------------------------
211  begin
212    return maximum(s) ;
213  end function resolved_max ;
214
215  ------------------------------------------------------------
216  function resolved_max ( s : boolean_vector) return boolean is
217  ------------------------------------------------------------
218  begin
219    return maximum(s) ;
220  end function resolved_max ;
221
222
223  -- resolved_sum - appropriate for numeric types
224  -- return sum of values that /= type'left
225  -- No initializations required on ports, default of type'left is ok
226  ------------------------------------------------------------
227  function resolved_sum ( s : integer_vector ) return integer is
228  ------------------------------------------------------------
229    variable result : integer := 0 ;
230  begin
231    for i in s'RANGE loop
232      if s(i) /= integer'left then
233        result := s(i) + result;
234      end if ;
235    end loop ;
236    return result ;
237  end function resolved_sum ;
238
239  ------------------------------------------------------------
240  function resolved_sum ( s : time_vector ) return time is
241  ------------------------------------------------------------
242    variable result : time := 0 sec ;
243  begin
244    for i in s'RANGE loop
245      if s(i) /= time'left then
246        result := s(i) + result;
247      end if ;
248    end loop ;
249    return result ;
250  end function resolved_sum ;
251
252  ------------------------------------------------------------
253  function resolved_sum ( s : real_vector ) return real is
254  ------------------------------------------------------------
255    variable result : real := 0.0 ;
256  begin
257    for i in s'RANGE loop
258      if s(i) /= real'left then
259        result := s(i) + result;
260      end if ;
261    end loop ;
262    return result ;
263  end function resolved_sum ;
264
265
266  -- resolved_weak
267  -- Special just for std_ulogic
268  -- No initializations required on ports, default of type'left is ok
269  type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC;
270
271  constant weak_resolution_table : stdlogic_table := (
272    --  Resolution order:  Z < U < W < X < - < L < H < 0 < 1
273    --      ---------------------------------------------------------
274    --      |  U    X    0    1    Z    W    L    H    -        |   |
275    --      ---------------------------------------------------------
276             ('U', 'X', '0', '1', 'U', 'W', 'L', 'H', '-'),  -- | U |
277             ('X', 'X', '0', '1', 'X', 'X', 'L', 'H', '-'),  -- | X |
278             ('0', '0', '0', '1', '0', '0', '0', '0', '0'),  -- | 0 |
279             ('1', '1', '1', '1', '1', '1', '1', '1', '1'),  -- | 1 |
280             ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'),  -- | Z |
281             ('W', 'X', '0', '1', 'W', 'W', 'L', 'H', '-'),  -- | W |
282             ('L', 'L', '0', '1', 'L', 'L', 'L', 'H', 'L'),  -- | L |
283             ('H', 'H', '0', '1', 'H', 'H', 'W', 'H', 'H'),  -- | H |
284             ('-', '-', '0', '1', '-', '-', 'L', 'H', '-')   -- | - |
285             );
286
287  ------------------------------------------------------------
288  function resolved_weak (s : std_ulogic_vector) return std_ulogic is
289  ------------------------------------------------------------
290    variable result : std_ulogic := 'Z' ;
291  begin
292    for i in s'RANGE loop
293      result := weak_resolution_table(result, s(i)) ;
294    end loop ;
295    return result ;
296  end function resolved_weak ;
297
298
299  -- legacy stuff.
300  -- requires ports to be initialized to 0 in the appropriate type.
301
302  ------------------------------------------------------------
303  function resolved ( s : integer_vector ) return integer is
304  -- requires interface to be initialized to 0
305  ------------------------------------------------------------
306    variable result : integer := 0 ;
307    variable failed : boolean := FALSE ;
308  begin
309    for i in s'RANGE loop
310      if s(i) /= 0 then
311        failed := failed or (result /= 0) ;
312        result := maximum(s(i),result);
313      end if ;
314    end loop ;
315    assert not failed report "ResolutionPkg.resolved: multiple drivers on integer" severity MULTIPLE_DRIVER_SEVERITY ;
316    -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on integer") ;
317    return result ;
318  end function resolved ;
319
320  ------------------------------------------------------------
321  function resolved ( s : time_vector ) return time is
322  -- requires interface to be initialized to 0 ns
323  ------------------------------------------------------------
324    variable result : time := 0 ns ;
325    variable failed : boolean := FALSE ;
326  begin
327    for i in s'RANGE loop
328      if s(i) > 0 ns then
329        failed := failed or (result /= 0 ns) ;
330        result := maximum(s(i),result);
331      end if ;
332    end loop ;
333    assert not failed report "ResolutionPkg.resolved: multiple drivers on time" severity MULTIPLE_DRIVER_SEVERITY ;
334    -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on time") ;
335    return result ;
336  end function resolved ;
337
338  ------------------------------------------------------------
339  function resolved ( s : real_vector ) return real is
340  -- requires interface to be initialized to 0.0
341  ------------------------------------------------------------
342    variable result : real := 0.0 ;
343    variable failed : boolean := FALSE ;
344  begin
345    for i in s'RANGE loop
346      if s(i) /= 0.0 then
347        failed := failed or (result /= 0.0) ;
348        result := maximum(s(i),result);
349      end if ;
350    end loop ;
351    assert not failed report "ResolutionPkg.resolved: multiple drivers on real" severity MULTIPLE_DRIVER_SEVERITY ;
352    -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on real") ;
353    return result ;
354  end function resolved ;
355
356  ------------------------------------------------------------
357  function resolved (s : string) return character is
358  -- same as resolved_max
359  ------------------------------------------------------------
360    variable result : character := NUL ;
361    variable failed : boolean := FALSE ;
362  begin
363    for i in s'RANGE loop
364      if s(i) /= NUL then
365        failed := failed or (result /= NUL) ;
366        result := maximum(result, s(i)) ;
367      end if ;
368    end loop ;
369    assert not failed report "ResolutionPkg.resolved: multiple drivers on character" severity MULTIPLE_DRIVER_SEVERITY ;
370    -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on character") ;
371    return result ;
372  end function resolved ;
373
374  ------------------------------------------------------------
375  function resolved ( s : boolean_vector) return boolean is
376  -- same as resolved_max
377  ------------------------------------------------------------
378    variable result : boolean := FALSE ;
379    variable failed : boolean := FALSE ;
380  begin
381    for i in s'RANGE loop
382      if s(i) then
383        failed := failed or result ;
384        result := TRUE ;
385      end if ;
386    end loop ;
387    assert not failed report "ResolutionPkg.resolved: multiple drivers on boolean" severity MULTIPLE_DRIVER_SEVERITY ;
388    -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on boolean") ;
389    return result ;
390  end function resolved ;
391
392end package body ResolutionPkg ;
393