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

Subversion Repositories lxp32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /lxp32/trunk/verify/icache/src/tb
    from Rev 6 to Rev 9
    Reverse comparison

Rev 6 → Rev 9

/cpu_model.vhd
1,179 → 1,179
---------------------------------------------------------------------
-- CPU model
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Requests data from cache
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
 
use work.common_pkg.all;
use work.tb_pkg.all;
 
entity cpu_model is
generic(
BLOCKS: integer;
VERBOSE: boolean
);
port(
clk_i: in std_logic;
lli_re_o: out std_logic;
lli_adr_o: out std_logic_vector(29 downto 0);
lli_dat_i: in std_logic_vector(31 downto 0);
lli_busy_i: in std_logic;
finish_o: out std_logic
);
end entity;
 
architecture sim of cpu_model is
 
constant bursts: integer:=10000;
 
signal re: std_logic:='0';
signal lli_adr: std_logic_vector(29 downto 0);
 
signal request: std_logic:='0';
signal request_addr: std_logic_vector(29 downto 0);
 
signal finish: std_logic:='0';
 
signal current_latency: integer:=1;
signal max_latency: integer:=-1;
signal total_latency: integer:=0;
signal spurious_misses: integer:=0;
 
begin
 
process is
variable b: integer:=1;
variable start: integer;
variable size: integer;
variable addr: integer:=0;
variable delay: integer;
variable rng_state: rng_state_type;
variable r: integer;
variable total_requests: integer:=0;
begin
while b<=BLOCKS loop
rand(rng_state,1,10,r);
if r=1 then -- insert large block occasionally
rand(rng_state,1,400,size);
else -- small block
rand(rng_state,1,32,size);
end if;
rand(rng_state,0,1,r);
if r=0 then -- long jump
rand(rng_state,0,1024,start);
addr:=start;
if VERBOSE then
report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)&
" of size "&integer'image(size);
end if;
else -- short jump
rand(rng_state,-10,10,r);
start:=addr+r;
if start<0 then
start:=0;
end if;
addr:=start;
if VERBOSE then
report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)&
" of size "&integer'image(size)&" (short jump)";
end if;
end if;
while addr<start+size loop
re<='1';
total_requests:=total_requests+1;
lli_adr<=std_logic_vector(to_unsigned(addr,30));
wait until rising_edge(clk_i) and lli_busy_i='0';
re<='0';
addr:=addr+1;
rand(rng_state,0,4,delay);
if delay>0 then
for i in 1 to delay loop
wait until rising_edge(clk_i);
end loop;
end if;
end loop;
if (b mod 10000)=0 then
report integer'image(b)&" BLOCKS PROCESSED";
end if;
b:=b+1;
end loop;
report "Number of requests: "&integer'image(total_requests);
report "Maximum latency: "&integer'image(max_latency);
report "Average latency: "&real'image(real(total_latency)/real(total_requests));
report "Number of spurious misses: "&integer'image(spurious_misses);
finish<='1';
wait;
end process;
 
lli_re_o<=re;
lli_adr_o<=lli_adr;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if lli_busy_i='0' then
if request='1' then
assert lli_dat_i=(("00"&request_addr) xor xor_constant)
report "Data mismatch: expected 0x"&
hex_string(("00"&request_addr) xor xor_constant)&
", got 0x"&hex_string(lli_dat_i)
severity failure;
end if;
request<=re;
request_addr<=lli_adr;
end if;
end if;
end process;
 
finish_o<=finish;
 
-- Measure latency
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if lli_busy_i='0' then
if request='1' then
total_latency<=total_latency+current_latency;
if current_latency>max_latency then
max_latency<=current_latency;
end if;
end if;
current_latency<=1;
else
if lli_dat_i=(("00"&request_addr) xor xor_constant) and current_latency=1 then
spurious_misses<=spurious_misses+1;
end if;
current_latency<=current_latency+1;
end if;
end if;
end process;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
assert lli_busy_i='0' or request='1'
report "LLI busy signal asserted without a request"
severity failure;
end if;
end process;
 
end architecture;
---------------------------------------------------------------------
-- CPU model
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Requests data from cache
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
 
use work.common_pkg.all;
use work.tb_pkg.all;
 
entity cpu_model is
generic(
BLOCKS: integer;
VERBOSE: boolean
);
port(
clk_i: in std_logic;
lli_re_o: out std_logic;
lli_adr_o: out std_logic_vector(29 downto 0);
lli_dat_i: in std_logic_vector(31 downto 0);
lli_busy_i: in std_logic;
finish_o: out std_logic
);
end entity;
 
architecture sim of cpu_model is
 
constant bursts: integer:=10000;
 
signal re: std_logic:='0';
signal lli_adr: std_logic_vector(29 downto 0);
 
signal request: std_logic:='0';
signal request_addr: std_logic_vector(29 downto 0);
 
signal finish: std_logic:='0';
 
signal current_latency: integer:=1;
signal max_latency: integer:=-1;
signal total_latency: integer:=0;
signal spurious_misses: integer:=0;
 
begin
 
process is
variable b: integer:=1;
variable start: integer;
variable size: integer;
variable addr: integer:=0;
variable delay: integer;
variable rng_state: rng_state_type;
variable r: integer;
variable total_requests: integer:=0;
begin
while b<=BLOCKS loop
rand(rng_state,1,10,r);
if r=1 then -- insert large block occasionally
rand(rng_state,1,400,size);
else -- small block
rand(rng_state,1,32,size);
end if;
rand(rng_state,0,1,r);
if r=0 then -- long jump
rand(rng_state,0,1024,start);
addr:=start;
if VERBOSE then
report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)&
" of size "&integer'image(size);
end if;
else -- short jump
rand(rng_state,-10,10,r);
start:=addr+r;
if start<0 then
start:=0;
end if;
addr:=start;
if VERBOSE then
report "Fetching block #"&integer'image(b)&" at address "&integer'image(addr)&
" of size "&integer'image(size)&" (short jump)";
end if;
end if;
while addr<start+size loop
re<='1';
total_requests:=total_requests+1;
lli_adr<=std_logic_vector(to_unsigned(addr,30));
wait until rising_edge(clk_i) and lli_busy_i='0';
re<='0';
addr:=addr+1;
rand(rng_state,0,4,delay);
if delay>0 then
for i in 1 to delay loop
wait until rising_edge(clk_i);
end loop;
end if;
end loop;
if (b mod 10000)=0 then
report integer'image(b)&" BLOCKS PROCESSED";
end if;
b:=b+1;
end loop;
report "Number of requests: "&integer'image(total_requests);
report "Maximum latency: "&integer'image(max_latency);
report "Average latency: "&real'image(real(total_latency)/real(total_requests));
report "Number of spurious misses: "&integer'image(spurious_misses);
finish<='1';
wait;
end process;
 
lli_re_o<=re;
lli_adr_o<=lli_adr;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if lli_busy_i='0' then
if request='1' then
assert lli_dat_i=(("00"&request_addr) xor xor_constant)
report "Data mismatch: expected 0x"&
hex_string(("00"&request_addr) xor xor_constant)&
", got 0x"&hex_string(lli_dat_i)
severity failure;
end if;
request<=re;
request_addr<=lli_adr;
end if;
end if;
end process;
 
finish_o<=finish;
 
-- Measure latency
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if lli_busy_i='0' then
if request='1' then
total_latency<=total_latency+current_latency;
if current_latency>max_latency then
max_latency<=current_latency;
end if;
end if;
current_latency<=1;
else
if lli_dat_i=(("00"&request_addr) xor xor_constant) and current_latency=1 then
spurious_misses<=spurious_misses+1;
end if;
current_latency<=current_latency+1;
end if;
end if;
end process;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
assert lli_busy_i='0' or request='1'
report "LLI busy signal asserted without a request"
severity failure;
end if;
end process;
 
end architecture;
/ram_model.vhd
1,79 → 1,79
---------------------------------------------------------------------
-- RAM model
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Simulates RAM controller which provides WISHBONE registered
-- feedback interface.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.common_pkg.all;
use work.tb_pkg.all;
 
entity ram_model is
port(
clk_i: in std_logic;
wbm_cyc_i: in std_logic;
wbm_stb_i: in std_logic;
wbm_cti_i: in std_logic_vector(2 downto 0);
wbm_bte_i: in std_logic_vector(1 downto 0);
wbm_ack_o: out std_logic;
wbm_adr_i: in std_logic_vector(29 downto 0);
wbm_dat_o: out std_logic_vector(31 downto 0)
);
end entity;
 
architecture sim of ram_model is
 
signal ack: std_logic:='0';
signal cycle: std_logic:='0';
 
begin
 
wbm_ack_o<=ack;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if wbm_cyc_i='1' and wbm_stb_i='1' and wbm_cti_i="010" and wbm_bte_i="00" then
cycle<='1';
elsif wbm_cyc_i='0' or (wbm_cyc_i='1' and wbm_stb_i='1' and (wbm_cti_i/="010" or wbm_bte_i/="00")) then
cycle<='0';
end if;
end if;
end process;
 
process is
variable rng_state: rng_state_type;
variable delay: integer;
begin
wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1';
ack<='0';
-- Random delay before the first beat
if cycle='0' then
rand(rng_state,0,3,delay);
if delay>0 then
for i in 1 to delay loop
wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1';
end loop;
end if;
end if;
if ack='0' then
wbm_dat_o<=("00"&wbm_adr_i) xor xor_constant;
ack<='1';
elsif wbm_cti_i="010" and wbm_bte_i="00" then
wbm_dat_o<=("00"&std_logic_vector(unsigned(wbm_adr_i)+1)) xor xor_constant;
ack<='1';
end if;
end process;
 
end architecture;
---------------------------------------------------------------------
-- RAM model
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Simulates RAM controller which provides WISHBONE registered
-- feedback interface.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.common_pkg.all;
use work.tb_pkg.all;
 
entity ram_model is
port(
clk_i: in std_logic;
wbm_cyc_i: in std_logic;
wbm_stb_i: in std_logic;
wbm_cti_i: in std_logic_vector(2 downto 0);
wbm_bte_i: in std_logic_vector(1 downto 0);
wbm_ack_o: out std_logic;
wbm_adr_i: in std_logic_vector(29 downto 0);
wbm_dat_o: out std_logic_vector(31 downto 0)
);
end entity;
 
architecture sim of ram_model is
 
signal ack: std_logic:='0';
signal cycle: std_logic:='0';
 
begin
 
wbm_ack_o<=ack;
 
process (clk_i) is
begin
if rising_edge(clk_i) then
if wbm_cyc_i='1' and wbm_stb_i='1' and wbm_cti_i="010" and wbm_bte_i="00" then
cycle<='1';
elsif wbm_cyc_i='0' or (wbm_cyc_i='1' and wbm_stb_i='1' and (wbm_cti_i/="010" or wbm_bte_i/="00")) then
cycle<='0';
end if;
end if;
end process;
 
process is
variable rng_state: rng_state_type;
variable delay: integer;
begin
wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1';
ack<='0';
-- Random delay before the first beat
if cycle='0' then
rand(rng_state,0,3,delay);
if delay>0 then
for i in 1 to delay loop
wait until rising_edge(clk_i) and wbm_cyc_i='1' and wbm_stb_i='1';
end loop;
end if;
end if;
if ack='0' then
wbm_dat_o<=("00"&wbm_adr_i) xor xor_constant;
ack<='1';
elsif wbm_cti_i="010" and wbm_bte_i="00" then
wbm_dat_o<=("00"&std_logic_vector(unsigned(wbm_adr_i)+1)) xor xor_constant;
ack<='1';
end if;
end process;
 
end architecture;
/tb.vhd
1,104 → 1,104
---------------------------------------------------------------------
-- LXP32 instruction cache verification environment (self-checking
-- testbench)
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Parameters:
-- CACHE_BURST_SIZE: burst size for cache unit
-- CACHE_PREFETCH_SIZE: prefetch distance for cache unit
-- CPU_BLOCKS: number of data blocks to fetch
-- VERBOSE: print more messages
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity tb is
generic(
CACHE_BURST_SIZE: integer:=16;
CACHE_PREFETCH_SIZE: integer:=32;
CPU_BLOCKS: integer:=100000;
VERBOSE: boolean:=false
);
end entity;
 
architecture testbench of tb is
 
signal clk: std_logic:='0';
signal rst: std_logic:='0';
 
signal lli_re: std_logic;
signal lli_adr: std_logic_vector(29 downto 0);
signal lli_dat: std_logic_vector(31 downto 0);
signal lli_busy: std_logic;
 
signal wbm_cyc: std_logic;
signal wbm_stb: std_logic;
signal wbm_cti: std_logic_vector(2 downto 0);
signal wbm_bte: std_logic_vector(1 downto 0);
signal wbm_ack: std_logic;
signal wbm_adr: std_logic_vector(29 downto 0);
signal wbm_dat: std_logic_vector(31 downto 0);
 
signal finish: std_logic:='0';
 
begin
 
clk<=not clk and not finish after 5 ns;
 
dut: entity work.lxp32_icache(rtl)
generic map(
BURST_SIZE=>CACHE_BURST_SIZE,
PREFETCH_SIZE=>CACHE_PREFETCH_SIZE
)
port map(
clk_i=>clk,
rst_i=>rst,
lli_re_i=>lli_re,
lli_adr_i=>lli_adr,
lli_dat_o=>lli_dat,
lli_busy_o=>lli_busy,
wbm_cyc_o=>wbm_cyc,
wbm_stb_o=>wbm_stb,
wbm_cti_o=>wbm_cti,
wbm_bte_o=>wbm_bte,
wbm_ack_i=>wbm_ack,
wbm_adr_o=>wbm_adr,
wbm_dat_i=>wbm_dat
);
 
ram_model_inst: entity work.ram_model(sim)
port map(
clk_i=>clk,
wbm_cyc_i=>wbm_cyc,
wbm_stb_i=>wbm_stb,
wbm_cti_i=>wbm_cti,
wbm_bte_i=>wbm_bte,
wbm_ack_o=>wbm_ack,
wbm_adr_i=>wbm_adr,
wbm_dat_o=>wbm_dat
);
 
cpu_model_inst: entity work.cpu_model(sim)
generic map(
BLOCKS=>CPU_BLOCKS,
VERBOSE=>VERBOSE
)
port map(
clk_i=>clk,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy,
finish_o=>finish
);
 
end architecture;
---------------------------------------------------------------------
-- LXP32 instruction cache verification environment (self-checking
-- testbench)
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Parameters:
-- CACHE_BURST_SIZE: burst size for cache unit
-- CACHE_PREFETCH_SIZE: prefetch distance for cache unit
-- CPU_BLOCKS: number of data blocks to fetch
-- VERBOSE: print more messages
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
entity tb is
generic(
CACHE_BURST_SIZE: integer:=16;
CACHE_PREFETCH_SIZE: integer:=32;
CPU_BLOCKS: integer:=100000;
VERBOSE: boolean:=false
);
end entity;
 
architecture testbench of tb is
 
signal clk: std_logic:='0';
signal rst: std_logic:='0';
 
signal lli_re: std_logic;
signal lli_adr: std_logic_vector(29 downto 0);
signal lli_dat: std_logic_vector(31 downto 0);
signal lli_busy: std_logic;
 
signal wbm_cyc: std_logic;
signal wbm_stb: std_logic;
signal wbm_cti: std_logic_vector(2 downto 0);
signal wbm_bte: std_logic_vector(1 downto 0);
signal wbm_ack: std_logic;
signal wbm_adr: std_logic_vector(29 downto 0);
signal wbm_dat: std_logic_vector(31 downto 0);
 
signal finish: std_logic:='0';
 
begin
 
clk<=not clk and not finish after 5 ns;
 
dut: entity work.lxp32_icache(rtl)
generic map(
BURST_SIZE=>CACHE_BURST_SIZE,
PREFETCH_SIZE=>CACHE_PREFETCH_SIZE
)
port map(
clk_i=>clk,
rst_i=>rst,
lli_re_i=>lli_re,
lli_adr_i=>lli_adr,
lli_dat_o=>lli_dat,
lli_busy_o=>lli_busy,
wbm_cyc_o=>wbm_cyc,
wbm_stb_o=>wbm_stb,
wbm_cti_o=>wbm_cti,
wbm_bte_o=>wbm_bte,
wbm_ack_i=>wbm_ack,
wbm_adr_o=>wbm_adr,
wbm_dat_i=>wbm_dat
);
 
ram_model_inst: entity work.ram_model(sim)
port map(
clk_i=>clk,
wbm_cyc_i=>wbm_cyc,
wbm_stb_i=>wbm_stb,
wbm_cti_i=>wbm_cti,
wbm_bte_i=>wbm_bte,
wbm_ack_o=>wbm_ack,
wbm_adr_i=>wbm_adr,
wbm_dat_o=>wbm_dat
);
 
cpu_model_inst: entity work.cpu_model(sim)
generic map(
BLOCKS=>CPU_BLOCKS,
VERBOSE=>VERBOSE
)
port map(
clk_i=>clk,
lli_re_o=>lli_re,
lli_adr_o=>lli_adr,
lli_dat_i=>lli_dat,
lli_busy_i=>lli_busy,
finish_o=>finish
);
 
end architecture;
/tb_pkg.vhd
1,17 → 1,17
---------------------------------------------------------------------
-- LXP32 instruction cache testbench package
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Auxiliary package declaration for the LXP32 instruction cache
-- testbench.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package tb_pkg is
constant xor_constant: std_logic_vector(31 downto 0):=X"12345678";
end package;
---------------------------------------------------------------------
-- LXP32 instruction cache testbench package
--
-- Part of the LXP32 instruction cache testbench
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
-- Auxiliary package declaration for the LXP32 instruction cache
-- testbench.
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
 
package tb_pkg is
constant xor_constant: std_logic_vector(31 downto 0):=X"12345678";
end package;

powered by: WebSVN 2.1.0

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