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; |