Commit f00e5bab authored by Francis Fuentes's avatar Francis Fuentes Committed by Guillem
Browse files

Testbench expanded, still in WIP

parent 0a83591a
#$1
TOP=../../..
vlib bsc
vmap work $PWD/bsc
vlog +acc=rn +incdir+$TOP/hdl/injector_pkg $TOP/tb/tb_injector_pkg
vlib tb_injector
vmap work $PWD/tb_injector
vlog +acc=rn +incdir+$TOP/hdl/ $TOP/hdl/injector $TOP/hdl/injector_apb $TOP/hdl/injector_ctrl $TOP/hdl/injector_delay_if $TOP/hdl/injector_read_if $TOP/hdl/injector_write_if tb_injector.sv ./colors.vh
vmake tb_injector/ > Makefile
if [ -z "$1" ]
then
vsim work.tb_injector # -do "view wave -new" -do "do wave.do" -do "run -all"
else
vsim work.tb_injector $1 # -do "do save_wave.do"
fi
......@@ -47,48 +47,48 @@ architecture rtl of tb_injector is
-----------------------------------------------------------------------------
-- Pointers
constant apb_injector : std_logic_vector(31 downto 0) := 16#000# & paddr & 16#00#; -- Location of the injector at APB memory
constant apb_inj_addr : std_logic_vector(31 downto 0) := X"000" & std_logic_vector(to_unsigned(paddr, 12)) & X"00"; -- Location of the injector at APB memory
constant descr_addr1 : std_logic_vector(31 downto 0) := X"0100_0000"; -- First descriptor MSB address for test 1
constant descr_addr2w : std_logic_vector(31 downto 0) := X"0110_0000"; -- First descriptor MSB address for test 2 writes
constant descr_addr2r : std_logic_vector(31 downto 0) := X"0120_0000"; -- First descriptor MSB address for test 2 reads
constant action_addr : std_logic_vector(31 downto 0) := X"0200_0000"; -- Write/read address
-- Injector configurations
-- Test 1 configuration: Queue mode enabled, enable interrupt on error, (interrupt disabled), (kick disabled), nreset, start injector.
constant inj_config1 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "110011";
-- Test 1 configuration: Queue mode enabled, enable interrupt on error, interrupt enabled, (kick disabled), reset, start injector.
constant inj_config1 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "111001";
-- Test 2 configuration: (Queue mode disabled), enable interrupt on error, (interrupt disabled), (kick disabled), nreset, start injector.
constant inj_config2 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "010011";
-- Test 2 configuration: (Queue mode disabled), enable interrupt on error, interrupt enabled, (kick disabled), reset, start injector.
constant inj_config2 : std_logic_vector(31 downto 0) := X"0000_00" & "00" & "011001";
-- Descriptors to load into injector's fifo for test 1 (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors1 : descriptor_bank(0 to 7) := (
write_descriptor( 4, 63, WRT, action_addr, '1', descr_addr1 + 0, '0' ) & -- 64 write transactions of 4 bytes
write_descriptor( 8, 31, WRT, action_addr, '1', descr_addr1 + 20, '0' ) & -- 32 write transactions of 8 bytes
write_descriptor( 16, 15, RD, action_addr, '1', descr_addr1 + 40, '0' ) & -- 16 read transactions of 16 bytes
write_descriptor( 32, 7, RD, action_addr, '1', descr_addr1 + 60, '0' ) & -- 8 read transactions of 32 bytes
write_descriptor( 64, 3, WRT, action_addr, '1', descr_addr1 + 80, '0' ) & -- 4 write transactions of 64 bytes
write_descriptor( 128, 1, WRT, action_addr, '1', descr_addr1 + 100, '0' ) & -- 2 write transactions of 128 bytes
write_descriptor( 256, 0, RD, action_addr, '1', descr_addr1 + 120, '1' ) -- 1 read transaction of 256 bytes
constant descriptors1 : descriptor_bank(0 to 6) := (
write_descriptor( 4, 63, WRT, action_addr, '1', add_vector(descr_addr1, 0, 32), '0'),-- 64 write transactions of 4 bytes
write_descriptor( 8, 31, WRT, action_addr, '1', add_vector(descr_addr1, 20, 32), '0'),-- 32 write transactions of 8 bytes
write_descriptor( 16, 15, RD, action_addr, '1', add_vector(descr_addr1, 40, 32), '0'),-- 16 read transactions of 16 bytes
write_descriptor( 32, 7, RD, action_addr, '1', add_vector(descr_addr1, 60, 32), '0'),-- 8 read transactions of 32 bytes
write_descriptor( 64, 3, WRT, action_addr, '1', add_vector(descr_addr1, 80, 32), '0'),-- 4 write transactions of 64 bytes
write_descriptor( 128, 1, WRT, action_addr, '1', add_vector(descr_addr1, 100, 32), '0'),-- 2 write transactions of 128 bytes
write_descriptor( 256, 0, RD, action_addr, '1', add_vector(descr_addr1, 120, 32), '1') -- 1 read transaction of 256 bytes
);
-- Descriptors to load into injector's fifo for test 2 write (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors2w : descriptor_bank(0 to 5) := (
write_descriptor( MAX_SIZE_BEAT-3, 0, WRT, action_addr, '0', descr_addr2w + 0, '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, WRT, action_addr, '0', descr_addr2w + 20, '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, WRT, action_addr, '0', descr_addr2w + 40, '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, WRT, action_addr, '1', descr_addr2w + 60, '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, WRT, action_addr, '1', descr_addr2w + 80, '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, WRT, action_addr, '1', descr_addr2w + 100, '1' ) -- With fix addr, check if it really fixes the addr
write_descriptor( MAX_SIZE_BEAT-3, 0, WRT, action_addr, '0', add_vector(descr_addr1, 0, 32), '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, WRT, action_addr, '0', add_vector(descr_addr1, 20, 32), '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, WRT, action_addr, '0', add_vector(descr_addr1, 40, 32), '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, WRT, action_addr, '1', add_vector(descr_addr1, 60, 32), '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, WRT, action_addr, '1', add_vector(descr_addr1, 80, 32), '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, WRT, action_addr, '1', add_vector(descr_addr1, 100, 32), '1' ) -- With fix addr, check if it really fixes the addr
);
-- Descriptors to load into injector's fifo for test 2 read (size, count, action, addr, addrfix, nextraddr, last)
constant descriptors2r : descriptor_bank(0 to 5) := (
write_descriptor( MAX_SIZE_BEAT-3, 0, RD, action_addr, '0', descr_addr2r + 0, '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, RD, action_addr, '0', descr_addr2r + 20, '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, RD, action_addr, '0', descr_addr2r + 40, '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, RD, action_addr, '1', descr_addr2r + 60, '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, RD, action_addr, '1', descr_addr2r + 80, '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, RD, action_addr, '1', descr_addr2r + 100, '1' ) -- With fix addr, check if it really fixes the addr
write_descriptor( MAX_SIZE_BEAT-3, 0, RD, action_addr, '0', add_vector(descr_addr1, 0, 32), '0' ), -- Check if writes the correct ammount below size beat
write_descriptor( MAX_SIZE_BEAT, 0, RD, action_addr, '0', add_vector(descr_addr1, 20, 32), '0' ), -- Check if writes the correct ammount equal size beat
write_descriptor( MAX_SIZE_BEAT+3, 0, RD, action_addr, '0', add_vector(descr_addr1, 40, 32), '0' ), -- Check if writes the correct ammount above size beat
write_descriptor( 3, 0, RD, action_addr, '1', add_vector(descr_addr1, 60, 32), '0' ), -- With fix addr, check if reads lower of a word
write_descriptor( 4, 0, RD, action_addr, '1', add_vector(descr_addr1, 80, 32), '0' ), -- With fix addr, check if reads a word
write_descriptor( 15, 0, RD, action_addr, '1', add_vector(descr_addr1, 100, 32), '1' ) -- With fix addr, check if it really fixes the addr
);
-----------------------------------------------------------------------------
......@@ -110,8 +110,11 @@ architecture rtl of tb_injector is
signal apbi : apb_slave_in_type := DEF_INJ_APB;
signal bm_out : bm_out_type := DEF_INJ_BM;
-- APB configuration
signal apb_sel: std_logic_vector(apbi.sel'range) := std_logic_vector(shift_left(to_unsigned(1, apbi.sel'length), apbi.sel'length-pindex-1));
-----------------------------------------------------------------------------
-- Function/procedure declaration
-----------------------------------------------------------------------------
......@@ -132,38 +135,60 @@ begin -- rtl
test : process
begin
-- Configure injector for test 1
apbi.sel <= std_logic_vector(shift_left(16#0000_0001#, pindex), 32);
apbi.addr <= apb_injector + 8; -- Write 1st descriptor pointer
apbi.wdata <= descr_addr1; -- Test 1 descriptors pointer
apbi.sel <= apb_sel;
apbi.addr <= add_vector(apb_inj_addr, 8, apbi.addr'length); -- Write 1st descriptor pointer
apbi.wdata <= descr_addr1; -- Test 1 descriptors pointer
wait for T + 3 ns;
rstn <= '1';
wait for rising_edge(clk);
rstn <= '1';
apbi.write <= '1';
wait for T;
apbi.write <= '0';
apbi.addr <= apb_injector; -- Configure injector
wait until falling_edge(clk);
apbi.en <= '1';
wait until falling_edge(clk);
apbi.en <= '0';
apbi.addr <= apb_inj_addr; -- Configure and start injector
apbi.wdata <= inj_config1; -- Test 1 configuration
wait for T;
apbi.write <= '1';
wait for 3*T;
wait until falling_edge(clk);
apbi.en <= '1';
wait until falling_edge(clk);
apbi.en <= '0';
if(FALSE) then
assert TRUE report "Test 1: load configuration FAILED!" severity error;
else report "Test 1: load configuration passed!\n Starting to load descriptors.\n\n";
end if;
wait until rising_edge(bm_in.rd_req);
apbi.addr <= (others => '0');
apbi.write <= '0';
wait for rising_edge(bm_in.rd_req);
-- Load descriptors
if(bm_in.rd_addr = descr_addr1) then
read_descr(descriptors1, bm_out.rd_data, bm_out.rd_valid, bm_out.rd_done, bm_in.rd_req, bm_out.rd_req_grant);
else assert TRUE report "Test 1: load descriptors FAILED!" severity error;
end if; report "Test 1: load descriptors passed!\n Executing Test 1.\n\n";
read_descr(descriptors1, bm_out.rd_data, bm_out.rd_valid, bm_out.rd_done, bm_in.rd_req, bm_out.rd_req_grant);
else assert FALSE report "Test 1: load descriptors FAILED!" & LF & " Injector is fetching descriptors at a wrong address." severity failure;
end if; report "Test 1: load descriptors passed!" & LF & " Executing Test 1.";
-- Check if the descriptors have been loaded correctly
if(FALSE) then -- It seems that VHDL doesn't allow to tap into component signals. Check ram!=descriptors if found a way to do it.
assert FALSE report "Test 1: load configuration FAILED!" & LF & " Something wrong has happened while loading descriptors into the FIFO." severity failure;
else report "Test 1: load configuration passed!" & LF & " Starting to load descriptors.";
end if;
test_descriptor_batch(bm_in, descriptors1, bm_out, MAX_SIZE_BEAT); -- Test all descriptors from TEST 1 once
assert FALSE report "TEST FINISHED" severity failure;
end process test;
-- Everytime a read/write transaction is completed, the respective done flag is asserted for a single clock cycle.
-- This action can be verified by reading the bit 0 at the APB memory 0x20 of the injector, 2 clock cycles after the desassertation of the done signal.
completed_transaction : process (bm_out.rd_done, bm_out.wr_done)
begin
apbi.sel <= apb_sel; -- <- Line probably not required
apbi.en <= '1';
apbi.addr <= add_vector(apb_inj_addr, x"20", apbi.addr'length);
wait for T;
assert apbo.rdata(0) report "The injector is not reporting 'done' at dbg.sts after a write/read transaction!" severity failure;
apbi.en <= '0';
end process;
-----------------------------------------------------------------------------
-- Component instantiation
......
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb_injector/rstn
add wave -noupdate /tb_injector/clk
add wave -noupdate /tb_injector/apbi
add wave -noupdate /tb_injector/apbo
add wave -noupdate /tb_injector/core/apb/pindex
add wave -noupdate /tb_injector/core/apb/rin
add wave -noupdate /tb_injector/bm_in
add wave -noupdate /tb_injector/bm_out
add wave -noupdate /tb_injector/core/ctrl/status
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {14 ns} 0}
quietly wave cursor active 1
configure wave -namecolwidth 150
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {0 ns} {105 ns}
......@@ -81,16 +81,25 @@ package tb_injector_pkg is
-- Procedure used to simulate a memory fetch to load descriptors for a test
procedure read_descr(
variable descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(31 downto 0);
signal valid : out std_logic := '0';
signal done : out std_logic := '0';
constant descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(127 downto 0);
signal valid : out std_logic;
signal done : out std_logic;
signal req : in std_logic;
signal req_grant : out std_logic := '1'
signal req_grant : out std_logic
);
-- Procedure used to execute read/write transactions
procedure test_descriptor_batch(
signal bmin : in bm_in_type;
signal bmout : out bm_out_type;
constant descr : in descriptor_bank
);
end package tb_injector_pkg;
package body tb_injector_pkg is
-----------------------------------------------------------------------------
......@@ -105,20 +114,22 @@ package body tb_injector_pkg is
nextaddr : std_logic_vector(31 downto 0); -- Address to load from the next descriptor
last : std_ulogic -- Last descriptor flag
) return descriptor_words is
variable descr_words : descriptor_words := (others => (others => '0'));
variable src_addr, dest_addr : std_ulogic := '0';
variable src_fix_addr, dest_fix_addr, size_std, count_std : std_logic_vector(31 downto 0) := (others => '0');
variable descr_words : descriptor_words := (others => (others => '0'));
variable src_fix_addr, dest_fix_addr : std_ulogic := '0';
variable src_addr, dest_addr : std_logic_vector(31 downto 0) := (others => '0');
variable size_std : std_logic_vector(18 downto 0) := (others => '0');
variable count_std : std_logic_vector(5 downto 0) := (others => '0');
begin
size_std := std_logic_vector( unsigned(size, size_std'length ) );
count_std := std_logic_vector( unsigned(count, count_std'length) );
size_std := std_logic_vector( to_unsigned(size, size_std'length ) );
count_std := std_logic_vector( to_unsigned(count, count_std'length) );
case action is
when READ =>
when RD =>
src_addr := addr;
src_fix_addr := addrfix;
when WRITE =>
when WRT =>
dest_addr := addr;
dest_fix_addr := addrfix;
......@@ -138,34 +149,39 @@ package body tb_injector_pkg is
last ,
dest_addr , --0x08 Write address
src_addr , --0x0C Read address
16#0000_0000# --0x10 Descriptor status word (for future implementation)
x"00000000" --0x10 Descriptor status word (for future implementation)
);
return descr_words;
end write_descriptor;
end function write_descriptor;
procedure read_descr(
variable descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(31 downto 0);
signal valid : out std_logic := '0';
signal done : out std_logic := '0';
constant descriptor_bank : in descriptor_bank;
signal rdata : out std_logic_vector(127 downto 0);
signal valid : out std_logic;
signal done : out std_logic;
signal req : in std_logic;
signal req_grant : out std_logic := '1'
signal req_grant : out std_logic
) is
variable descriptor : descriptor_words;
begin
for j in descriptor_bank'range loop -- Loop between descriptors
descriptor := descriptor_bank(j);
wait for falling_edge(req);
req_grant <= '1';
done <= '0';
valid <= '0';
wait until falling_edge(req);
req_grant <= '0';
for i in descriptor'range loop -- Loop for a single descriptor
valid <= '0';
rdata <= descriptor(i);
rdata <= descriptor(i) & X"00000000_00000000_00000000";
wait for T;
done <= (i = (descriptor'length - 1));
if (i = (descriptor'length - 1)) then done <= '1';
else done <= '0';
end if;
valid <= '1';
wait for T;
end loop;
......@@ -174,8 +190,124 @@ package body tb_injector_pkg is
done <= '0';
valid <= '0';
end loop;
end read_descr;
end procedure read_descr;
procedure test_descriptor_batch(
signal bmin : in bm_in_type;
signal bmout : out bm_out_type;
constant descr : in descriptor_bank;
constant MAX_BEAT : in integer
) is
variable tot_size : integer := 0; -- Remaining bytes to read/write from total transfer
variable beat_size : integer := 0; -- Remaining bytes to read/write from beat transfer
signal addr_off : integer := 0; -- Address offset where to execute the transfer beat
begin
-- Wait for transaction request
wait until rising_edge(bmin.rd_req) or rising_edge(bmin.wr_req);
-- Loop for every descriptor transaction
for descr_num in descr'range loop
-- Loop descriptor transaction for number of repetitions
for repet_count in to_unsigned(descr(descr_num)(0)(12 downto 7)) to 0 loop
addr_off <= 0;
-- Read transaction
if(bmin.rd_req) then
tot_size := to_integer(bmin.rd_size) + 1;
-- Due to maximum size beats in bursts, big transactions must be sliced in MAX_SIZE_BEAT beats.
while (tot_size > 0) loop
-- Size management
if(tot_size > MAX_BEAT) then
beat_size := MAX_BEAT;
tot_size := tot_size - MAX_BEAT;
else
beat_size := tot_size;
tot_size := 0;
end if;
-- Compute address offset if the transfer is not address fixed
if(not descr(descr_num)(0)(5)) then addr_off <= to_integer(bmin.rd_size) + 1 - tot_size; end if;
-- Check if injector is reading on the correct address
assert (bmin.rd_addr = descr(descr_num)(3) + addr_off) report "Wrong address fetched for read transaction!" & LF & "Expected 0x"
& to_hstring(descr(descr_num)(3) + addr_off) & " address, but injector fetched at 0x"
& to_hstring(bmin.rd_addr) & "." severity failure;
-- Start reading beat
wait until falling_edge(bmin.rd_req); -- Putting this line here allows to manage beats
bmout.rd_req_grant <= '0';
while (beat_size > 4) loop -- This loop may be unnecessary for the injector, but simulates SELENE platform behaviour
beat_size := beat_size - 4;
wait for T; -- May change to random wait
bmout.rd_valid <= '1';
if(beat_size > 4) then bmout.rd_done <= '1'; end if; -- Last read must also have done asserted.
wait for T;
bmout.rd_valid <= '0';
bmout.rd_done <= '0';
end loop;
-- Finished reading a beat
bmout.rd_req_grant <= '1'; -- Prepare for next reading beat
end loop; -- BURST loop
end if;
-- Write transaction
if(bmin.wr_req) then
tot_size := to_integer(bmin.wr_size) + 1;
-- Due to maximum size beats in bursts, big transactions must be sliced in MAX_SIZE_BEAT beats.
while (tot_size > 0) loop
-- Size management
if(tot_size > MAX_BEAT) then
beat_size := MAX_BEAT;
tot_size := tot_size - MAX_BEAT;
else
beat_size := tot_size;
tot_size := 0;
end if;
-- Compute address offset if the transfer is not address fixed
if(not descr(descr_num)(0)(6)) then addr_off <= to_integer(bmin.wr_size) + 1 - tot_size; end if;
-- Check if injector is writing on the correct address
assert (bmin.wr_addr = descr(descr_num)(2) + addr_off) report "Wrong address fetched for read transaction!" & LF & "Expected 0x"
& to_hstring(descr(descr_num)(2) + addr_off) & " address, but injector fetched at 0x"
& to_hstring(bmin.wr_addr) & "." severity failure;
-- Start writting beat
wait until falling_edge(bmin.wr_req); -- Putting this line here allows to manage beats
bmout.wr_req_grant <= '0';
while (beat_size > 4) loop
beat_size := beat_size - 4;
bmout.wr_full <= '0';
wait for T; -- May change to random wait
bmout.wr_full <= '1';
wait for T;
if(beat_size > 4) then bmout.wr_done <= '1'; end if; -- Last write must also have done raised.
end loop;
-- Finished reading a beat
wait for T;
bmout.wr_done <= '0';
bmout.wr_req_grant <= '1'; -- Prepare for next writing beat
end loop; -- BURST loop
end if;
end loop; -- Loop for repetitions
end loop; -- Loop for descriptors
end procedure test_descriptor_batch;
-----------------------------------------------------------------------------
-- Component instantiation
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment