917 lines
28 KiB
VHDL
917 lines
28 KiB
VHDL
---- File: PCK_FIO.vhd
|
|
----
|
|
---- PCK_FIO: a VHDL package for C-style formatted file output
|
|
---- Copyright (C) 1995, 1999 Easics NV
|
|
----
|
|
---- This program is free software; you can redistribute it and/or modify
|
|
---- it under the terms of the GNU General Public License as published by
|
|
---- the Free Software Foundation; either version 1, or (at your option)
|
|
---- any later version.
|
|
----
|
|
---- This program is distributed in the hope that it will be useful,
|
|
---- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
---- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
---- GNU General Public License for more details.
|
|
----
|
|
---- You should have received a copy of the GNU General Public License
|
|
---- along with this program; if not, write to the Free Software
|
|
---- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
----
|
|
---- For suggestions, bug reports, enhancement requests, and info about
|
|
---- our design services, you can contact us at the following address:
|
|
---- Easics NV, Interleuvenlaan 86, B-3001 Leuven, Belgium
|
|
---- tel.: +32 16 395 600 fax : +32 16 395 619
|
|
---- e-mail: jand@easics.be (Jan Decaluwe)
|
|
----
|
|
----
|
|
---- Revision history:
|
|
----
|
|
---- $Source: /tmp/cvsroot/VHDL/lib/PCK_FIO-1.16/PCK_FIO.vhd,v $
|
|
---- $Revision: 1.1 $
|
|
---- $Log: not supported by cvs2svn $
|
|
---- Revision 1.16 1999/04/21 08:28:46 jand
|
|
---- Tested with IEEE.numeric_std
|
|
---- Small patch for Leapfrog
|
|
----
|
|
---- Revision 1.14 1997/07/14 10:16:04 jand
|
|
---- prefix/postfix for bits/bitvectors set to empty strings by default
|
|
----
|
|
---- Revision 1.13 1997/07/11 17:42:57 jand
|
|
---- Corrected Easics address
|
|
----
|
|
---- Revision 1.12 1997/07/11 17:38:49 jand
|
|
---- Improved prefix/postfix support
|
|
----
|
|
---- Revision 1.11 1995/11/15 13:46:02 jand
|
|
---- Catched integer'low value in fo for integers
|
|
----
|
|
---- Revision 1.10 1995/08/11 16:42:26 jand
|
|
---- Reimplemented FIO_FormatExpand as a procedure in an attempt to
|
|
---- avoid memory leakage problems in VSS
|
|
----
|
|
---- Revision 1.9 1995/08/09 13:47:51 jand
|
|
---- Removed array of line trick in fprint for less memory, less
|
|
---- CPU time, and more conservatism in general
|
|
---- Rearranged FIO_PrintValue call so that fprint remains concise
|
|
----
|
|
---- Revision 1.8 1995/08/09 10:32:27 jand
|
|
---- Removed fprint_flat to have a single call level
|
|
---- Added explicit deallocators of line variables (has strong influence
|
|
---- on memory usage in VSS - and possibly CPU time)
|
|
---- Redefined 'fo' for type time to make it more portable
|
|
----
|
|
---- Revision 1.7 1995/08/07 08:56:04 jand
|
|
---- Improved conciseness of fprint argument handling through array of line type
|
|
----
|
|
---- Revision 1.6 1995/08/04 18:19:13 jand
|
|
---- Increase # arguments from 16 to 32
|
|
---- Corrected bug within fprint 's call to Arg16
|
|
---- Added support for bit format specifier 'b'
|
|
----
|
|
---- Revision 1.5 1995/08/02 10:22:37 jand
|
|
---- Release 1.1 under GNU
|
|
----
|
|
---- Revision 1.4 1995/08/01 11:15:52 jand
|
|
---- Added escaping during iteration string read
|
|
----
|
|
---- Revision 1.3 1995/08/01 08:23:47 jand
|
|
---- Many improvements in robustness, conciseness and coding style
|
|
----
|
|
---- Revision 1.2 1995/07/30 16:15:43 jand
|
|
---- Improved robustness for release to the world
|
|
----
|
|
---- Revision 1.1 1995/07/30 14:21:30 jand
|
|
---- Initial revision
|
|
----
|
|
|
|
use STD.TEXTIO.all;
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
-- signed/unsigned definition: use either std_logic_arith or numeric_std
|
|
use IEEE.std_logic_arith.all; -- the Synopsys one
|
|
-- use IEEE.numeric_std.all;
|
|
|
|
package PCK_FIO is
|
|
|
|
-- prefix string for hex output
|
|
-- VHDL style: "X"""
|
|
-- Verilog style: "h'"
|
|
-- C style: "0x"
|
|
constant FIO_h_PRE: string := "0x";
|
|
|
|
-- postfix string for hex output
|
|
-- VHDL style: """"
|
|
constant FIO_h_POST: string := "";
|
|
|
|
-- prefix string for bit vector output
|
|
-- VHDL style: "B"""
|
|
-- Verilog style: "b'"
|
|
constant FIO_bv_PRE: string := "";
|
|
|
|
-- postfix string for bit vector output
|
|
-- VHDL style: """"
|
|
constant FIO_bv_POST: string := "";
|
|
|
|
-- prefix string for bit output
|
|
-- VHDL style: "'"
|
|
-- Verilog style: "b'"
|
|
constant FIO_b_PRE: string := "";
|
|
|
|
-- postfix string for bit output
|
|
-- VHDL style: "'"
|
|
constant FIO_b_POST: string := "";
|
|
|
|
-- digit width for the string representation of integers
|
|
constant FIO_d_WIDTH: integer := 10;
|
|
|
|
-- bit width for the string representation of integers
|
|
constant FIO_b_WIDTH: integer := 32;
|
|
|
|
-- definition of the NIL string (default value for fprint arguments)
|
|
-- fprint stops consuming arguments at the first NIL argument
|
|
constant FIO_NIL: string := "\";
|
|
|
|
procedure fprint
|
|
(F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 : in string := FIO_NIL;
|
|
A9 , A10, A11, A12, A13, A14, A15, A16: in string := FIO_NIL;
|
|
A17, A18, A19, A20, A21, A22, A23, A24: in string := FIO_NIL;
|
|
A25, A26, A27, A28, A29, A30, A31, A32: in string := FIO_NIL
|
|
);
|
|
|
|
function fo (Arg: unsigned) return string;
|
|
function fo (Arg: signed) return string;
|
|
function fo (Arg: std_logic_vector) return string;
|
|
function fo (Arg: std_ulogic_vector) return string;
|
|
function fo (Arg: bit_vector) return string;
|
|
function fo (Arg: integer) return string;
|
|
function fo (Arg: std_ulogic) return string;
|
|
function fo (Arg: bit) return string;
|
|
function fo (Arg: boolean) return string;
|
|
function fo (Arg: character) return string;
|
|
function fo (Arg: string) return string;
|
|
function fo (Arg: time) return string;
|
|
|
|
procedure FIO_FormatExpand (FMT: inout line;
|
|
Format: in string;
|
|
StartPointer: in positive);
|
|
|
|
end PCK_FIO;
|
|
|
|
|
|
package body PCK_FIO is
|
|
|
|
|
|
--------------------------
|
|
-- FIO Warnings support --
|
|
--------------------------
|
|
|
|
procedure FIO_Warning_Fsbla (F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
Pointer: in positive) is
|
|
begin
|
|
fprint (F, L, "\n** Warning: FIO_PrintLastValue: " &
|
|
"Format specifier beyond last argument\n");
|
|
fprint (F, L, "** in format string: ""%s""\n", Format);
|
|
fprint (F, L, "** ");
|
|
for i in 1 to Pointer-1 loop
|
|
fprint (F, L, "-");
|
|
end loop;
|
|
fprint (F, L, "^\n");
|
|
end FIO_Warning_Fsbla;
|
|
|
|
procedure FIO_Warning_Ufs (F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
Pointer: in positive;
|
|
Char: in character) is
|
|
begin
|
|
fprint (F, L, "\n** Warning: FIO_PrintArg: " &
|
|
"Unexpected format specifier '%r'\n",
|
|
fo(Char));
|
|
fprint (F, L, "** in format string: ""%s""\n", Format) ;
|
|
fprint (F, L, "** ");
|
|
for i in 1 to Pointer-1 loop
|
|
fprint (F, L, "-");
|
|
end loop;
|
|
fprint (F, L, "^\n** Assuming 'q' to proceed: ");
|
|
end FIO_Warning_Ufs;
|
|
|
|
|
|
----------------------------------
|
|
-- bit conversion support --
|
|
----------------------------------
|
|
|
|
type T_bit_map is array(bit) of character;
|
|
|
|
constant C_BIT_MAP: T_bit_map
|
|
:= ('0', '1');
|
|
|
|
----------------------------------
|
|
-- std_logic conversion support --
|
|
----------------------------------
|
|
|
|
type T_std_logic_map is array(std_ulogic) of character;
|
|
|
|
constant C_STD_LOGIC_MAP: T_std_logic_map
|
|
:= ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');
|
|
|
|
------------------------------
|
|
-- Digit conversion support --
|
|
------------------------------
|
|
|
|
-- types & constants
|
|
|
|
subtype S_digit_chars is character range '0' to '9';
|
|
subtype S_digits is integer range 0 to 9 ;
|
|
|
|
type T_digit_chars_map is array(S_digit_chars) of S_digits;
|
|
|
|
constant C_DIGIT_CHARS_MAP: T_digit_chars_map
|
|
:= (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
|
|
type T_digits_map is array(S_digits) of S_digit_chars;
|
|
|
|
constant C_DIGITS_MAP: T_digits_map
|
|
:= ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
|
|
|
|
|
|
--------------------------------
|
|
-- Decimal conversion support --
|
|
--------------------------------
|
|
|
|
function U_To_d (Arg: string) return integer is
|
|
constant Argument: string(Arg'length downto 1) := Arg;
|
|
variable Result: integer := 0;
|
|
begin
|
|
for i in Argument'range loop
|
|
case Argument(i) is when '1' => Result := 2**(i-1) + Result;
|
|
when '0' => null;
|
|
when others => return(-1);
|
|
end case;
|
|
end loop;
|
|
return (Result);
|
|
end U_To_d;
|
|
|
|
function S_To_d (Arg: string) return integer is
|
|
constant Argument: string(Arg'length downto 1) := Arg;
|
|
variable Result: integer := 0;
|
|
begin
|
|
case Argument(Argument'left) is
|
|
when '1' => Result := - 2**(Argument'left-1);
|
|
when '0' => Result := 0;
|
|
when others => return (integer'low);
|
|
end case;
|
|
for i in Argument'left-1 downto 1 loop
|
|
case Argument(i) is when '1' => Result := 2**(i-1) + Result;
|
|
when '0' => null;
|
|
when others => return(integer'low);
|
|
end case;
|
|
end loop;
|
|
return (Result);
|
|
end S_To_d;
|
|
|
|
function I_To_d (Arg: string(1 to FIO_d_WIDTH+1)) return integer is
|
|
constant Sign: character := Arg(1);
|
|
constant Value: string(Arg'length-1 downto 1) := Arg(2 to Arg'length);
|
|
variable Char: character;
|
|
variable Result: integer := 0;
|
|
begin
|
|
Result := 0;
|
|
for i in Value'range loop
|
|
Result := Result * 10;
|
|
Char := Value(i);
|
|
if (Char /= ' ') then
|
|
Result := Result + C_DIGIT_CHARS_MAP(Char);
|
|
end if;
|
|
end loop;
|
|
case Sign is when '-' => return(-Result);
|
|
when others => return(Result);
|
|
end case;
|
|
end I_To_d;
|
|
|
|
function B_To_d (Arg: string(1 to 1)) return integer is
|
|
begin
|
|
case Arg is when "1" => return(1);
|
|
when "0" => return(0);
|
|
when others => return(-1);
|
|
end case;
|
|
end B_To_d;
|
|
|
|
function L_To_d (Arg: string(1 to 1)) return integer is
|
|
begin
|
|
case Arg is when "T" => return(1);
|
|
when others => return(0);
|
|
end case;
|
|
end L_To_d;
|
|
|
|
|
|
|
|
----------------------------
|
|
-- Hex conversion support --
|
|
----------------------------
|
|
|
|
-- Constants & types
|
|
|
|
constant C_HEX_CHARS: string(1 to 17) := "0123456789ABCDEF?";
|
|
|
|
-- Function to return Hex index of a nibble
|
|
|
|
function U_To_h_Index(Arg: string(4 downto 1)) return integer is
|
|
variable Index: integer := 0;
|
|
begin
|
|
for i in Arg'range loop
|
|
case Arg(i) is when '1' => Index := 2**(i-1) + Index;
|
|
when '0' => null;
|
|
when others => return (17);
|
|
end case;
|
|
end loop;
|
|
return (Index+1);
|
|
end U_To_h_Index;
|
|
|
|
-- Hex conversion
|
|
|
|
function U_To_h (Arg: string) return string is
|
|
variable Result: string((Arg'length-1)/4 +1 downto 1);
|
|
variable ExtArg: string(Result'length*4 downto 1) := (others => '0');
|
|
begin
|
|
ExtArg(Arg'length downto 1) := Arg;
|
|
for i in Result'range loop
|
|
Result(i) := C_HEX_CHARS(U_To_h_Index( ExtArg(i*4 downto i*4 -3) ));
|
|
end loop;
|
|
return (FIO_h_PRE & Result & FIO_h_POST);
|
|
end U_To_h;
|
|
|
|
|
|
|
|
----------------------------
|
|
-- Bit conversion support --
|
|
----------------------------
|
|
|
|
function L_To_b (Arg: string(1 to 1)) return string is
|
|
variable Result: string(1 to 1);
|
|
begin
|
|
case Arg is when "T" => Result := "1";
|
|
when others => Result := "0";
|
|
end case;
|
|
return(FIO_b_PRE & Result & FIO_b_POST);
|
|
end L_To_b;
|
|
|
|
|
|
function I_To_b (Arg: string(1 to FIO_d_WIDTH+1);
|
|
Justified: side;
|
|
Width: integer) return string is
|
|
|
|
variable IntValue: integer := I_To_d(Arg);
|
|
variable BitValue: string(1 to FIO_b_WIDTH) := (others => ' ');
|
|
variable Sign: character := ' ';
|
|
constant Blanks: string(1 to FIO_b_WIDTH) := (others => ' ');
|
|
variable BitWidth: integer range 0 to FIO_b_WIDTH;
|
|
variable MsPos: integer range 1 to BitValue'length;
|
|
variable BitValueExtended: string(1 to 2*FIO_b_WIDTH);
|
|
|
|
begin
|
|
|
|
if (IntValue < 0) then
|
|
Sign := '-';
|
|
IntValue := -IntValue;
|
|
end if;
|
|
|
|
for i in BitValue'reverse_range loop
|
|
BitValue(i) := C_DIGITS_MAP(IntValue mod 2);
|
|
IntValue := IntValue / 2;
|
|
exit when (IntValue = 0);
|
|
end loop;
|
|
|
|
BitValueExtended := BitValue & Blanks;
|
|
|
|
if (Width = 0) or (Width > FIO_b_WIDTH+1) then
|
|
BitWidth := FIO_b_WIDTH;
|
|
else
|
|
BitWidth := Width-1;
|
|
end if;
|
|
|
|
if (Justified = RIGHT) then
|
|
return (FIO_bv_PRE &
|
|
Sign & BitValue(BitValue'length-BitWidth+1 to BitValue'length) &
|
|
FIO_bv_POST);
|
|
else
|
|
for i in BitValue'range loop
|
|
if BitValue(i) /= ' ' then
|
|
MSPos := i;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
return (FIO_bv_PRE &
|
|
Sign & BitValueExtended(MSPos to MSPos+BitWidth-1) &
|
|
FIO_bv_POST);
|
|
end if;
|
|
|
|
end I_To_b;
|
|
|
|
|
|
-----------------------------------
|
|
-- Reasonable conversion support --
|
|
-----------------------------------
|
|
|
|
function I_To_r (Arg: string(1 to FIO_d_WIDTH+1);
|
|
Justified: side;
|
|
Width: integer) return string is
|
|
constant Value: string(1 to FIO_d_WIDTH) := Arg(2 to FIO_d_WIDTH+1);
|
|
constant Sign: character := Arg(1);
|
|
constant Blanks: string(1 to FIO_d_WIDTH) := (others => ' ');
|
|
variable IntWidth: integer range 0 to FIO_d_WIDTH;
|
|
variable MsPos: integer range 1 to Value'length;
|
|
variable ValueExtended: string(1 to 2*FIO_d_WIDTH) := Value & Blanks;
|
|
begin
|
|
if (Width = 0) or (Width > FIO_d_WIDTH+1) then
|
|
IntWidth := FIO_d_WIDTH;
|
|
else
|
|
IntWidth := Width-1;
|
|
end if;
|
|
if (Justified = RIGHT) then
|
|
return (Sign & Value(Value'length-IntWidth+1 to Value'length));
|
|
else
|
|
for i in Value'range loop
|
|
if Value(i) /= ' ' then
|
|
MSPos := i;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
return (Sign & ValueExtended(MSPos to MSPos+IntWidth-1));
|
|
end if;
|
|
end I_To_r;
|
|
|
|
|
|
-------------------------------------------
|
|
-- Reasonable output conversion function --
|
|
-------------------------------------------
|
|
|
|
function ReasonableOutput (Arg: string;
|
|
Justified: side;
|
|
Width: integer) return string is
|
|
constant Argument: string(1 to Arg'length) := Arg;
|
|
constant TypeSpec: string (1 to 2) := Argument(1 to 2);
|
|
constant Value: string(1 to Arg'length-2) := Argument(3 to Arg'length);
|
|
begin
|
|
case TypeSpec is
|
|
when "U:" | "S:" | "V:" =>
|
|
return U_To_h(Value);
|
|
when "I:" =>
|
|
return I_To_r(Value, Justified, Width);
|
|
when "B:" | "L:" | "C:" =>
|
|
return Value;
|
|
when others =>
|
|
return Argument;
|
|
end case;
|
|
|
|
end ReasonableOutput;
|
|
|
|
|
|
------------------------------------
|
|
-- Bit output conversion function --
|
|
------------------------------------
|
|
|
|
function BitOutput (Arg: string;
|
|
Justified: side;
|
|
Width: integer) return string is
|
|
constant Argument: string(1 to Arg'length) := Arg;
|
|
constant TypeSpec: string (1 to 2) := Argument(1 to 2);
|
|
constant Value: string(1 to Arg'length-2) := Argument(3 to Arg'length);
|
|
begin
|
|
case TypeSpec is
|
|
when "U:" | "S:" | "V:" =>
|
|
return (FIO_bv_PRE & Value & FIO_bv_POST);
|
|
when "B:" =>
|
|
-- Value(1 to 1) instead of Value for LeapFrog
|
|
return (FIO_b_PRE & Value(1 to 1) & FIO_b_POST);
|
|
when "I:" =>
|
|
return I_To_b(Value, Justified, Width);
|
|
when "L:" =>
|
|
-- Value(1 to 1) instead of Value for LeapFrog
|
|
return L_To_b(Value(1 to 1));
|
|
when others =>
|
|
return Argument;
|
|
end case;
|
|
|
|
end BitOutput;
|
|
|
|
|
|
-------------------------------------------
|
|
-- Decimal output conversion function --
|
|
-------------------------------------------
|
|
|
|
function DecimalOutput (Arg: string) return integer is
|
|
constant Argument: string(1 to Arg'length) := Arg;
|
|
constant TypeSpec: string (1 to 2) := Argument(1 to 2);
|
|
constant Value: string(1 to Arg'length-2) := Argument(3 to Arg'length);
|
|
begin
|
|
case TypeSpec is
|
|
when "U:"| "V:" =>
|
|
return U_To_d(Value);
|
|
when "S:" =>
|
|
return S_To_d(Value);
|
|
when "I:" =>
|
|
return I_To_d(Value);
|
|
when "B:" =>
|
|
return B_To_d(Value);
|
|
when "L:" =>
|
|
return L_To_d(Value);
|
|
when others =>
|
|
return integer'low;
|
|
end case;
|
|
|
|
end DecimalOutput;
|
|
|
|
|
|
----------------------------
|
|
-- Atomic print functions --
|
|
----------------------------
|
|
|
|
function FIO_EOS (Format: in string;
|
|
Pointer: in integer)
|
|
return boolean is
|
|
begin
|
|
return (Pointer > Format'length);
|
|
end FIO_EOS;
|
|
|
|
|
|
-- Atomic value print function
|
|
|
|
procedure FIO_PrintValue (F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
Pointer: inout integer;
|
|
Last: in boolean := FALSE) is
|
|
variable Char: character;
|
|
begin
|
|
while (not FIO_EOS(Format, Pointer)) loop
|
|
Char := Format(Pointer);
|
|
case Char is
|
|
when '\' =>
|
|
Pointer := Pointer + 1;
|
|
exit when (FIO_EOS(Format, Pointer));
|
|
Char := Format(Pointer);
|
|
case Char is when 'n' => writeline(F, L);
|
|
when others => write(L, Char);
|
|
end case;
|
|
when '%' =>
|
|
if Last then
|
|
FIO_Warning_Fsbla(F, L, Format, Pointer);
|
|
end if;
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
when others =>
|
|
write(L, char);
|
|
end case;
|
|
Pointer := Pointer + 1;
|
|
end loop;
|
|
end FIO_PrintValue;
|
|
|
|
|
|
---- Atomic argument print function
|
|
|
|
procedure FIO_PrintArg (F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
Pointer: inout integer;
|
|
Arg: in string) is
|
|
variable Char: character;
|
|
variable Justified: side;
|
|
variable Width: integer;
|
|
begin
|
|
|
|
FIO_PrintValue(F, L, Format, Pointer);
|
|
|
|
Justified := RIGHT;
|
|
Width := 0;
|
|
while (not FIO_EOS(Format, Pointer)) loop
|
|
Char := Format(Pointer);
|
|
case Char is
|
|
when '-' =>
|
|
Justified := LEFT;
|
|
Pointer := Pointer + 1;
|
|
when '0' to '9' =>
|
|
Width := Width*10 + C_DIGIT_CHARS_MAP(Char);
|
|
Pointer := Pointer + 1;
|
|
when 'r' =>
|
|
write(L, ReasonableOutput(Arg, Justified, Width), Justified, Width);
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
when 'b' =>
|
|
write(L, BitOutput(Arg, Justified, Width), Justified, Width);
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
when 'd' =>
|
|
write(L, DecimalOutput(Arg), Justified, Width);
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
when 'q' | 's' =>
|
|
write(L, Arg, Justified, Width);
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
when others =>
|
|
FIO_Warning_Ufs(F, L, Format, Pointer, Char);
|
|
write(L, Arg, Justified, Width);
|
|
Pointer := Pointer + 1;
|
|
exit;
|
|
end case;
|
|
end loop;
|
|
end FIO_PrintArg;
|
|
|
|
|
|
-----------------------------------------------------
|
|
-- The format string iteration expansion procedure --
|
|
-----------------------------------------------------
|
|
|
|
procedure FIO_FormatExpand (FMT: inout line;
|
|
Format: in string;
|
|
StartPointer: in positive) is
|
|
|
|
variable Pointer: positive := StartPointer;
|
|
variable TokenStart: positive;
|
|
variable IterStringStart: positive;
|
|
variable IterStringEnd: positive;
|
|
variable IterCount: natural;
|
|
variable OpenBrackets: natural;
|
|
variable L: line;
|
|
|
|
begin
|
|
|
|
FORMAT_SEARCH: while not FIO_EOS(Format, Pointer) loop
|
|
|
|
case Format(Pointer) is
|
|
|
|
-- look for format specifier
|
|
when '%' =>
|
|
|
|
-- initialize iteration token search
|
|
TokenStart := Pointer;
|
|
IterCount := 0;
|
|
Pointer := Pointer + 1;
|
|
|
|
-- start iteration token search
|
|
TOKEN_READ: while not FIO_EOS(Format, Pointer) loop
|
|
|
|
case Format(Pointer) is
|
|
|
|
-- read iteration counter
|
|
when '0' to '9' =>
|
|
IterCount := IterCount*10 + C_DIGIT_CHARS_MAP(Format(Pointer));
|
|
Pointer := Pointer + 1;
|
|
|
|
-- expect open bracket
|
|
when '{' =>
|
|
|
|
-- initialize iteration string read
|
|
OpenBrackets := 1;
|
|
IterStringStart := Pointer + 1;
|
|
Pointer := Pointer + 1;
|
|
-- quit prematurely when iteration count is 0
|
|
next FORMAT_SEARCH when (IterCount = 0);
|
|
|
|
-- start iteration string read
|
|
ITER_STRING_READ: while not FIO_EOS(Format, Pointer) loop
|
|
|
|
case Format(Pointer) is
|
|
-- keep track of open brackets
|
|
when '{' =>
|
|
OpenBrackets := OpenBrackets + 1;
|
|
Pointer := Pointer + 1;
|
|
-- when closing bracket is found, process iteration string
|
|
when '}' =>
|
|
OpenBrackets := OpenBrackets - 1;
|
|
if (OpenBrackets = 0) then
|
|
IterStringEnd := Pointer-1;
|
|
if (TokenStart /= 1) then
|
|
write(L, Format(1 to TokenStart-1));
|
|
end if;
|
|
for i in 1 to IterCount loop
|
|
write(L, Format(IterStringStart to IterStringEnd));
|
|
end loop;
|
|
if (IterStringEnd /= Format'length) then
|
|
write(L, Format(IterStringEnd+2 to Format'length));
|
|
end if;
|
|
-- call expansion procedure recursively on expanded format
|
|
FIO_FormatExpand(FMT, L.all, TokenStart);
|
|
deallocate(L);
|
|
return;
|
|
end if;
|
|
Pointer := Pointer + 1;
|
|
-- skip escaped characters
|
|
when '\' =>
|
|
Pointer := Pointer + 2;
|
|
-- read iteration string
|
|
when others =>
|
|
Pointer := Pointer + 1;
|
|
|
|
end case;
|
|
|
|
end loop ITER_STRING_READ;
|
|
|
|
-- stop iteration token search when no opening bracket found
|
|
when others =>
|
|
Pointer := Pointer + 1;
|
|
next FORMAT_SEARCH;
|
|
|
|
end case;
|
|
|
|
end loop TOKEN_READ;
|
|
|
|
-- skip escaped characters
|
|
when '\' =>
|
|
Pointer := Pointer + 2;
|
|
|
|
-- read other characters
|
|
when others =>
|
|
Pointer := Pointer + 1;
|
|
|
|
end case;
|
|
|
|
end loop FORMAT_SEARCH;
|
|
|
|
write(FMT, Format);
|
|
deallocate(L);
|
|
|
|
end FIO_FormatExpand;
|
|
|
|
|
|
|
|
--------------------------
|
|
-- The fprint procedure --
|
|
--------------------------
|
|
|
|
procedure fprint
|
|
(F: out text;
|
|
L: inout line;
|
|
Format: in string;
|
|
A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 : in string := FIO_NIL;
|
|
A9 , A10, A11, A12, A13, A14, A15, A16: in string := FIO_NIL;
|
|
A17, A18, A19, A20, A21, A22, A23, A24: in string := FIO_NIL;
|
|
A25, A26, A27, A28, A29, A30, A31, A32: in string := FIO_NIL
|
|
) is
|
|
|
|
variable Pointer: integer;
|
|
variable FMT: line;
|
|
|
|
begin
|
|
|
|
Pointer := 1;
|
|
|
|
FIO_FormatExpand (FMT, Format, Format'low);
|
|
|
|
if (A1 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A1 );
|
|
if (A2 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A2 );
|
|
if (A3 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A3 );
|
|
if (A4 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A4 );
|
|
if (A5 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A5 );
|
|
if (A6 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A6 );
|
|
if (A7 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A7 );
|
|
if (A8 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A8 );
|
|
if (A9 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A9 );
|
|
if (A10 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A10);
|
|
if (A11 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A11);
|
|
if (A12 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A12);
|
|
if (A13 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A13);
|
|
if (A14 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A14);
|
|
if (A15 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A15);
|
|
if (A16 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A16);
|
|
if (A17 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A17);
|
|
if (A18 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A18);
|
|
if (A19 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A19);
|
|
if (A20 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A20);
|
|
if (A21 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A21);
|
|
if (A22 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A22);
|
|
if (A23 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A23);
|
|
if (A24 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A24);
|
|
if (A25 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A25);
|
|
if (A26 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A26);
|
|
if (A27 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A27);
|
|
if (A28 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A28);
|
|
if (A29 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A29);
|
|
if (A30 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A30);
|
|
if (A31 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A31);
|
|
if (A32 /= FIO_NIL) then FIO_PrintArg(F, L, FMT.all, Pointer, A32);
|
|
end if; end if; end if; end if; end if; end if; end if; end if;
|
|
end if; end if; end if; end if; end if; end if; end if; end if;
|
|
end if; end if; end if; end if; end if; end if; end if; end if;
|
|
end if; end if; end if; end if; end if; end if; end if; end if;
|
|
|
|
FIO_PrintValue(F, L, FMT.all, Pointer, Last => TRUE);
|
|
|
|
deallocate(FMT);
|
|
|
|
end fprint;
|
|
|
|
|
|
-------------------------------------------
|
|
-- Formatted output conversion functions --
|
|
-------------------------------------------
|
|
|
|
function fo (Arg: unsigned) return string is
|
|
constant Argument: unsigned(1 to Arg'length) := Arg;
|
|
variable Result: string(1 to Arg'length);
|
|
begin
|
|
for i in Argument'range loop
|
|
Result(i) := C_STD_LOGIC_MAP(Argument(i));
|
|
end loop;
|
|
return ("U:" & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: signed) return string is
|
|
constant Argument: signed(1 to Arg'length) := Arg;
|
|
variable Result: string(1 to Arg'length);
|
|
begin
|
|
for i in Argument'range loop
|
|
Result(i) := C_STD_LOGIC_MAP(Argument(i));
|
|
end loop;
|
|
return ("S:" & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: std_logic_vector) return string is
|
|
constant Argument: std_logic_vector(1 to Arg'length) := Arg;
|
|
variable Result: string(1 to Arg'length);
|
|
begin
|
|
for i in Argument'range loop
|
|
Result(i) := C_STD_LOGIC_MAP(Argument(i));
|
|
end loop;
|
|
return ("V:" & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: std_ulogic_vector) return string is
|
|
constant Argument: std_ulogic_vector(1 to Arg'length) := Arg;
|
|
variable Result: string(1 to Arg'length);
|
|
begin
|
|
for i in Argument'range loop
|
|
Result(i) := C_STD_LOGIC_MAP(Argument(i));
|
|
end loop;
|
|
return ("V:" & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: bit_vector) return string is
|
|
constant Argument: bit_vector(1 to Arg'length) := Arg;
|
|
variable Result: string(1 to Arg'length);
|
|
begin
|
|
for i in Argument'range loop
|
|
Result(i) := C_BIT_MAP(Argument(i));
|
|
end loop;
|
|
return ("V:" & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: integer) return string is
|
|
variable Argument: integer := Arg;
|
|
variable Result: string(1 to FIO_d_WIDTH) := (others => ' ');
|
|
variable Sign: character := ' ';
|
|
begin
|
|
if (Argument < 0) and (Argument /= integer'low) then
|
|
Sign := '-';
|
|
Argument := -Argument;
|
|
end if;
|
|
for i in Result'reverse_range loop
|
|
Result(i) := C_DIGITS_MAP(Argument mod 10);
|
|
Argument := Argument / 10;
|
|
exit when (Argument = 0);
|
|
end loop;
|
|
return ("I:" & Sign & Result);
|
|
end fo;
|
|
|
|
function fo (Arg: std_ulogic) return string is
|
|
begin
|
|
return ("B:" & C_STD_LOGIC_MAP(Arg));
|
|
end fo;
|
|
|
|
function fo (Arg: bit) return string is
|
|
begin
|
|
return ("B:" & C_BIT_MAP(Arg));
|
|
end fo;
|
|
|
|
function fo (Arg: boolean) return string is
|
|
begin
|
|
if (ARG = TRUE) then
|
|
return ("L:T");
|
|
else
|
|
return ("L:F");
|
|
end if;
|
|
end fo;
|
|
|
|
function fo (Arg: character) return string is
|
|
begin
|
|
return ("C:" & Arg);
|
|
end fo;
|
|
|
|
function fo (Arg: string) return string is
|
|
begin
|
|
return Arg;
|
|
end fo;
|
|
|
|
function fo (Arg: time) return string is
|
|
begin
|
|
return fo (integer (Arg / 1 ns));
|
|
end fo;
|
|
|
|
end PCK_FIO;
|