##// END OF EJS Templates
temp
temp

File last commit:

r100:fc97c34d69e3 martin
r249:279a122aaba5 JC
Show More
testlib.vhd
802 lines | 31.0 KiB | text/x-vhdl | VhdlLexer
------------------------------------------------------------------------------
-- This file is a part of the GRLIB VHDL IP LIBRARY
-- Copyright (C) 2003 - 2008, Gaisler Research
-- Copyright (C) 2008 - 2010, Aeroflex Gaisler
--
-- 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-----------------------------------------------------------------------------
-- package: testlib
-- file: testlib.vhd
-- author: Marko Isomaki - Aeroflex Gaisler
-- description: package for common vhdl functions for testbenches
------------------------------------------------------------------------------
library std;
use std.standard.all;
use std.textio.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library grlib;
use grlib.stdio.all;
use grlib.stdlib.tost;
package testlib is
type octet_vector is array (natural range <>) of std_logic_vector(7 downto 0);
subtype data_vector8 is octet_vector;
type data_vector16 is array (natural range <>) of std_logic_vector(15 downto 0);
type data_vector32 is array (natural range <>) of std_logic_vector(31 downto 0);
type data_vector64 is array (natural range <>) of std_logic_vector(63 downto 0);
type data_vector128 is array (natural range <>) of std_logic_vector(127 downto 0);
type data_vector256 is array (natural range <>) of std_logic_vector(255 downto 0);
type nibble_vector is array (natural range <>) of std_logic_vector(3 downto 0);
subtype data_vector is data_vector32;
-----------------------------------------------------------------------------
-- compare function handling '-'. c is the expected data parameter. If it is
--'-' or 'U' then this bit is not compared. Returns true if the vectors match
-----------------------------------------------------------------------------
function compare(o, c: in std_logic_vector) return boolean;
-----------------------------------------------------------------------------
-- compare function handling '-'
-----------------------------------------------------------------------------
function compare(o, c: in std_ulogic_vector) return boolean;
-----------------------------------------------------------------------------
-- this procedure prints a message to standard output. Also includes the time
-- at which it occurs.
-----------------------------------------------------------------------------
procedure print(
constant comment: in string := "-";
constant severe: in severity_level := note;
constant screen: in boolean := true);
-----------------------------------------------------------------------------
-- synchronisation with respect to clock and with output offset
-----------------------------------------------------------------------------
procedure synchronise(
signal clock: in std_ulogic;
constant offset: in time := 5 ns;
constant enable: in boolean := true);
-----------------------------------------------------------------------------
-- this procedure initialises the test error counters. Used in testbenches
-- with a test variable to check if a subtest has failed and at the end how
-- many subtests have failed. This procedure is called before the first
-- subtest
-----------------------------------------------------------------------------
procedure tinitialise(
variable test: inout boolean;
variable testcount: inout integer);
-----------------------------------------------------------------------------
-- this procedure completes the sub-test. Called at the end of each subtest
-----------------------------------------------------------------------------
procedure tintermediate(
variable test: inout boolean;
variable testcount: inout integer);
-----------------------------------------------------------------------------
-- this procedure completes the test. Called at the end of the complete test
-----------------------------------------------------------------------------
procedure tterminate(
variable test: inout boolean;
variable testcount: inout integer);
-----------------------------------------------------------------------------
-- check std_logic_vector array
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_logic_vector;
constant expected: in std_logic_vector;
constant message: in string := "");
-----------------------------------------------------------------------------
-- check std_logic
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_logic;
constant expected: in std_logic;
constant message: in string := "");
-----------------------------------------------------------------------------
-- check std_ulogic_vector array
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_ulogic_vector;
constant expected: in std_ulogic_vector;
constant message: in string := "");
-----------------------------------------------------------------------------
-- check natural
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in natural;
constant expected: in natural;
constant message: in string := "");
-----------------------------------------------------------------------------
-- check time
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in time;
constant expected: in time;
constant spread: in time;
constant message: in string := "");
-----------------------------------------------------------------------------
-- check boolean
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in boolean;
constant expected: in boolean;
constant message: in string := "");
-----------------------------------------------------------------------------
-- Convert Data_Vector to Octet_Vector
-----------------------------------------------------------------------------
function conv_octet_vector(
constant d: in data_vector)
return octet_vector;
-----------------------------------------------------------------------------
-- Convert Octet_Vector to Data_Vector, with padding
-----------------------------------------------------------------------------
function conv_data_vector(
constant o: in octet_vector)
return data_vector;
procedure compare(
constant data: in octet_vector;
constant cxdata: in octet_vector;
variable tP: inout boolean);
----------------------------------------------------------------------------
-- Read file contents to octet vector
----------------------------------------------------------------------------
--Expects data only in hex with four bytes on each line.
procedure readfile(
constant filename: in string := "";
constant filetype: in integer := 0;
constant size: in integer := 0;
variable dataout: out octet_vector);
--Reads bytes from a file with the format packets are output from ethereal
procedure readfile(
constant filename: in string := "";
constant size: in integer := 0;
variable dataout: out octet_vector);
----------------------------------------------------------------------------
-- Read file contents to data_vector
----------------------------------------------------------------------------
--Expects data only in hex with four bytes on each line.
procedure readfile(
constant filename: in string := "";
constant size: in integer := 0;
variable dataout: out data_vector);
--generates an random integer from 0 to the maximum value specified with max
procedure gen_rand_int(
constant max : in real;
variable seed1 : inout positive;
variable seed2 : inout positive;
variable rand : out integer);
--reverses std_logic_vector
function reverse(din : std_logic_vector) return std_logic_vector;
-- Returns offset to start of valid data for an access of size 'size' in
-- AMBA data vector
function ahb_doff (
constant dw : integer;
constant size : integer; -- access size
constant addr : std_logic_vector(4 downto 0))
return integer;
end package testlib;
--============================================================================--
package body testlib is
-----------------------------------------------------------------------------
-- compare function handling '-'
-----------------------------------------------------------------------------
function compare(o, c: in std_logic_vector) return boolean is
variable t: std_logic_vector(o'range) := c;
variable result: boolean;
begin
result := true;
for i in o'range loop
if not (o(i)=t(i) or t(i)='-' or t(i)='U') then
result := false;
end if;
end loop;
return result;
end function compare;
-----------------------------------------------------------------------------
-- compare function handling '-'
-----------------------------------------------------------------------------
function compare(o, c: in std_ulogic_vector) return boolean is
variable t: std_ulogic_vector(o'range) := c;
variable result: boolean;
begin
result := true;
for i in o'range loop
if not (o(i)=t(i) or t(i)='-' or t(i)='U') then
result := false;
end if;
end loop;
return result;
end function compare;
-----------------------------------------------------------------------------
-- this procedure prints a message to standard output
-----------------------------------------------------------------------------
procedure print(
constant comment: in string := "-";
constant severe: in severity_level := note;
constant screen: in boolean := true) is
variable l: line;
begin
if screen then
write(l, now, right, 15);
write(l, " : " & comment);
if severe = warning then
write(l, string'(" # warning, "));
elsif severe = error then
write(l, string'(" # error, "));
elsif severe = failure then
write(l, string'(" # failure, "));
end if;
writeline(output, l);
end if;
end procedure print;
-----------------------------------------------------------------------------
-- synchronisation with respect to clock and with output offset
-----------------------------------------------------------------------------
procedure synchronise(
signal clock: in std_ulogic;
constant offset: in time := 5 ns;
constant enable: in boolean := true) is
begin
if enable then
wait until clock = '1'; -- synchronise
wait for offset; -- output offset delay
end if;
end procedure synchronise;
-----------------------------------------------------------------------------
-- this procedure initialises the test error counters
-----------------------------------------------------------------------------
procedure tinitialise(
variable test: inout boolean;
variable testcount: inout integer) is
begin
--------------------------------------------------------------------------
-- initialise test status
--------------------------------------------------------------------------
test := true; -- reset any errors
testcount := 0;
print("--=========================================================--");
print("*** test initialised � ***");
print("--=========================================================--");
end procedure tinitialise;
-----------------------------------------------------------------------------
-- this procedure completes the sub-test
-----------------------------------------------------------------------------
procedure tintermediate(
variable test: inout boolean;
variable testcount: inout integer) is
variable l: line;
begin
--------------------------------------------------------------------------
-- report test status
--------------------------------------------------------------------------
wait for 10 us;
print("--=========================================================--");
if test then
print("*** sub-test completed successfully ***");
if testcount > 0 then
write(l, now, right, 15);
write(l, string'(" : "));
write(l, testcount);
write(l, string'(" sub-test(s) ended with one or more errors."));
writeline(output, l);
end if;
else
print("*** sub-test completed with errors -- # error # -- ***");
testcount := testcount + 1;
test := true;
if testcount > 0 then
write(l, now, right, 15);
write(l, string'(" : "));
write(l, testcount);
write(l, string'(" sub-test(s) ended with one or more errors."));
writeline(output, l);
end if;
end if;
print("--=========================================================--");
end procedure tintermediate;
-----------------------------------------------------------------------------
-- this procedure completes the test
-----------------------------------------------------------------------------
procedure tterminate(
variable test: inout boolean;
variable testcount: inout integer) is
variable l: line;
begin
--------------------------------------------------------------------------
-- end of test
--------------------------------------------------------------------------
wait for 1 ms;
print("--=========================================================--");
if testcount = 0 then
print("*** test completed successfully ***");
else
print("*** test completed with errors -- # error # -- ***");
write(l, now, right, 15);
write(l, string'(" : "));
write(l, testcount);
write(l, string'(" sub-test(s) ended with one or more errors."));
writeline(output, l);
end if;
print("--=========================================================--");
report "---- end of test ----"
severity failure;
wait;
end procedure tterminate;
-----------------------------------------------------------------------------
-- check std_logic_vector array
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_logic_vector;
constant expected: in std_logic_vector;
constant message: in string := "") is
variable l: line;
constant padding: std_logic_vector(1 to
(4-(received'length mod 4))) :=
(others => '0');
begin
if not compare(received, expected) then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
if padding'length > 0 and padding'length < 4 then
hwrite(l, padding & std_logic_vector(received));
else
hwrite(l, std_logic_vector(received));
end if;
write(l, string'(" expected: "));
if padding'length > 0 and padding'length < 4 then
hwrite(l, padding & std_logic_vector(expected));
else
hwrite(l, std_logic_vector(expected));
end if;
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- check std_logic
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_logic;
constant expected: in std_logic;
constant message: in string := "") is
variable l: line;
begin
if not (to_x01z(received)=to_x01z(expected)) then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
write(l, received);
write(l, string'(" expected: "));
write(l, expected);
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- check std_ulogic_vector array
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in std_ulogic_vector;
constant expected: in std_ulogic_vector;
constant message: in string := "") is
variable l: line;
constant padding: std_ulogic_vector(1 to
(4-(received'length mod 4))) :=
(others => '0');
begin
if not compare(received, expected) then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
if padding'length > 0 and padding'length < 4 then
hwrite(l, std_logic_vector(padding) & std_logic_vector(received));
else
hwrite(l, std_logic_vector(received));
end if;
write(l, string'(" expected: "));
if padding'length > 0 and padding'length < 4 then
hwrite(l, std_logic_vector(padding) & std_logic_vector(expected));
else
hwrite(l, std_logic_vector(expected));
end if;
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- check natural
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in natural;
constant expected: in natural;
constant message: in string := "") is
variable l: line;
begin
if received /= expected then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
write(l, received);
write(l, string'(" expected: "));
write(l, expected);
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- check time
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in time;
constant expected: in time;
constant spread: in time;
constant message: in string := "") is
variable l: line;
begin
if (received > expected+spread) or
(received < expected-spread) then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
write(l, received);
write(l, string'(" expected: "));
write(l, expected);
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- check boolean
-----------------------------------------------------------------------------
procedure check(
variable tp: inout boolean;
constant received: in boolean;
constant expected: in boolean;
constant message: in string := "") is
variable l: line;
begin
if received /= expected then
write(l, now, right, 15);
write(l, string'(" : ") & message & string'(" :"));
write(l, string'(" received: "));
write(l, received);
write(l, string'(" expected: "));
write(l, expected);
write(l, string'(" # error"));
writeline(output, l);
tp := false;
end if;
end procedure check;
-----------------------------------------------------------------------------
-- Convert Data_Vector to Octet_Vector
-----------------------------------------------------------------------------
function conv_octet_vector(
constant d: in data_vector)
return octet_vector is
variable o: octet_vector(0 to d'Length*4-1);
begin
for i in o'range loop
o(i) := d(i/4)((3-(i mod 4))*8+7 downto (3-(i mod 4))*8);
end loop;
return o;
end function conv_octet_vector;
-----------------------------------------------------------------------------
-- Convert Octet_Vector to Data_Vector, with padding
-----------------------------------------------------------------------------
function conv_data_vector(
constant o: in octet_vector)
return data_vector is
variable d: data_vector(0 to (1+(o'Length-1)/4)-1);
begin
for i in o'Range loop
d(i/4)((3-(i mod 4))*8+7 downto (3-(i mod 4))*8) := o(i);
end loop;
return d;
end function conv_data_vector;
procedure compare(
constant data: in octet_vector;
constant cxdata: in octet_vector;
variable tp: inout boolean) is
begin
if (data'length /= cxdata'length) then
tp := false;
print("compare error: lengths do not match");
else
for i in data'low to data'low+data'length-1 loop
if not compare(data(i), cxdata(i)) then
tp := false;
print("compare error. index: " & tost(i) & " data: " & tost(data(i)) & " expected: " & tost(cxdata(i)));
end if;
end loop;
end if;
end compare;
function FromChar(C: Character) return Std_Logic_Vector is
variable R: Std_Logic_Vector(0 to 3);
begin
case C is
when '0' => R := "0000";
when '1' => R := "0001";
when '2' => R := "0010";
when '3' => R := "0011";
when '4' => R := "0100";
when '5' => R := "0101";
when '6' => R := "0110";
when '7' => R := "0111";
when '8' => R := "1000";
when '9' => R := "1001";
when 'A' => R := "1010";
when 'B' => R := "1011";
when 'C' => R := "1100";
when 'D' => R := "1101";
when 'E' => R := "1110";
when 'F' => R := "1111";
when 'a' => R := "1010";
when 'b' => R := "1011";
when 'c' => R := "1100";
when 'd' => R := "1101";
when 'e' => R := "1110";
when 'f' => R := "1111";
when others => R := "XXXX";
end case;
return R;
end FromChar;
procedure readfile(
constant filename: in string := "";
constant filetype: in integer := 0;
constant size: in integer := 0;
variable dataout: out octet_vector) is
file readfile: text;
variable l: line;
variable test: boolean := true;
variable count: integer := 0;
variable dtmp: std_logic_vector(31 downto 0);
variable data: octet_vector(0 to size-1);
variable i: integer := 0;
variable good: boolean := true;
variable c: character;
begin
if size /= 0 then
if filename = "" then
print("no file given");
else
if filetype = 0 then
file_open(readfile, filename, read_mode);
while not endfile(readfile) loop
readline(readfile, l);
hread(l, dtmp, test);
if (not test) then
print("illegal data in file");
exit;
end if;
for i in 0 to 3 loop
data(count) := dtmp(31-i*8 downto 24-i*8);
count := count + 1;
if count >= size then
exit;
end if;
end loop;
if count >= size then
exit;
end if;
end loop;
if count < size then
print("not enough data in file");
else
for i in 0 to size-1 loop
dataout(dataout'low+i) := data(i);
end loop;
end if;
else
file_open(readfile, filename, read_mode);
while not endfile(readfile) loop
readline(readfile, L);
while (i < 4) loop
Read(L, C, good);
if not good then
Print("Error in read data");
exit;
end if;
if (C = character'val(32)) or (C = character'val(160)) or (C = HT) then
next;
else
i := i + 1;
end if;
end loop;
i := 0;
while (i < 32) loop
Read(L, C, good);
if not good then
Print("Error in read data");
exit;
end if;
if (C = character'val(32)) or (C = character'val(160)) or (C = HT) then
next;
else
if (i mod 2) = 0 then
data(count)(7 downto 4) := fromchar(C);
else
data(count)(3 downto 0) := fromchar(C);
-- Print(tost(data(count)));
count := count + 1;
if count >= size then
exit;
end if;
end if;
i := i + 1;
end if;
end loop;
i := 0;
end loop;
if count < size then
Print("Not enough data in file");
else
dataout := data;
end if;
end if;
end if;
else
print("size is zero. no data read");
end if;
end procedure;
procedure readfile(
constant filename: in string := "";
constant size: in integer := 0;
variable dataout: out octet_vector) is
begin
readfile(filename, 0, size, dataout);
end procedure;
procedure readfile(
constant filename: in string := "";
constant size: in integer := 0;
variable dataout: out data_vector) is
file readfile: text;
variable l: line;
variable test: boolean := true;
variable count: integer := 0;
variable data: data_vector(0 to size/4);
begin
if size /= 0 then
if filename = "" then
print("no file given");
else
file_open(readfile, filename, read_mode);
while not endfile(readfile) loop
readline(readfile, l);
hread(l, data(count/4), test);
if (not test) then
print("illegal data in file");
exit;
end if;
count := count + 4;
if count >= size then
exit;
end if;
end loop;
if count < size then
print("not enough data in file");
else
if (size mod 4) = 0 then
dataout(dataout'low to dataout'low+data'high-1) :=
data(0 to data'high-1);
else
dataout(dataout'low to dataout'low+data'high) := data(0 to data'high);
end if;
end if;
end if;
else
print("size is zero. no data read");
end if;
end procedure;
procedure gen_rand_int(
constant max : in real;
variable seed1 : inout positive;
variable seed2 : inout positive;
variable rand : out integer) is
variable rand_tmp : real;
begin
uniform(seed1, seed2, rand_tmp);
rand := integer(floor(rand_tmp*max));
end procedure;
function reverse(din : std_logic_vector)
return std_logic_vector is
variable dout: std_logic_vector(din'REVERSE_RANGE);
begin
for i in din'RANGE loop dout(i) := din(i); end loop;
return dout;
end function reverse;
function ahb_doff (
constant dw : integer;
constant size : integer;
constant addr : std_logic_vector(4 downto 0))
return integer is
variable off : integer;
begin -- ahb_doff
if size < 256 and dw = 256 and addr(4) = '0' then off := 128; else off := 0; end if;
if size < 128 and dw >= 128 and addr(3) = '0' then off := off + 64; end if;
if size < 64 and dw >= 64 and addr(2) = '0' then off := off + 32; end if;
if size < 32 and addr(1) = '0' then off := off + 16; end if;
if size < 16 and addr(0) = '0' then off := off + 8; end if;
return off;
end ahb_doff;
end package body ; --=======================================--