925 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			925 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
PACKAGE BODY testUtils IS
 | 
						|
 | 
						|
  --============================================================================
 | 
						|
  -- console output
 | 
						|
  --
 | 
						|
 | 
						|
  procedure print(value : string) is
 | 
						|
    variable my_line : line;
 | 
						|
  begin
 | 
						|
    write(my_line, value);
 | 
						|
    writeLine(output, my_line);
 | 
						|
    deallocate(my_line);
 | 
						|
  end print;
 | 
						|
 | 
						|
 | 
						|
  --============================================================================
 | 
						|
  -- string manipulation
 | 
						|
  --
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- change to lowercase
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure lc(value: inout line) is
 | 
						|
    variable out_line: line;
 | 
						|
  begin
 | 
						|
    for index in value'range loop
 | 
						|
      if (value(index) >= 'A') and (value(index) <= 'Z') then
 | 
						|
        value(index) := character'val(character'pos(value(index))
 | 
						|
                                    - character'pos('A')
 | 
						|
                                    + character'pos('a')
 | 
						|
                                      );
 | 
						|
      end if;
 | 
						|
    end loop;
 | 
						|
  end lc;
 | 
						|
 | 
						|
  function lc(value: string) return string is
 | 
						|
    variable out_line: line;
 | 
						|
  begin
 | 
						|
    write(out_line, value);
 | 
						|
    lc(out_line);
 | 
						|
    return(out_line.all);
 | 
						|
  end lc;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- change to uppercase
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure uc(value: inout line) is
 | 
						|
    variable out_line: line;
 | 
						|
  begin
 | 
						|
    for index in value'range loop
 | 
						|
      if (value(index) >= 'a') and (value(index) <= 'z') then
 | 
						|
        value(index) := character'val(character'pos(value(index))
 | 
						|
                                    - character'pos('a')
 | 
						|
                                    + character'pos('A')
 | 
						|
                                      );
 | 
						|
      end if;
 | 
						|
    end loop;
 | 
						|
  end uc;
 | 
						|
 | 
						|
  function uc(value: string) return string is
 | 
						|
    variable out_line: line;
 | 
						|
  begin
 | 
						|
    write(out_line, value);
 | 
						|
    uc(out_line);
 | 
						|
    return(out_line.all);
 | 
						|
  end uc;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: padding and justifying
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function pad(
 | 
						|
    value           : string;
 | 
						|
    string_length   : natural;
 | 
						|
    fill_char       : character := ' ';
 | 
						|
    right_justify   : boolean := false
 | 
						|
  ) return string is
 | 
						|
    variable value_line : line;
 | 
						|
    variable out_line : line;
 | 
						|
    variable value_length : natural;
 | 
						|
    variable shift_sign : boolean;
 | 
						|
  begin
 | 
						|
    write(value_line, value);
 | 
						|
    value_length := value_line.all'length;
 | 
						|
    if string_length = 0 then
 | 
						|
      write(out_line, value_line.all);
 | 
						|
    elsif string_length > value_length then
 | 
						|
      if right_justify then
 | 
						|
        if (value_line.all(value_line.all'left) <= '-') and not(fill_char = ' ') then
 | 
						|
          shift_sign := true;
 | 
						|
          write(out_line, value_line.all(value_line.all'left));
 | 
						|
        end if;
 | 
						|
        for index in 1 to string_length-value_length loop
 | 
						|
          write(out_line, fill_char);
 | 
						|
        end loop;
 | 
						|
      end if;
 | 
						|
      if shift_sign then
 | 
						|
        write(out_line, value_line.all(value_line.all'left+1 to value_line.all'right));
 | 
						|
      else
 | 
						|
        write(out_line, value_line.all);
 | 
						|
      end if;
 | 
						|
      if not right_justify then
 | 
						|
        for index in 1 to string_length-value_length loop
 | 
						|
          write(out_line, fill_char);
 | 
						|
        end loop;
 | 
						|
      end if;
 | 
						|
    elsif string_length < value_length then
 | 
						|
      write(out_line, '#');
 | 
						|
      write(out_line, value_line.all(value_length-string_length+2 to value_length));
 | 
						|
    else
 | 
						|
      write(out_line, value_line.all);
 | 
						|
    end if;
 | 
						|
    deallocate(value_line);
 | 
						|
    return(out_line.all);
 | 
						|
  end pad;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- remove separator characters at beginning and end of line
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure rm_side_separators(
 | 
						|
    value : inout line;
 | 
						|
    separators : in string
 | 
						|
  ) is
 | 
						|
    variable input_line : line    := value;
 | 
						|
    variable found      : boolean := false;
 | 
						|
    variable position   : integer := 0;
 | 
						|
  begin
 | 
						|
    -- remove all separators in the beginning
 | 
						|
    position := -1;
 | 
						|
    for character_index in input_line'range loop
 | 
						|
      found := false;
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line(character_index) = separators(separator_index) then
 | 
						|
          found := true;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
      if found then
 | 
						|
          position := character_index;
 | 
						|
      else
 | 
						|
          exit;
 | 
						|
      end if;
 | 
						|
   end loop;
 | 
						|
   if position > -1 then
 | 
						|
     input_line := new string'( input_line(position+1 to input_line'right) );
 | 
						|
   end if;
 | 
						|
 | 
						|
   -- remove all separators in the end
 | 
						|
    position := -1;
 | 
						|
    for character_index in input_line'reverse_range loop
 | 
						|
      found := false;
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line(character_index) = separators(separator_index) then
 | 
						|
          found := true;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
      if found then
 | 
						|
          position := character_index;
 | 
						|
      else
 | 
						|
          exit;
 | 
						|
      end if;
 | 
						|
   end loop;
 | 
						|
   if position > -1 then
 | 
						|
     input_line := new string'( input_line(input_line'left to position-1) );
 | 
						|
   end if;
 | 
						|
 | 
						|
   value := input_line;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure rm_side_separators(value : inout line) is
 | 
						|
  begin
 | 
						|
    rm_side_separators(value, " :" & ht);
 | 
						|
  end;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- remove multiple occurences of separator characters, keeping one single
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure trim_line(
 | 
						|
    value : inout line;
 | 
						|
    separators : in string
 | 
						|
  ) is
 | 
						|
    variable input_line: line := value;
 | 
						|
    variable output_line: line := new string'("");
 | 
						|
    variable is_separator, was_separator : boolean := false;
 | 
						|
  begin
 | 
						|
    rm_side_separators(input_line);
 | 
						|
    for character_index in input_line'range loop
 | 
						|
      is_separator := false;
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line.all(character_index) = separators(separator_index) then
 | 
						|
          is_separator := true;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
      if not (is_separator and was_separator) then
 | 
						|
        write(output_line, input_line.all(character_index));
 | 
						|
      end if;
 | 
						|
      was_separator := is_separator;
 | 
						|
    end loop;
 | 
						|
 | 
						|
    value := output_line;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure trim_line(value : inout line) is
 | 
						|
  begin
 | 
						|
    trim_line(value, " :" & ht);
 | 
						|
  end;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- remove all occurences of separator characters
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure rm_all_separators(
 | 
						|
    value : inout line;
 | 
						|
    separators : in string
 | 
						|
  ) is
 | 
						|
    variable input_line   : line    := value;
 | 
						|
    variable is_separator : boolean := false;
 | 
						|
  begin
 | 
						|
 | 
						|
    -- remove separators from beginn and end of the line
 | 
						|
    -- rm_separator_be(value, separators);
 | 
						|
 | 
						|
    -- empty output line
 | 
						|
    value := new string'("");
 | 
						|
 | 
						|
    -- find all separator symbols
 | 
						|
    for character_index in input_line'range loop
 | 
						|
      is_separator := false;
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line(character_index) = separators(separator_index) then
 | 
						|
          is_separator := true;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
      if not is_separator then
 | 
						|
        write(value, input_line.all(character_index));
 | 
						|
      end if;
 | 
						|
    end loop;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure rm_all_separators(value : inout line) is
 | 
						|
  begin
 | 
						|
    rm_all_separators(value, " _." & ht);
 | 
						|
  end;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- read first "word" out of a line
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure read_first(
 | 
						|
    value : inout line;
 | 
						|
    separators : in string;
 | 
						|
    first : out line
 | 
						|
  ) is
 | 
						|
    variable input_line: line;
 | 
						|
    variable position: natural := 0;
 | 
						|
  begin
 | 
						|
    input_line := value;
 | 
						|
    for character_index in input_line.all'reverse_range loop
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line.all(character_index) = separators(separator_index) then
 | 
						|
          position := character_index;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
    end loop;
 | 
						|
    if position > 1 then
 | 
						|
      first := new string'(input_line.all(input_line'left to position-1));
 | 
						|
	    value := new string'(input_line(position+1 to input_line'right));
 | 
						|
    else
 | 
						|
      first := new string'(input_line.all);
 | 
						|
	    value := new string'("");
 | 
						|
    end if;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure read_first(value : inout line; first : out line) is
 | 
						|
  begin
 | 
						|
    read_first(value, " :" & ht, first);
 | 
						|
  end;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- read last "word" out of a line
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure read_last(
 | 
						|
    value : inout line;
 | 
						|
    separators : in string;
 | 
						|
    last : out line
 | 
						|
  ) is
 | 
						|
    variable input_line: line := value;
 | 
						|
    variable position: natural := 0;
 | 
						|
  begin
 | 
						|
    for character_index in input_line'range loop
 | 
						|
      for separator_index in separators'range loop
 | 
						|
        if input_line(character_index) = separators(separator_index) then
 | 
						|
          position := character_index;
 | 
						|
        end if;
 | 
						|
      end loop;
 | 
						|
    end loop;
 | 
						|
    if position <= input_line'right and
 | 
						|
       position >  0                then
 | 
						|
      value := new string'(input_line(input_line'left to position-1));
 | 
						|
      last  := new string'(input_line(position+1 to input_line'right));
 | 
						|
    else
 | 
						|
      last := new string'(input_line.all);
 | 
						|
    end if;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure read_last(value : inout line; last : out line) is
 | 
						|
  begin
 | 
						|
    read_last(value, " :" & ht, last);
 | 
						|
  end;
 | 
						|
 | 
						|
 | 
						|
  --============================================================================
 | 
						|
  -- formatted string output, internal functions
 | 
						|
  --
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- get format specification
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure get_format_items(
 | 
						|
    format          : string;
 | 
						|
    right_justify   : out boolean;
 | 
						|
    add_sign        : out boolean;
 | 
						|
    fill_char       : out character;
 | 
						|
    total_length    : out natural;
 | 
						|
    point_precision : out natural;
 | 
						|
    format_type     : inout line
 | 
						|
  ) is
 | 
						|
    variable find_sign : boolean := false;
 | 
						|
    variable find_padding : boolean := false;
 | 
						|
    variable find_length : boolean := false;
 | 
						|
    variable find_precision : boolean := false;
 | 
						|
    variable find_type : boolean := false;
 | 
						|
    variable right_justify_int : boolean := true;
 | 
						|
    variable total_length_int : natural := 0;
 | 
						|
    variable point_precision_int : natural := 0;
 | 
						|
  begin
 | 
						|
    add_sign := false;
 | 
						|
    fill_char := ' ';
 | 
						|
    for index in 1 to format'length loop
 | 
						|
      if find_type then
 | 
						|
        write(format_type, format(index));
 | 
						|
      end if;
 | 
						|
      if find_precision then
 | 
						|
        if (format(index) >= '0') and (format(index) <= '9') then
 | 
						|
          point_precision_int := 10*point_precision_int + character'pos(format(index)) - character'pos('0');
 | 
						|
          if format(index+1) >= 'A' then
 | 
						|
            find_precision := false;
 | 
						|
            find_type := true;
 | 
						|
          end if;
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
      if find_length then
 | 
						|
        if (format(index) >= '0') and (format(index) <= '9') then
 | 
						|
          total_length_int := 10*total_length_int + character'pos(format(index)) - character'pos('0');
 | 
						|
        end if;
 | 
						|
        if format(index) = '.' then
 | 
						|
          find_length := false;
 | 
						|
          find_precision := true;
 | 
						|
        elsif format(index+1) >= 'A' then
 | 
						|
          find_length := false;
 | 
						|
          find_type := true;
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
      if find_padding then
 | 
						|
        if format(index) = '0' then
 | 
						|
          if right_justify_int then
 | 
						|
            fill_char := '0';
 | 
						|
          end if;
 | 
						|
        end if;
 | 
						|
        find_padding := false;
 | 
						|
        if format(index+1) >= 'A' then
 | 
						|
          find_type := true;
 | 
						|
        else
 | 
						|
          find_length := true;
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
      if find_sign then
 | 
						|
        if format(index) = '-' then
 | 
						|
          right_justify_int := false;
 | 
						|
        end if;
 | 
						|
        if format(index) = '+' then
 | 
						|
          add_sign := true;
 | 
						|
        end if;
 | 
						|
        find_sign := false;
 | 
						|
        if format(index+1) <= '-' then
 | 
						|
          find_sign := true;
 | 
						|
        elsif format(index+1) = '0' then
 | 
						|
          find_padding := true;
 | 
						|
        elsif format(index+1) >= 'A' then
 | 
						|
          find_type := true;
 | 
						|
        else
 | 
						|
          find_length := true;
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
      if format(index) = '%' then
 | 
						|
        if format(index+1) <= '-' then
 | 
						|
          find_sign := true;
 | 
						|
        elsif format(index+1) = '0' then
 | 
						|
          find_padding := true;
 | 
						|
        elsif format(index+1) >= 'A' then
 | 
						|
          find_type := true;
 | 
						|
        else
 | 
						|
          find_length := true;
 | 
						|
        end if;
 | 
						|
      end if;
 | 
						|
    end loop;
 | 
						|
    right_justify := right_justify_int;
 | 
						|
    total_length := total_length_int;
 | 
						|
    point_precision := point_precision_int;
 | 
						|
  end get_format_items;
 | 
						|
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: converting std_ulogic to character
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function to_character(value: std_ulogic) return character is
 | 
						|
    variable out_value: character;
 | 
						|
  begin
 | 
						|
    case value is
 | 
						|
      when 'U' => out_value := 'U';
 | 
						|
      when 'X' => out_value := 'X';
 | 
						|
      when '0' => out_value := '0';
 | 
						|
      when '1' => out_value := '1';
 | 
						|
      when 'Z' => out_value := 'Z';
 | 
						|
      when 'W' => out_value := 'W';
 | 
						|
      when 'L' => out_value := 'L';
 | 
						|
      when 'H' => out_value := 'H';
 | 
						|
      when '-' => out_value := '-';
 | 
						|
    end case;
 | 
						|
    return(out_value);
 | 
						|
  end to_character;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: binary integer
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf_b(value: std_ulogic_vector) return string is
 | 
						|
    variable out_line : line;
 | 
						|
  begin
 | 
						|
    for index in value'range loop
 | 
						|
      write(out_line, to_character(value(index)));
 | 
						|
    end loop;
 | 
						|
    return(out_line.all);
 | 
						|
  end sprintf_b;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: decimal integer
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf_d(
 | 
						|
    right_justify   : boolean;
 | 
						|
    add_sign        : boolean;
 | 
						|
    fill_char       : character;
 | 
						|
    string_length   : natural;
 | 
						|
    value           : integer
 | 
						|
  ) return string is
 | 
						|
    variable value_line : line;
 | 
						|
  begin
 | 
						|
    if add_sign and (value >= 0) then
 | 
						|
      write(value_line, '+');
 | 
						|
    end if;
 | 
						|
    write(value_line, value);
 | 
						|
    if string_length = 0 then
 | 
						|
      return(value_line.all);
 | 
						|
    else
 | 
						|
      return(pad(value_line.all, string_length, fill_char, right_justify));
 | 
						|
    end if;
 | 
						|
  end sprintf_d;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: fixed point real
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf_f(
 | 
						|
    right_justify   : boolean;
 | 
						|
    add_sign        : boolean;
 | 
						|
    fill_char       : character;
 | 
						|
    string_length   : natural;
 | 
						|
    point_precision : natural;
 | 
						|
    value           : real
 | 
						|
  ) return string is
 | 
						|
    variable point_precision_int : natural;
 | 
						|
    variable integer_part : integer;
 | 
						|
    variable decimal_part : natural;
 | 
						|
    variable value_line : line;
 | 
						|
  begin
 | 
						|
    if point_precision = 0 then
 | 
						|
      point_precision_int := 6;
 | 
						|
    else
 | 
						|
      point_precision_int := point_precision;
 | 
						|
    end if;
 | 
						|
    if value >= 0.0 then
 | 
						|
      integer_part := integer(value-0.5);
 | 
						|
    else
 | 
						|
      integer_part := - integer(-value-0.5);
 | 
						|
    end if;
 | 
						|
    decimal_part := abs(integer((value-real(integer_part))*(10.0**point_precision_int)));
 | 
						|
    if add_sign and (value >= 0.0) then
 | 
						|
      write(value_line, '+');
 | 
						|
    end if;
 | 
						|
    write(value_line, integer_part);
 | 
						|
    write(value_line, '.');
 | 
						|
    write(value_line, sprintf_d(true, false, '0', point_precision_int, decimal_part));
 | 
						|
    if string_length = 0 then
 | 
						|
      return(value_line.all);
 | 
						|
    else
 | 
						|
      return(pad(value_line.all, string_length, fill_char, right_justify));
 | 
						|
    end if;
 | 
						|
  end sprintf_f;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- formatted string output: hexadecimal integer
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf_X(
 | 
						|
    extend_unsigned : boolean;
 | 
						|
    value           : std_ulogic_vector
 | 
						|
  ) return string is
 | 
						|
    variable bit_count : positive;
 | 
						|
    variable value_line : line;
 | 
						|
    variable out_line : line;
 | 
						|
    variable nibble: string(1 to 4);
 | 
						|
  begin
 | 
						|
    bit_count := value'length;
 | 
						|
    while (bit_count mod 4) /= 0 loop
 | 
						|
      if extend_unsigned then
 | 
						|
        write(value_line, to_character('0'));
 | 
						|
      else
 | 
						|
        write(value_line, to_character(value(value'high)));
 | 
						|
      end if;
 | 
						|
      bit_count := bit_count + 1;
 | 
						|
    end loop;
 | 
						|
    write(value_line, sprintf_b(value));
 | 
						|
    for index in value_line.all'range loop
 | 
						|
      if (index mod 4) = 0 then
 | 
						|
        nibble := value_line.all(index-3 to index);
 | 
						|
        case nibble is
 | 
						|
          when "0000" => write(out_line, 0);
 | 
						|
          when "0001" => write(out_line, 1);
 | 
						|
          when "0010" => write(out_line, 2);
 | 
						|
          when "0011" => write(out_line, 3);
 | 
						|
          when "0100" => write(out_line, 4);
 | 
						|
          when "0101" => write(out_line, 5);
 | 
						|
          when "0110" => write(out_line, 6);
 | 
						|
          when "0111" => write(out_line, 7);
 | 
						|
          when "1000" => write(out_line, 8);
 | 
						|
          when "1001" => write(out_line, 9);
 | 
						|
          when "1010" => write(out_line, 'A');
 | 
						|
          when "1011" => write(out_line, 'B');
 | 
						|
          when "1100" => write(out_line, 'C');
 | 
						|
          when "1101" => write(out_line, 'D');
 | 
						|
          when "1110" => write(out_line, 'E');
 | 
						|
          when "1111" => write(out_line, 'F');
 | 
						|
          when others => write(out_line, 'X');
 | 
						|
        end case;
 | 
						|
      end if;
 | 
						|
    end loop;
 | 
						|
    return(out_line.all);
 | 
						|
  end sprintf_X;
 | 
						|
 | 
						|
 | 
						|
  --============================================================================
 | 
						|
  -- formatted string output, interface functions
 | 
						|
  --
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- integer
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : integer) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if format_type.all = "b" then
 | 
						|
      if string_length = 0 then
 | 
						|
        string_length := 8;
 | 
						|
      end if;
 | 
						|
      return(sprintf_b(std_ulogic_vector(to_signed(value, string_length+1)(string_length-1 downto 0))));
 | 
						|
    elsif format_type.all = "d" then
 | 
						|
      return(sprintf_d(right_justify, add_sign, fill_char, string_length, value));
 | 
						|
    elsif format_type.all = "f" then
 | 
						|
      return(sprintf_f(right_justify, add_sign, fill_char,
 | 
						|
                       string_length, point_precision, real(value)));
 | 
						|
    elsif (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      if string_length = 0 then
 | 
						|
        string_length := 8;
 | 
						|
      end if;
 | 
						|
      string_length := 4*string_length;
 | 
						|
      if format_type.all = "X" then
 | 
						|
        return(sprintf_X(false, std_ulogic_vector(to_signed(value, string_length+1)(string_length-1 downto 0))));
 | 
						|
      else
 | 
						|
        return(lc(sprintf_X(false, std_ulogic_vector(to_signed(value, string_length+1)(string_length-1 downto 0)))));
 | 
						|
      end if;
 | 
						|
    else
 | 
						|
      return("Unhandled format type: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- real
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : real) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if (format_type.all = "d") or (point_precision = 0) then
 | 
						|
      return(sprintf_d(right_justify, add_sign, fill_char,
 | 
						|
                       string_length, integer(value)));
 | 
						|
    elsif format_type.all = "f" then
 | 
						|
      return(sprintf_f(right_justify, add_sign, fill_char,
 | 
						|
                       string_length, point_precision, value));
 | 
						|
    else
 | 
						|
      return("Unhandled format type: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- std_logic
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : std_logic) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
    variable logic_vector: std_logic_vector(1 to 1);
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if (format_type.all = "b") or (format_type.all = "d") or
 | 
						|
       (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      logic_vector(1) := value;
 | 
						|
      return(sprintf(format, std_ulogic_vector(logic_vector)));
 | 
						|
    else
 | 
						|
      return("Not a std_logic format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- std_ulogic_vector
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : std_ulogic_vector) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable bit_string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     bit_string_length, point_precision, format_type);
 | 
						|
    if format_type.all = "b" then
 | 
						|
      return(pad(sprintf_b(value), bit_string_length, fill_char, right_justify));
 | 
						|
    elsif format_type.all = "d" then
 | 
						|
      return(sprintf_d(right_justify, add_sign, fill_char, bit_string_length, to_integer(unsigned(value))));
 | 
						|
    elsif (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      if format_type.all = "X" then
 | 
						|
        return(pad(sprintf_X(true, value), bit_string_length, fill_char, right_justify));
 | 
						|
      else
 | 
						|
        return(lc(pad(sprintf_X(true, value), bit_string_length, fill_char, right_justify)));
 | 
						|
      end if;
 | 
						|
    else
 | 
						|
      return("Not a std_ulogic_vector format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- std_logic_vector
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : std_logic_vector) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if (format_type.all = "b") or (format_type.all = "d") or
 | 
						|
       (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      return(sprintf(format, std_ulogic_vector(value)));
 | 
						|
    else
 | 
						|
      return("Not a std_logic_vector format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- unsigned
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : unsigned) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if (format_type.all = "b") or (format_type.all = "d") or
 | 
						|
       (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      return(sprintf(format, std_ulogic_vector(value)));
 | 
						|
    else
 | 
						|
      return("Not an unsigned format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- signed
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : signed) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable bit_string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     bit_string_length, point_precision, format_type);
 | 
						|
    if (fill_char = '0') and (value(value'left) = '1') then
 | 
						|
      fill_char := '1';
 | 
						|
    end if;
 | 
						|
    if format_type.all = "b" then
 | 
						|
      return(pad(sprintf_b(std_ulogic_vector(value)), bit_string_length, fill_char, right_justify));
 | 
						|
    elsif format_type.all = "d" then
 | 
						|
      return(sprintf_d(right_justify, add_sign, fill_char, bit_string_length, to_integer(signed(value))));
 | 
						|
    elsif (format_type.all = "X") or (format_type.all = "x") then
 | 
						|
      if fill_char = '1' then
 | 
						|
        fill_char := 'F';
 | 
						|
      end if;
 | 
						|
      if format_type.all = "X" then
 | 
						|
        return(pad(sprintf_X(true, std_ulogic_vector(value)), bit_string_length, fill_char, right_justify));
 | 
						|
      else
 | 
						|
        return(lc(pad(sprintf_X(true, std_ulogic_vector(value)), bit_string_length, fill_char, right_justify)));
 | 
						|
      end if;
 | 
						|
    else
 | 
						|
      return("Not a signed format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- time
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sprintf(format : string; value : time) return string is
 | 
						|
    variable right_justify : boolean;
 | 
						|
    variable add_sign : boolean;
 | 
						|
    variable fill_char : character;
 | 
						|
    variable string_length : natural;
 | 
						|
    variable point_precision : natural;
 | 
						|
    variable format_type : line;
 | 
						|
    variable scaling : real;
 | 
						|
    variable base_time : time;
 | 
						|
    variable unit : string(1 to 3);
 | 
						|
  begin
 | 
						|
    get_format_items(format, right_justify, add_sign, fill_char,
 | 
						|
                     string_length, point_precision, format_type);
 | 
						|
    if format_type.all(format_type.all'left) = 't' then
 | 
						|
      scaling := 10.0**point_precision;
 | 
						|
      if format_type.all = "tp" then
 | 
						|
        base_time := 1 ps;
 | 
						|
        unit := " ps";
 | 
						|
      elsif format_type.all = "tn" then
 | 
						|
        base_time := 1 ns;
 | 
						|
        unit := " ns";
 | 
						|
      elsif format_type.all = "tu" then
 | 
						|
        base_time := 1 us;
 | 
						|
        unit := " us";
 | 
						|
      elsif format_type.all = "tm" then
 | 
						|
        base_time := 1 ms;
 | 
						|
        unit := " ms";
 | 
						|
      elsif format_type.all = "ts" then
 | 
						|
        base_time := 1 sec;
 | 
						|
        unit := " s.";
 | 
						|
      else
 | 
						|
        return("Undefined time format: '" & format_type.all & "'");
 | 
						|
      end if;
 | 
						|
      if point_precision = 0 then
 | 
						|
        return(sprintf_d(right_justify, add_sign, fill_char,
 | 
						|
                         string_length, value/base_time) & unit);
 | 
						|
      else
 | 
						|
        return(sprintf_f(right_justify, add_sign, fill_char, string_length,
 | 
						|
                         point_precision, real(scaling*value/base_time)/scaling) & unit);
 | 
						|
      end if;
 | 
						|
    else
 | 
						|
      return("Not a time format: '" & format_type.all & "'");
 | 
						|
    end if;
 | 
						|
  end sprintf;
 | 
						|
 | 
						|
 | 
						|
  --============================================================================
 | 
						|
  -- formatted string input
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- read a nibble out of a character
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sscanf(value : character) return natural is
 | 
						|
  begin
 | 
						|
    if (value >= '0') and (value <= '9') then
 | 
						|
      return(character'pos(value) - character'pos('0'));
 | 
						|
    elsif (value >= 'a') and (value <= 'f') then
 | 
						|
      return(character'pos(value) - character'pos('a') + 10);
 | 
						|
    elsif (value >= 'A') and (value <= 'F') then
 | 
						|
      return(character'pos(value) - character'pos('A') + 10);
 | 
						|
    else
 | 
						|
      return(0);
 | 
						|
    end if;
 | 
						|
  end sscanf;
 | 
						|
 | 
						|
  function sscanf(value : character) return nibbleUnsignedType is
 | 
						|
  begin
 | 
						|
    return(to_unsigned(sscanf(value), nibbleUnsignedType'length));
 | 
						|
  end sscanf;
 | 
						|
 | 
						|
  function sscanf(value : character) return nibbleUlogicType is
 | 
						|
    variable unsigned_value : nibbleUnsignedType;
 | 
						|
  begin
 | 
						|
    unsigned_value := sscanf(value);
 | 
						|
    return(std_ulogic_vector(unsigned_value));
 | 
						|
  end sscanf;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- read an binary word out of a string
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  function sscanf(value : string) return natural is
 | 
						|
    variable integer_value : natural;
 | 
						|
  begin
 | 
						|
    integer_value := 0;
 | 
						|
    for index in value'left to value'right loop
 | 
						|
      integer_value := integer_value*16 + sscanf(value(index));
 | 
						|
    end loop;
 | 
						|
    return(integer_value);
 | 
						|
  end;
 | 
						|
 | 
						|
  function sscanf(value : string) return unsigned is
 | 
						|
    variable unsigned_value : unsigned(4*value'length-1 downto 0);
 | 
						|
  begin
 | 
						|
    unsigned_value := to_unsigned(0,unsigned_value'length);
 | 
						|
    for index in value'left to value'right loop
 | 
						|
      unsigned_value := shift_left(unsigned_value,4) + to_unsigned(sscanf(value(index)),4);
 | 
						|
    end loop;
 | 
						|
    return(unsigned_value);
 | 
						|
  end;
 | 
						|
 | 
						|
  function sscanf(value : string) return std_ulogic_vector is
 | 
						|
    variable unsigned_value : unsigned(4*value'length-1 downto 0);
 | 
						|
  begin
 | 
						|
    unsigned_value := sscanf(value);
 | 
						|
    return(std_ulogic_vector(unsigned_value));
 | 
						|
  end;
 | 
						|
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  -- read time from a string
 | 
						|
  -- time can be formated as follows:
 | 
						|
  --   "1ps" or "1 ps" or " 1 ps " or " 1ps"
 | 
						|
  -- possible time units are: hr, min, sec, ms, us, ns, ps, fs
 | 
						|
  ------------------------------------------------------------------------------
 | 
						|
  procedure sscanf(
 | 
						|
     value    : inout line;
 | 
						|
     time_val : out time
 | 
						|
  ) is
 | 
						|
      variable time_line  : line := value;
 | 
						|
      variable time_base  : string(1 to 3);
 | 
						|
      variable time_value : integer;
 | 
						|
      variable time_int   : time;
 | 
						|
  begin
 | 
						|
    -- remove all spaces and tabs
 | 
						|
    rm_all_separators(time_line);
 | 
						|
 | 
						|
    -- strip time base (3 last characters)
 | 
						|
    time_base := time_line(time_line'right-2 to time_line'right);
 | 
						|
 | 
						|
    -- separate time value and base
 | 
						|
    if time_base(2 to 3) = "hr" then
 | 
						|
        time_int   := 1 hr;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    elsif time_base = "min" then
 | 
						|
        time_int   := 1 min;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -3));
 | 
						|
    elsif time_base = "sec" then
 | 
						|
        time_int   := 1 sec;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -3));
 | 
						|
    elsif time_base(2 to 3) = "ms" then
 | 
						|
        time_int   := 1 ms;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    elsif time_base(2 to 3) = "us" then
 | 
						|
        time_int   := 1 us;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    elsif time_base(2 to 3) = "ns" then
 | 
						|
        time_int   := 1 ns;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    elsif time_base(2 to 3) = "ps" then
 | 
						|
        time_int   := 1 ps;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    elsif time_base(2 to 3) = "fs" then
 | 
						|
        time_int   := 1 fs;
 | 
						|
        time_value := integer'value(time_line(time_line'left to time_line'right -2));
 | 
						|
    else
 | 
						|
        time_int   := 0 ps;
 | 
						|
        time_value := 1;
 | 
						|
    end if;
 | 
						|
 | 
						|
    -- build time from value and base
 | 
						|
    time_val := time_int * time_value;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
  function sscanf(value : string) return time is
 | 
						|
    variable value_line : line;
 | 
						|
    variable time_val   : time;
 | 
						|
  begin
 | 
						|
    value_line := new string'(value);
 | 
						|
    sscanf(value_line, time_val);
 | 
						|
    return(time_val);
 | 
						|
  end;
 | 
						|
 | 
						|
END testUtils;
 |