Open Source VHDL Verification Methodology/Пример использования OS-VVM/Пример 2
Материал из Wiki
Проект OS-VVM
Исходные коды
- Пример использования OS-VVM
- Пример 2 (Интеллектуальный ТБ)
Презентации
Coverage
Содержание |
Листинги 1
-- Для покрытия всех пар состояний требуется 1615 циклов -- покрытие A достигается за 103 циклов -- покрытие B достикается за 68 циклов
Листинг файла testbench(tb1)
Файл: tstb_tb1.vhd |
-- Для покрытия всех пар состояний требуется 1615 циклов -- покрытие A достигается за 103 циклов -- покрытие B достикается за 68 циклов library ieee; use ieee.std_logic_1164.all; use ieee.math_real.all; use ieee.numeric_std.all; use work.RandomPkg.all; use work.CoveragePkg.all; entity testbench is end; architecture tb1 of testbench is component sxema port (a, b : in std_logic_vector (4 downto 1); d : out std_logic_vector (8 downto 1)); end component; signal a, b : std_logic_vector (4 downto 1); signal d : std_logic_vector (8 downto 1); shared variable CovA, CovB : CovPType; shared variable CovD : CovPType; shared variable CovCrossAB : CovPType; begin p0 : sxema port map ( a => a, b => b, d => d); RandomGenProc1 : process variable RndValA, RndValB : real; -- Random value variable RndA, RndB : integer; variable SeedA1 : positive := 7; -- initialize seeds variable SeedA2 : positive := 1; variable SeedB1 : positive := 4; -- initialize seeds variable SeedB2 : positive := 2; variable i : natural := 0; variable CovACovered, CovBCovered : natural := 0; begin -- создание корзин для a, b, d CovA.AddBins(GenBin(0, 15)); CovB.AddBins(GenBin(0, 15)); CovD.AddBins(GenBin(0, 225)); CovCrossAB.AddCross(GenBin(0, 15), GenBin(0, 15)); MainCovLoop : while not (CovCrossAB.IsCovered) loop uniform(SeedA1, SeedA2, RndValA); -- randomize 0.0 to 1.0 uniform(SeedB1, SeedB2, RndValB); -- randomize 0.0 to 1.0 RndA := integer(trunc(RndValA*16.0)); -- scale to 0 to 15 RndB := integer(trunc(RndValB*16.0)); -- scale to 0 to 15 a <= std_logic_vector(to_unsigned(RndA, 4)); b <= std_logic_vector(to_unsigned(RndB, 4)); wait for 10 ns; CovA.ICover(to_integer(unsigned(a))); CovB.ICover(to_integer(unsigned(b))); CovCrossAB.ICover((to_integer(unsigned(a)), to_integer(unsigned(b)))); CovD.ICover(to_integer(unsigned(d))); i := i+1; if (CovA.IsCovered and CovACovered = 0) then CovACovered := i; end if; if (CovB.IsCovered and CovBCovered = 0) then CovBCovered := i; end if; end loop; wait for 10 ns; CovA.WriteBin; CovB.WriteBin; CovD.WriteBin; CovCrossAB.WriteBin; CovA.WriteCovDb ("tb1_CovA.db", OpenKind => write_mode); CovB.WriteCovDb ("tb1_CovB.db", OpenKind => write_mode); CovD.WriteCovDb ("tb1_CovD.db", OpenKind => write_mode); CovCrossAB.WriteCovDb ("tb1_CovCrossAB.db", OpenKind => write_mode); wait; end process; end architecture tb1; |
Листинг файла testbench(tb1a)
-- Для покрытия всех пар состояний требуется 1615 циклов
-- покрытие A достигается за 103 циклов
-- покрытие B достикается за 68 циклов
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;
entity testbench is
end;
architecture tb1a of testbench is
component sxema
port (a, b : in std_logic_vector (4 downto 1);
d : out std_logic_vector (8 downto 1));
end component;
signal a, b : std_logic_vector (4 downto 1);
signal d : std_logic_vector (8 downto 1);
shared variable CovA, CovB : integer_vector (0 to 15) := (others => 0);
shared variable CovCrossAB : integer_vector (0 to 255) := (others => 0);
begin
p0 : sxema
port map (a => a, b => b, d => d);
RandomGenProc1 : process
variable RndValA, RndValB : real; -- Random value
variable RndA, RndB, a_i, b_i : integer;
variable SeedA1 : positive := 7; -- initialize seeds
variable SeedA2 : positive := 1;
variable SeedB1 : positive := 4; -- initialize seeds
variable SeedB2 : positive := 2;
variable i : natural := 0;
variable CovACovered, CovBCovered : natural := 0;
variable CovCrossABCovered : natural := 0;
begin
-- создание корзин для a, b, d
MainCovLoop : while not (CovCrossABCovered = 1) loop
uniform(SeedA1, SeedA2, RndValA); -- randomize 0.0 to 1.0
uniform(SeedB1, SeedB2, RndValB); -- randomize 0.0 to 1.0
RndA := integer(trunc(RndValA*16.0)); -- scale to 0 to 15
RndB := integer(trunc(RndValB*16.0)); -- scale to 0 to 15
a <= std_logic_vector(to_unsigned(RndA, 4));
b <= std_logic_vector(to_unsigned(RndB, 4));
wait for 10 ns;
a_i := to_integer(unsigned(a));
b_i := to_integer(unsigned(b));
CovA(a_i) := CovA(a_i) + 1 ;
CovB(b_i) := CovB(b_i) + 1 ;
CovCrossAB(b_i*16+a_i) := CovCrossAB(b_i*16+a_i) + 1;
i := i+1;
if i = 1000000 then
exit;
end if;
CovACovered := 1;
for j in 0 to 15 loop
if CovA(j)=0 then
CovACovered := 0;
end if;
end loop; -- j
CovBCovered := 1;
for j in 0 to 15 loop
if CovB(j)=0 then
CovBCovered := 0;
end if;
end loop; -- j
CovCrossABCovered := 1;
for j in 0 to 255 loop
if CovCrossAB(j)=0 then
CovCrossABCovered := 0;
end if;
end loop; -- j
end loop;
wait for 10 ns;
wait;
end process;
end architecture tb1a;
Распределение покрытия CovA
Распределение покрытия CovB
Распределение покрытия CovD
Распределение покрытия CovCrossAB (3D)
|
---|
Листинги 2
-- Для покрытия всех пар состояний требуется 1615 циклов -- покрытие A достигается за 103 циклов -- покрытие B достикается за 68 циклов
Листинг файла testbench(tb2)
Файл: tstb_tb2.vhd |
-- Для покрытия всех пар состояний требуется 1615 циклов -- покрытие A достигается за 103 циклов -- покрытие B достикается за 68 циклов library ieee; use ieee.std_logic_1164.all; use ieee.math_real.all; use ieee.numeric_std.all; use work.RandomPkg.all; use work.CoveragePkg.all; entity testbench is end; architecture tb2 of testbench is component sxema port (a, b : in std_logic_vector (4 downto 1); d : out std_logic_vector (8 downto 1)); end component; signal a, b : std_logic_vector (4 downto 1); signal d : std_logic_vector (8 downto 1); shared variable RndA, RndB : RandomPType; shared variable CovA, CovB : CovPType; shared variable CovD : CovPType; shared variable CovCrossAB : CovPType; begin p0 : sxema port map ( a => a, b => b, d => d); RandomGenProc1 : process variable SeedA1 : positive := 7; -- initialize seeds variable SeedA2 : positive := 1; variable SeedB1 : positive := 4; -- initialize seeds variable SeedB2 : positive := 2; variable i : natural := 0; variable CovACovered, CovBCovered : natural := 0; begin -- инициализация генератора псевдослучайных чисел RndA.InitSeed(IV => (SeedA1, SeedA2)); RndB.InitSeed(IV => (SeedB1, SeedB2)); -- создание корзин для a, b, d CovA.AddBins(GenBin(0, 15)); CovB.AddBins(GenBin(0, 15)); CovD.AddBins(GenBin(0, 225)); CovCrossAB.AddCross(GenBin(0, 15), GenBin(0, 15)); MainCovLoop : while not (CovCrossAB.IsCovered) loop a <= RndA.RandSlv(0, 15, 4); b <= RndB.RandSlv(0, 15, 4); wait for 10 ns; CovA.ICover(to_integer(unsigned(a))); CovB.ICover(to_integer(unsigned(b))); CovCrossAB.ICover((to_integer(unsigned(a)), to_integer(unsigned(b)))); CovD.ICover(to_integer(unsigned(d))); i := i+1; if (CovA.IsCovered and CovACovered = 0) then CovACovered := i; end if; if (CovB.IsCovered and CovBCovered = 0) then CovBCovered := i; end if; end loop; wait for 10 ns; CovA.WriteBin; CovB.WriteBin; CovD.WriteBin; CovCrossAB.WriteBin; CovA.WriteCovDb ("tb2_CovA.db", OpenKind => write_mode); CovB.WriteCovDb ("tb2_CovB.db", OpenKind => write_mode); CovD.WriteCovDb ("tb2_CovD.db", OpenKind => write_mode); CovCrossAB.WriteCovDb ("tb2_CovCrossAB.db", OpenKind => write_mode); wait; end process; end architecture tb2; |
Листинги 3
Листинг файла testbench(tb3)
Файл: tstb_tb3.vhd |
-- Случайным образом генерит входные A и B с помощью пакета покрытия, используя перекрёстное покрытие -- т.е. интеллектуальный тестбенч для перебора всех пар -- Для покрытия всех пар состояний требуется 256 циклов -- покрытие A достигается за 49 циклов -- покрытие B достикается за 44 циклов library ieee; use ieee.std_logic_1164.all; use ieee.math_real.all; use ieee.numeric_std.all; use work.RandomPkg.all; use work.CoveragePkg.all; entity testbench is end; architecture tb3 of testbench is component sxema port (a, b : in std_logic_vector (4 downto 1); d : out std_logic_vector (8 downto 1)); end component; signal a, b : std_logic_vector (4 downto 1); signal d : std_logic_vector (8 downto 1); -- shared variable RndA, RndB : RandomPType; shared variable CovA, CovB, CovD : CovPType; shared variable CovCrossAB : CovPType; begin p0 : sxema port map ( a => a, b => b, d => d); RandomGenProc1 : process variable RndA, RndB : integer; variable SeedA1 : positive := 7; -- initialize seeds variable SeedA2 : positive := 1; variable SeedB1 : positive := 4; -- initialize seeds variable SeedB2 : positive := 2; variable i : natural := 0; variable CovACovered, CovBCovered : natural := 0; begin -- инициализация генератора псевдослучайных чисел CovCrossAB.InitSeed(CovCrossAB'instance_name); -- создание корзин для a, b, d CovA.AddBins(GenBin(0, 15)); CovB.AddBins(GenBin(0, 15)); CovD.AddBins(GenBin(0, 225)); CovCrossAB.AddCross(GenBin(0, 15), GenBin(0, 15)); MainCovLoop : while not (CovCrossAB.IsCovered) loop (RndA, RndB) := CovCrossAB.RandCovPoint; a <= std_logic_vector(to_unsigned(RndA, 4)); b <= std_logic_vector(to_unsigned(RndB, 4)); wait for 10 ns; CovA.ICover(to_integer(unsigned(a))); CovB.ICover(to_integer(unsigned(b))); CovCrossAB.ICover((to_integer(unsigned(a)), to_integer(unsigned(b)))); CovD.ICover(to_integer(unsigned(d))); i := i+1; if (CovA.IsCovered and CovACovered = 0) then CovACovered := i; end if; if (CovB.IsCovered and CovBCovered = 0) then CovBCovered := i; end if; end loop; wait for 10 ns; CovA.WriteBin; CovB.WriteBin; CovD.WriteBin; CovCrossAB.WriteBin; CovA.WriteCovDb ("tb3_CovA.db", OpenKind => write_mode); CovB.WriteCovDb ("tb3_CovB.db", OpenKind => write_mode); CovD.WriteCovDb ("tb3_CovD.db", OpenKind => write_mode); CovCrossAB.WriteCovDb ("tb3_CovCrossAB.db", OpenKind => write_mode); wait; end process; end architecture tb3; |
Листинг 0
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;
entity tstb is
end;
architecture beh of tstb is
component sxema
port (a, b : in std_logic_vector (4 downto 1);
d : out std_logic_vector (8 downto 1));
end component;
signal a, b : std_logic_vector (4 downto 1);
signal d : std_logic_vector (8 downto 1);
begin
p0 : sxema
port map (a => a, b => b, d => d);
RandomGenProc1 : process
variable RndValA, RndValB : real; -- Random value
variable RndA, RndB : integer;
variable SeedA1 : positive := 7; -- initialize seeds
variable SeedA2 : positive := 1;
variable SeedB1 : positive := 4; -- initialize seeds
variable SeedB2 : positive := 2;
begin
for i in 1 to 100 loop
uniform(SeedA1, SeedA2, RndValA); -- randomize 0.0 to 1.0
uniform(SeedB1, SeedB2, RndValB); -- randomize 0.0 to 1.0
RndA := integer(trunc(RndValA*16.0)); -- scale to 0 to 15
RndB := integer(trunc(RndValB*16.0)); -- scale to 0 to 15
a <= std_logic_vector(to_unsigned(RndA, 4));
b <= std_logic_vector(to_unsigned(RndB, 4));
wait for 10 ns;
end loop;
wait ;
end process;
end;
- Листинг деклараций пакета ieee.math_real (тело пакета)
procedure UNIFORM(variable SEED1,SEED2:inout POSITIVE; variable X:out REAL); -- Purpose: -- Returns, in X, a pseudo-random number with uniform -- distribution in the open interval (0.0, 1.0). -- Special values: -- None -- Domain: -- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398 -- Error conditions: -- Error if SEED1 or SEED2 outside of valid domain -- Range: -- 0.0 < X < 1.0 -- Notes: -- a) The semantics for this function are described by the -- algorithm published by Pierre L'Ecuyer in "Communications -- of the ACM," vol. 31, no. 6, June 1988, pp. 742-774. -- The algorithm is based on the combination of two -- multiplicative linear congruential generators for 32-bit -- platforms. -- -- b) Before the first call to UNIFORM, the seed values -- (SEED1, SEED2) have to be initialized to values in the range -- [1, 2147483562] and [1, 2147483398] respectively. The -- seed values are modified after each call to UNIFORM. -- -- c) This random number generator is portable for 32-bit -- computers, and it has a period of ~2.30584*(10**18) for each -- set of seed values. -- -- d) For information on spectral tests for the algorithm, refer -- to the L'Ecuyer article.
function TRUNC (X : in REAL ) return REAL; -- Purpose: -- Truncates X towards 0.0 and returns truncated value -- Special values: -- TRUNC(0.0) = 0.0 -- Domain: -- X in REAL -- Error conditions: -- None -- Range: -- TRUNC(X) is mathematically unbounded -- Notes: -- a) Implementations have to support at least the domain -- ABS(X) < REAL(INTEGER'HIGH)