OpenCores
URL https://opencores.org/ocsvn/iicmb/iicmb/trunk

Subversion Repositories iicmb

[/] [iicmb/] [trunk/] [src_tb/] [test.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sshuv2
 
2
--==============================================================================
3
--                                                                             |
4
--    Project: IIC Multiple Bus Controller (IICMB)                             |
5
--                                                                             |
6
--    Module:  Test package.                                                   |
7
--    Version:                                                                 |
8
--             1.0,   April 29, 2016                                           |
9 4 sshuv2
--             1.1,   May   10, 2016 Removed obsolete stuff                    |
10 2 sshuv2
--                                                                             |
11
--    Author:  Sergey Shuvalkin, (sshuv2@opencores.org)                        |
12
--                                                                             |
13
--==============================================================================
14
--==============================================================================
15
-- Copyright (c) 2016, Sergey Shuvalkin                                        |
16
-- All rights reserved.                                                        |
17
--                                                                             |
18
-- Redistribution and use in source and binary forms, with or without          |
19
-- modification, are permitted provided that the following conditions are met: |
20
--                                                                             |
21
-- 1. Redistributions of source code must retain the above copyright notice,   |
22
--    this list of conditions and the following disclaimer.                    |
23
-- 2. Redistributions in binary form must reproduce the above copyright        |
24
--    notice, this list of conditions and the following disclaimer in the      |
25
--    documentation and/or other materials provided with the distribution.     |
26
--                                                                             |
27
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
28
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   |
29
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  |
30
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE    |
31
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         |
32
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF        |
33
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    |
34
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN     |
35
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)     |
36
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  |
37
-- POSSIBILITY OF SUCH DAMAGE.                                                 |
38
--==============================================================================
39
 
40
 
41
library ieee;
42
use ieee.std_logic_1164.all;
43
use ieee.numeric_std.all;
44
 
45
 
46
--==============================================================================
47
package test is
48
 
49
  type integer_array     is array (natural range <>) of integer;
50
  type integer_array_ptr is access integer_array;
51
  type string_ptr        is access string;
52
 
53
  type char_file         is file of character;
54
  ------------------------------------------------------------------------------
55
  -- The file type declaration above implicitly defines the following operations:
56
  -- procedure file_open (                               file f : char_file; name : in string; open_kind : in file_open_kind := read_mode);
57
  -- procedure file_open (status : out file_open_status; file f : char_file; name : in string; open_kind : in file_open_kind := read_mode);
58
  -- procedure file_close(file f : char_file);
59
  -- procedure read (file f : char_file; value : out character);
60
  -- procedure write(file f : char_file; value : in  character);
61
  -- function  endfile(file f : char_file) return boolean;
62
  ------------------------------------------------------------------------------
63
 
64
  file stdin  : char_file open read_mode  is "STD_INPUT";
65
  file stdout : char_file open write_mode is "STD_OUTPUT";
66
 
67
  ------------------------------------------------------------------------------
68
  -- Printing to a file and stdout:
69
  constant newline : string := "" & lf;
70
 
71
  procedure fprint_string(file f : char_file; value : in string);
72
  procedure print_string(value : in string);
73
  --function to_string(value : in integer; width : in positive := 1) return string;
74
  --function to_string(value : in std_logic_vector) return string;
75
 
76
  ------------------------------------------------------------------------------
77
  -- Function for converting integer to string:
78
  function to_string(value  : in integer;
79
                     format : in string  := "d";
80
                     width  : in natural := 0;
81
                     prec   : in natural := 0) return string;
82
  function to_string(value  : in std_logic;
83
                     format : in string  := "b";
84
                     width  : in natural := 0;
85
                     prec   : in natural := 0) return string;
86
  function to_string(value  : in std_logic_vector;
87
                     format : in string  := "x";
88
                     width  : in natural := 0;
89
                     prec   : in natural := 0) return string;
90
  --
91
  -- format string: [FLAGS][WIDTH][.PREC]TYPE
92
  --
93
  --     * FLAGS
94
  --        an optional sequence of characters which control output
95
  --        justification, numeric signs, trailing zeroes, and octal and hex
96
  --        prefixes.  The flag characters are minus (`-'), plus (`+'), space
97
  --        ( ), zero (`0'), and sharp (`#').  They can appear in any
98
  --        combination.
99
  --
100
  --       `-'   The result of the conversion is left justified, and the right
101
  --             is padded with blanks.  If you do not use this flag, the
102
  --             result is right justified, and padded on the left.
103
  --
104
  --       `+'   The result of a signed conversion (as determined by TYPE)
105
  --             will always begin with a plus or minus sign.  (If you do not
106
  --             use this flag, positive values do not begin with a plus sign.)
107
  --
108
  --       `" " (space)'
109
  --             If the first character of a signed conversion specification
110
  --             is not a sign, or if a signed conversion results in no
111
  --             characters, the result will begin with a space.  If the space
112
  --             ( ) flag and the plus (`+') flag both appear, the space flag
113
  --             is ignored.
114
  --
115
  --       `0'   Leading zeroes are used to pad the field width (following any
116
  --             indication of sign or base); no spaces are used for padding.
117
  --             If the zero (`0') and minus (`-') flags both appear, the zero
118
  --             (`0') flag will be ignored.  If a precision PREC is specified,
119
  --             the zero (`0') flag is ignored.  Note that `0' is interpreted
120
  --             as a flag, not as the beginning of a field width.
121
  --   
122
  --       `#'   The result is to be converted to an alternative form,
123
  --             depending on the conversion type character:
124
  --
125
  --            `b'   result will have a `b' prefix.
126
  --
127
  --            `o'   increases precision to force the first digit of the
128
  --                  result to be a zero.
129
  --
130
  --            `x'   result will have a `0x' prefix.
131
  --
132
  --            `X'   result will have a `0X' prefix.
133
  --
134
  --            `all others'
135
  --                  ignored.
136
  --
137
  --     * WIDTH
138
  --        WIDTH is an optional minimum field width.  You can either specify
139
  --        it directly as a decimal integer, or indirectly by using instead
140
  --        an asterisk (`*'), in which case the 'width' argument is used as
141
  --        the field width.
142
  --
143
  --     * PREC
144
  --        an optional field; if present, it is introduced with "." (a
145
  --        period).  This field gives the minimum number of digits of an
146
  --        integer to print.  You can specify the precision either directly as
147
  --        a decimal integer or indirectly by using an asterisk (`*'), in which
148
  --        case a 'prec' argument is used as the precision.  If only a period
149
  --        is specified the precision is zero.
150
  --
151
  --     * TYPE
152
  --        TYPE field specifies what kind of conversion to_string() performs.
153
  --        Here is a table of these:
154
  --
155
  --       `b'   prints a unsigned binary integer;
156
  --
157
  --       `d'   prints a signed decimal integer; (same as `i')
158
  --
159
  --       `i'   prints a signed decimal integer; (same as `d')
160
  --
161
  --       `o'   prints an unsigned octal integer;
162
  --
163
  --       `u'   prints an unsigned decimal integer;
164
  --
165
  --       `x'   prints an unsigned hexadecimal integer (using `abcdef' as
166
  --             digits beyond `9');
167
  --
168
  --       `X'   prints an unsigned hexadecimal integer (using `ABCDEF' as
169
  --             digits beyond `9');
170
  ------------------------------------------------------------------------------
171
 
172
 
173
  ------------------------------------------------------------------------------
174
  -- format: [FLAGS][WIDTH][.PREC][SIZE][TYPE]
175
  --
176
  --     * FLAGS
177
  --
178
  --        an optional sequence of characters which control output
179
  --        justification, numeric signs, decimal points, trailing zeroes, and
180
  --        octal and hex prefixes.  The flag characters are minus (`-'), plus
181
  --        (`+'), space ( ), zero (`0'), and sharp (`#').  They can appear in
182
  --        any combination.
183
  --
184
  --       `-'
185
  --             The result of the conversion is left justified, and the right
186
  --             is padded with blanks.  If you do not use this flag, the
187
  --             result is right justified, and padded on the left.
188
  --
189
  --       `+'
190
  --             The result of a signed conversion (as determined by TYPE)
191
  --             will always begin with a plus or minus sign.  (If you do not
192
  --             use this flag, positive values do not begin with a plus sign.)
193
  --
194
  --       `" " (space)'
195
  --             If the first character of a signed conversion specification
196
  --             is not a sign, or if a signed conversion results in no
197
  --             characters, the result will begin with a space.  If the space
198
  --             ( ) flag and the plus (`+') flag both appear, the space flag
199
  --             is ignored.
200
  --
201
  --       `0'
202
  --             If the TYPE character is `d', `i', `o', `u', `x', `X', `e',
203
  --             `E', `f', `g', or `G': leading zeroes, are used to pad the
204
  --             field width (following any indication of sign or base); no
205
  --             spaces are used for padding.  If the zero (`0') and minus
206
  --             (`-') flags both appear, the zero (`0') flag will be ignored.
207
  --             For `d', `i', `o', `u', `x', and `X' conversions, if a
208
  --             precision PREC is specified, the zero (`0') flag is ignored.
209
  --             Note that `0' is interpreted as a flag, not as the beginning
210
  --             of a field width.
211
  --   
212
  --       `#'
213
  --             The result is to be converted to an alternative form,
214
  --             according to the next character:
215
  --
216
  --            `0'
217
  --                  increases precision to force the first digit of the
218
  --                  result to be a zero.
219
  --
220
  --            `x'
221
  --                  a non-zero result will have a `0x' prefix.
222
  --
223
  --            `X'
224
  --                  a non-zero result will have a `0X' prefix.
225
  --
226
  --            `e, E or f'
227
  --                  The result will always contain a decimal point even if
228
  --                  no digits follow the point.  (Normally, a decimal point
229
  --                  appears only if a digit follows it.)  Trailing zeroes
230
  --                  are removed.
231
  --
232
  --            `g or G'
233
  --                  same as `e' or `E', but trailing zeroes are not removed.
234
  --
235
  --            `all others'
236
  --                  undefined.
237
  --
238
  --      * WIDTH
239
  --
240
  --        WIDTH is an optional minimum field width.  You can either specify
241
  --        it directly as a decimal integer, or indirectly by using instead
242
  --        an asterisk (`*'), in which case an `int' argument is used as the
243
  --        field width.  Negative field widths are not supported; if you
244
  --        attempt to specify a negative field width, it is interpreted as a
245
  --        minus (`-') flag followed by a positive field width.
246
  --
247
  --      * PREC
248
  --
249
  --        an optional field; if present, it is introduced with ``.'' (a
250
  --        period). This field gives the maximum number of characters to
251
  --        print in a conversion; the minimum number of digits of an integer
252
  --        to print, for conversions with TYPE `d', `i', `o', `u', `x', and
253
  --        `X'; the maximum number of significant digits, for the `g' and `G'
254
  --        conversions; or the number of digits to print after the decimal
255
  --        point, for `e', `E', and `f' conversions.  You can specify the
256
  --        precision either directly as a decimal integer or indirectly by
257
  --        using an asterisk (`*'), in which case an `int' argument is used
258
  --        as the precision.  Supplying a negative precision is equivalent to
259
  --        omitting the precision.  If only a period is specified the
260
  --        precision is zero.  If a precision appears with any other
261
  --        conversion TYPE than those listed here, the behavior is undefined.
262
  --
263
  --      * SIZE
264
  --
265
  --        `h', `l', and `L' are optional size characters which override the
266
  --        default way that `printf' interprets the data type of the
267
  --        corresponding argument.  `h' forces the following `d', `i', `o',
268
  --        `u', `x' or `X' conversion TYPE to apply to a `short' or `unsigned
269
  --        short'. `h' also forces a following `n' TYPE to apply to a pointer
270
  --        to a `short'. Similarily, an `l' forces the following `d', `i',
271
  --        `o', `u', `x' or `X' conversion TYPE to apply to a `long' or
272
  --        `unsigned long'.  `l' also forces a following `n' TYPE to apply to
273
  --        a pointer to a `long'.  `l' with `c', `s' is equivalent to `C',
274
  --        `S' respectively.  If an `h' or an `l' appears with another
275
  --        conversion specifier, the behavior is undefined.  `L' forces a
276
  --        following `e', `E', `f', `g' or `G' conversion TYPE to apply to a
277
  --        `long double' argument.  If `L' appears with any other conversion
278
  --        TYPE, the behavior is undefined.
279
  --
280
  --      * TYPE
281
  --
282
  --        TYPE specifies what kind of conversion `printf' performs.  Here is
283
  --        a table of these:
284
  --
285
  --       `%'
286
  --             prints the percent character (`%')
287
  --
288
  --       `c'
289
  --             prints ARG as single character
290
  --
291
  --       `C'
292
  --             prints wchar_t ARG as single multibyte character
293
  --
294
  --       `s'
295
  --             prints characters until precision is reached or a null
296
  --             terminator is encountered; takes a string pointer
297
  --
298
  --       `S'
299
  --             converts wchar_t characters to multibyte output characters
300
  --             until precision is reached or a null wchar_t terminator is
301
  --             encountered; takes a wchar_t pointer
302
  --
303
  --       `d'
304
  --             prints a signed decimal integer; takes an `int' (same as `i')
305
  --
306
  --       `i'
307
  --             prints a signed decimal integer; takes an `int' (same as `d')
308
  --
309
  --       `o'
310
  --             prints a signed octal integer; takes an `int'
311
  --
312
  --       `u'
313
  --             prints an unsigned decimal integer; takes an `int'
314
  --
315
  --       `x'
316
  --             prints an unsigned hexadecimal integer (using `abcdef' as
317
  --             digits beyond `9'); takes an `int'
318
  --
319
  --       `X'
320
  --             prints an unsigned hexadecimal integer (using `ABCDEF' as
321
  --             digits beyond `9'); takes an `int'
322
  --
323
  --       `f'
324
  --             prints a signed value of the form `[-]9999.9999'; takes a
325
  --             floating-point number
326
  --
327
  --       `e'
328
  --             prints a signed     value of the form
329
  --             `[-]9.9999e[+|-]999'; takes a floating-point number
330
  --
331
  --       `E'
332
  --             prints the same way as `e', but using `E' to introduce the
333
  --             exponent; takes a floating-point number
334
  --
335
  --       `g'
336
  --             prints a signed value in either `f' or `e' form, based on
337
  --             given value and precision--trailing zeros and the decimal
338
  --             point are printed only if necessary; takes a floating-point
339
  --             number
340
  --
341
  --       `G'
342
  --             prints the same way as `g', but using `E' for the exponent if
343
  --             an exponent is needed; takes a floating-point number
344
  --
345
  --       `n'
346
  --             stores (in the same object) a count of the characters written;
347
  --             takes a pointer to `int'
348
  --
349
  --       `p'
350
  --             prints a pointer in an implementation-defined format.  This
351
  --             implementation treats the pointer as an `unsigned long' (same
352
  --             as `Lu').
353
  ------------------------------------------------------------------------------
354
 
355
  -- Conversion functions
356
  function to_integer         (value : in string) return integer;
357
  ------------------------------------------------------------------------------
358
 
359
end test;
360
--==============================================================================
361
 
362
--==============================================================================
363
package body test is
364
 
365
  constant hexadecimal_chars : string(1 to 32) := "0123456789abcdef0123456789ABCDEF";
366
 
367
  ------------------------------------------------------------------------------
368
  function to_character(value : in std_logic) return character is
369
  begin
370
    case value is
371
      when 'U' => return 'U';
372
      when 'X' => return 'X';
373
      when '0' => return '0';
374
      when '1' => return '1';
375
      when 'Z' => return 'Z';
376
      when 'W' => return 'W';
377
      when 'L' => return 'L';
378
      when 'H' => return 'H';
379
      when '-' => return '-';
380
    end case;
381
  end function to_character;
382
  ------------------------------------------------------------------------------
383
 
384
  ------------------------------------------------------------------------------
385
  procedure fprint_string (file f : char_file; value : in string) is
386
  begin
387
    for i in value'low to value'high loop
388
      write(f, value(i));
389
    end loop;
390
  end procedure fprint_string;
391
  ------------------------------------------------------------------------------
392
 
393
  ------------------------------------------------------------------------------
394
  procedure print_string(value : in string) is
395
  begin
396
    fprint_string(stdout, value);
397
  end procedure print_string;
398
  ------------------------------------------------------------------------------
399
 
400
  ------------------------------------------------------------------------------
401
  function to_integer(value : in string) return integer is
402
    variable value_local : integer := 0;
403
    variable start_idx   : positive;
404
    variable negative    : boolean;
405
  begin
406
    if (value'right > 2)and(value(1) = '0')and(value(2) = 'x') then -- hex format
407
      start_idx := 3;
408
 
409
      for i in start_idx to value'right loop
410
        if    (value(i) >= 'a')and(value(i) <= 'f') then
411
          value_local := (16 * value_local) + (character'pos(value(i)) - character'pos('a') + 10);
412
        elsif (value(i) >= 'A')and(value(i) <= 'F') then
413
          value_local := (16 * value_local) + (character'pos(value(i)) - character'pos('A') + 10);
414
        else
415
          value_local := (16 * value_local) + (character'pos(value(i)) - character'pos('0'));
416
        end if;
417
      end loop;
418
    else
419
      if (value(1) = '-') then
420
        negative  := true;
421
        start_idx := 2;
422
      else
423
        negative  := false;
424
        start_idx := 1;
425
      end if;
426
 
427
      for i in start_idx to value'right loop
428
        value_local := (10 * value_local) + (character'pos(value(i)) - character'pos('0'));
429
      end loop;
430
 
431
      if (negative) then
432
        value_local := (-1) * value_local;
433
      end if;
434
    end if;
435
 
436
    return value_local;
437
  end function to_integer;
438
  ------------------------------------------------------------------------------
439
 
440
  --function to_string(value : in integer; width : in positive := 1) return string is
441
  --  variable idx  : positive;
442
  --  variable buf  : string(1 to 80);
443
  --  variable negative : boolean := (value < 0);
444
  --  variable value_local : integer := abs(value);
445
  --begin
446
  --  idx := 80;
447
 
448
  --  if (value_local = 0) then
449
  --    buf(idx) := '0';
450
  --    idx := idx - 1;
451
  --  end if;
452
 
453
  --  while (value_local /= 0) loop
454
  --    buf(idx) := character'val((value_local rem 10) + character'pos('0'));
455
  --    value_local := value_local / 10;
456
  --    idx := idx - 1;
457
  --  end loop;
458
 
459
  --  if (negative) then
460
  --    buf(idx) := '-';
461
  --    idx := idx - 1;
462
  --  end if;
463
 
464
  --  while ((80 - idx) < width) loop
465
  --    buf(idx) := ' ';
466
  --    idx := idx - 1;
467
  --  end loop;
468
 
469
  --  buf(1 to (80 - idx)) := buf((1 + idx) to 80);
470
 
471
  --  return buf(1 to (80 - idx));
472
  --end function to_string;
473
 
474
  --function to_string(value : in std_logic_vector) return string is
475
  --  variable res_string : string((((value'length + 3)/4) + 2) downto 1);
476
  --  variable res_idx    : positive;
477
  --  variable hex_digit  : integer;
478
  --begin
479
 
480
  --  hex_digit := 0;
481
  --  res_idx   := 1;
482
  --  for idx in value'right to value'left loop
483
  --    if    (value(idx)  = '1') then
484
  --      hex_digit := hex_digit + 2**((idx - value'right) rem 4);
485
  --    elsif (value(idx) /= '0') then
486
  --      hex_digit := hex_digit + 100;
487
  --    end if;
488
  --    if (((idx - value'right) rem 4) = 3)or(idx = value'left) then
489
  --      case hex_digit is
490
  --        when  0     => res_string(res_idx) := '0';
491
  --        when  1     => res_string(res_idx) := '1';
492
  --        when  2     => res_string(res_idx) := '2';
493
  --        when  3     => res_string(res_idx) := '3';
494
  --        when  4     => res_string(res_idx) := '4';
495
  --        when  5     => res_string(res_idx) := '5';
496
  --        when  6     => res_string(res_idx) := '6';
497
  --        when  7     => res_string(res_idx) := '7';
498
  --        when  8     => res_string(res_idx) := '8';
499
  --        when  9     => res_string(res_idx) := '9';
500
  --        when 10     => res_string(res_idx) := 'A';
501
  --        when 11     => res_string(res_idx) := 'B';
502
  --        when 12     => res_string(res_idx) := 'C';
503
  --        when 13     => res_string(res_idx) := 'D';
504
  --        when 14     => res_string(res_idx) := 'E';
505
  --        when 15     => res_string(res_idx) := 'F';
506
  --        when others => res_string(res_idx) := 'X';
507
  --      end case;
508
  --      hex_digit := 0;
509
  --      res_idx   := res_idx + 1;
510
  --    end if;
511
  --  end loop;
512
  --  res_string(res_string'left)     := '0';
513
  --  res_string(res_string'left - 1) := 'x';
514
 
515
  --  return res_string;
516
  --end function to_string;
517
 
518
 
519
  ------------------------------------------------------------------------------
520
  function to_string(value  : in std_logic;
521
                     format : in string  := "b";
522
                     width  : in natural := 0;
523
                     prec   : in natural := 0) return string is
524
  begin
525
    return to_string("" & value, format, width, prec);
526
  end function to_string;
527
  ------------------------------------------------------------------------------
528
 
529
  ------------------------------------------------------------------------------
530
  function sel(arg0 : boolean; arg1 : integer; arg2 : integer) return integer is
531
  begin
532
    if (arg0) then return arg1; else return arg2; end if;
533
  end function sel;
534
  ------------------------------------------------------------------------------
535
 
536
  ------------------------------------------------------------------------------
537
  function sel(arg0 : boolean; arg1 : std_logic; arg2 : std_logic) return std_logic is
538
  begin
539
    if (arg0) then return arg1; else return arg2; end if;
540
  end function sel;
541
  ------------------------------------------------------------------------------
542
 
543
  ------------------------------------------------------------------------------
544
  function sel(arg0 : boolean; arg1 : character; arg2 : character) return character is
545
  begin
546
    if (arg0) then return arg1; else return arg2; end if;
547
  end function sel;
548
  ------------------------------------------------------------------------------
549
 
550
  ------------------------------------------------------------------------------
551
  function max(arg0 : integer; arg1 : integer) return integer is
552
  begin
553
    return sel(arg0 > arg1, arg0, arg1);
554
  end function max;
555
  ------------------------------------------------------------------------------
556
 
557
  ------------------------------------------------------------------------------
558
  function signed_num_bits(arg : integer) return positive is
559
    variable nbits : natural := 1;
560
    variable n     : natural := sel(arg < 0, -(arg + 1), arg);
561
  begin
562
    while (n > 0) loop
563
      nbits := nbits + 1;
564
      n     := n / 2;
565
    end loop;
566
    return nbits;
567
  end function signed_num_bits;
568
  ------------------------------------------------------------------------------
569
 
570
  ------------------------------------------------------------------------------
571
  function to_string(value  : in integer;
572
                     format : in string  := "d";
573
                     width  : in natural := 0;
574
                     prec   : in natural := 0) return string is
575
    variable tmp      : std_logic_vector(signed_num_bits(integer'high) - 1 downto 0);
576
    variable negative : std_logic := sel(value < 0, '1', '0');
577
    variable n        : natural   := sel(value < 0, -(value + 1), value);
578
  begin
579
    for i in tmp'right to tmp'left loop
580
      tmp(i) := sel(((n mod 2) = 0), negative, not(negative));
581
      n      := n / 2;
582
    end loop;
583
    return to_string(tmp, format, width, prec);
584
  end function to_string;
585
  ------------------------------------------------------------------------------
586
 
587
  ------------------------------------------------------------------------------
588
  function to_string(value  : in std_logic_vector;
589
                     format : in string  := "x";
590
                     width  : in natural := 0;
591
                     prec   : in natural := 0) return string is
592
    -- Flags:
593
    variable minus_flag             : boolean := false;
594
    variable plus_flag              : boolean := false;
595
    variable space_flag             : boolean := false;
596
    variable zero_flag              : boolean := false;
597
    variable sharp_flag             : boolean := false;
598
    -- Width:
599
    variable width_local            : natural := 0;
600
    -- Precision:
601
    variable prec_local             : natural := 0;
602
    -- Conversion Type:
603
    type conversion_type_type is (unsigned_binary, signed_decimal, unsigned_octal, unsigned_decimal, unsigned_hexadecimal_0, unsigned_hexadecimal_1);
604
    variable type_local             : conversion_type_type := signed_decimal;
605
    --
606
    --
607
    variable value_local            : std_logic_vector(value'length - 1 downto 0);
608
    variable idx                    : integer;
609
    variable number_buffer          : string(1 to value'length);
610
    variable sign_buffer            : string(1 to 2);
611
    variable result_ptr             : string_ptr;
612
    --
613
    variable space_padding_0        : integer;
614
    variable sign_chars             : integer;
615
    variable zero_padding           : integer;
616
    variable number_chars           : integer;
617
    variable space_padding_1        : integer;
618
  begin
619
    idx := format'low;
620
 
621
    -- Parse format string:
622
    ---- Read flags:
623
    while (true) loop
624
      case format(idx) is
625
        when '-' =>
626
          if (minus_flag) then report "'-' flag was aready set before" severity warning; else minus_flag := true; end if;
627
        when '+' =>
628
          if (plus_flag ) then report "'+' flag was aready set before" severity warning; else plus_flag  := true; end if;
629
        when ' ' =>
630
          if (space_flag) then report "' ' flag was aready set before" severity warning; else space_flag := true; end if;
631
        when '0' =>
632
          if (zero_flag ) then report "'0' flag was aready set before" severity warning; else zero_flag  := true; end if;
633
        when '#' =>
634
          if (sharp_flag) then report "'#' flag was aready set before" severity warning; else sharp_flag := true; end if;
635
        when others => exit;
636
      end case;
637
      if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
638
    end loop;
639
 
640
    if (space_flag and plus_flag) then
641
      report "' ' flag is ignored due to presence of '+' flag" severity warning;
642
      space_flag := false;
643
    end if;
644
 
645
    if (minus_flag and zero_flag) then
646
      report "'0' flag is ignored due to presence of '-' flag" severity warning;
647
      zero_flag := false;
648
    end if;
649
 
650
    ---- Read width:
651
    if (format(idx) = '*') then
652
      width_local     := width;
653
      if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
654
    else
655
      while (true) loop
656
        case format(idx) is
657
          when '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
658
            width_local := (width_local * 10) + (character'pos(format(idx)) - character'pos('0'));
659
            if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
660
          when others => exit;
661
        end case;
662
      end loop;
663
    end if;
664
 
665
    ---- Read precision:
666
    if (format(idx) = '.') then
667
      prec_local     := 0;
668
      if (zero_flag) then
669
        report "'0' flag is ignored due to presence of PREC field" severity warning;
670
        zero_flag := false;
671
      end if;
672
      if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
673
      if (format(idx) = '*') then
674
        prec_local     := prec;
675
        if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
676
      else
677
        while (true) loop
678
          case format(idx) is
679
            when '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
680
              prec_local := (prec_local * 10) + (character'pos(format(idx)) - character'pos('0'));
681
              if (idx < format'high) then idx := idx + 1; else report "Unexpected end of format string." severity error; end if;
682
            when others => exit;
683
          end case;
684
        end loop;
685
      end if;
686
    end if;
687
 
688
    ---- Read type:
689
    case format(idx) is
690
      when 'b'       =>
691
        type_local     := unsigned_binary;
692
      when 'd' | 'i' =>
693
        type_local     := signed_decimal;
694
        if (sharp_flag) then
695
          report "'#' flag is ignored due to signed decimal conversion type" severity warning;
696
          sharp_flag := false;
697
        end if;
698
      when 'o'       =>
699
        type_local     := unsigned_octal;
700
      when 'u'       =>
701
        type_local     := unsigned_decimal;
702
        if (sharp_flag) then
703
          report "'#' flag is ignored due to unsigned decimal conversion type" severity warning;
704
          sharp_flag := false;
705
        end if;
706
      when 'x'       =>
707
        type_local     := unsigned_hexadecimal_0;
708
      when 'X'       =>
709
        type_local     := unsigned_hexadecimal_1;
710
      when others    =>
711
        report "Unknown conversion type character: " & format(idx) severity error;
712
        type_local     := signed_decimal;
713
    end case;
714
    assert (idx = format'high) report "Extra characters in format string" severity warning;
715
 
716
    ---- Obtain number string:
717
    case type_local is
718
      when unsigned_binary =>
719
        -- Fill number buffer:
720
        value_local := value;
721
        idx         := 1;
722
 
723
        while (true) loop
724
          number_buffer(idx) := to_character(value_local(0));
725
          value_local := '0' & value_local(value_local'high downto 1);
726
          idx := idx + 1;
727
          exit when (value_local = (value_local'range => '0'));
728
        end loop;
729
 
730
        -- Fill sign buffer:
731
        if (sharp_flag) then
732
          sign_chars     := 1;
733
          sign_buffer(1) := 'b';
734
        else
735
          sign_chars      := 0;
736
        end if;
737
 
738
      when signed_decimal         =>
739
        -- Fill number buffer:
740
        value_local := std_logic_vector(abs(signed(value)));
741
        idx         := 1;
742
 
743
        while (true) loop
744
          number_buffer(idx) := hexadecimal_chars(to_integer(unsigned(value_local) rem 10) + 1);
745
          value_local := std_logic_vector(unsigned(value_local) / 10);
746
          idx := idx + 1;
747
          exit when (value_local = (value_local'range => '0'));
748
        end loop;
749
 
750
        -- Fill sign buffer:
751
        if (signed(value) < 0) then
752
          sign_buffer(1) := '-';
753
        elsif (plus_flag) then
754
          sign_buffer(1) := '+';
755
        else
756
          sign_buffer(1) := ' ';
757
        end if;
758
        sign_chars      := sel(signed(value) < 0, 1, sel(plus_flag or space_flag, 1, 0));
759
 
760
      when unsigned_octal         =>
761
        -- Fill number buffer:
762
        value_local := value;
763
        idx         := 1;
764
 
765
        while (true) loop
766
          number_buffer(idx) := hexadecimal_chars(to_integer(unsigned(value_local) rem 8) + 1);
767
          value_local := std_logic_vector(unsigned(value_local) / 8);
768
          idx := idx + 1;
769
          exit when (value_local = (value_local'range => '0'));
770
        end loop;
771
 
772
        -- Fill sign buffer:
773
        sign_chars      := 0;
774
        prec_local      := sel(sharp_flag and (prec_local < idx), idx, prec_local);
775
 
776
      when unsigned_decimal       =>
777
        -- Fill number buffer:
778
        value_local := value;
779
        idx         := 1;
780
 
781
        while (true) loop
782
          number_buffer(idx) := hexadecimal_chars(to_integer(unsigned(value_local) rem 10) + 1);
783
          value_local := std_logic_vector(unsigned(value_local) / 10);
784
          idx := idx + 1;
785
          exit when (value_local = (value_local'range => '0'));
786
        end loop;
787
 
788
        -- Fill sign buffer:
789
        sign_chars      := 0;
790
 
791
      when unsigned_hexadecimal_0 | unsigned_hexadecimal_1 =>
792
        -- Fill number buffer:
793
        value_local := value;
794
        idx         := 1;
795
 
796
        while (true) loop
797
          number_buffer(idx) := hexadecimal_chars(to_integer(unsigned(value_local) rem 16) + sel(type_local = unsigned_hexadecimal_0, 1, 17));
798
          value_local := std_logic_vector(unsigned(value_local) / 16);
799
          idx := idx + 1;
800
          exit when (value_local = (value_local'range => '0'));
801
        end loop;
802
 
803
        -- Fill sign buffer:
804
        if (sharp_flag) then
805
          sign_chars     := 2;
806
          sign_buffer(1) := '0';
807
          sign_buffer(2) := sel(type_local = unsigned_hexadecimal_0, 'x', 'X');
808
        else
809
          sign_chars      := 0;
810
        end if;
811
 
812
    end case;
813
 
814
    --
815
    number_chars    := idx - 1;
816
    zero_padding    := max(prec_local - number_chars, 0);
817
    space_padding_0 := sel(minus_flag, 0, max(width_local - (sign_chars + zero_padding + number_chars), 0));
818
    space_padding_1 := sel(minus_flag, max(width_local - (sign_chars + zero_padding + number_chars), 0), 0);
819
 
820
    --
821
    result_ptr := new string(1 to space_padding_0 + sign_chars + zero_padding + number_chars + space_padding_1);
822
 
823
    -- fill the space padding 0:
824
    for i in 1 to space_padding_0 loop
825
      result_ptr.all(i) := ' ';
826
    end loop;
827
    -- put sign chars:
828
    for i in 1 to sign_chars loop
829
      result_ptr.all(space_padding_0 + i) := sign_buffer(i);
830
    end loop;
831
    -- fill zero poadding:
832
    for i in 1 to zero_padding loop
833
      result_ptr.all(space_padding_0 + sign_chars + i) := '0';
834
    end loop;
835
    -- put number chars:
836
    for i in 1 to number_chars loop
837
      result_ptr.all(space_padding_0 + sign_chars + zero_padding + i) := number_buffer(idx - i);
838
    end loop;
839
    -- fill the space padding 1:
840
    for i in 1 to space_padding_1 loop
841
      result_ptr.all(space_padding_0 + sign_chars + zero_padding + number_chars + i) := ' ';
842
    end loop;
843
 
844
    return result_ptr.all;
845
 
846
  end function to_string;
847
  ------------------------------------------------------------------------------
848
 
849
end test;
850
--==============================================================================
851
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.