Commit 5f010f90 authored by Dimitris Lampridis's avatar Dimitris Lampridis

[hdl] handle host 32-bit address overflow in L2P DMA master

parent f2863fc1
...@@ -86,7 +86,14 @@ architecture behavioral of l2p_dma_master is ...@@ -86,7 +86,14 @@ architecture behavioral of l2p_dma_master is
--------------------- ---------------------
-- Constants -- Constants
--------------------- ---------------------
constant c_L2P_MAX_PAYLOAD : integer := 32;
-- L2P_MAX_PAYLOAD must be a power of 2 for easier 32-bit address overflow check.
constant c_L2P_MAX_PAYLOAD_NBITS : integer := 7;
constant c_L2P_MAX_PAYLOAD_BYTES : integer := 2 ** c_L2P_MAX_PAYLOAD_NBITS;
constant c_L2P_MAX_PAYLOAD_WORDS : integer := c_L2P_MAX_PAYLOAD_BYTES / 4;
constant c_L2P_A32_OVERFLOW_MASK : std_logic_vector(31 downto 0) :=
not std_logic_vector(to_unsigned(c_L2P_MAX_PAYLOAD_BYTES - 1, 32));
constant c_TIMEOUT : integer := 2000; constant c_TIMEOUT : integer := 2000;
-- how many pending WB requests to allow without ACK -- how many pending WB requests to allow without ACK
...@@ -330,13 +337,13 @@ begin ...@@ -330,13 +337,13 @@ begin
l2p_byte_swap <= dma_ctrl_byte_swap_i; l2p_byte_swap <= dma_ctrl_byte_swap_i;
l2p_last_packet <= '0'; l2p_last_packet <= '0';
elsif (l2p_dma_current_state = L2P_SETUP) then elsif (l2p_dma_current_state = L2P_SETUP) then
if (l2p_len_cnt > c_L2P_MAX_PAYLOAD) then if (l2p_len_cnt > c_L2P_MAX_PAYLOAD_WORDS) then
l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD_WORDS, 13);
l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD_WORDS, 13);
l2p_last_packet <= '0'; l2p_last_packet <= '0';
elsif (l2p_len_cnt = c_L2P_MAX_PAYLOAD) then elsif (l2p_len_cnt = c_L2P_MAX_PAYLOAD_WORDS) then
l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD_WORDS, 13);
l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD_WORDS, 13);
l2p_last_packet <= '1'; l2p_last_packet <= '1';
else else
l2p_data_cnt <= l2p_len_cnt(12 downto 0); l2p_data_cnt <= l2p_len_cnt(12 downto 0);
...@@ -349,10 +356,15 @@ begin ...@@ -349,10 +356,15 @@ begin
end if; end if;
elsif (l2p_dma_current_state = L2P_LAST_DATA) then elsif (l2p_dma_current_state = L2P_LAST_DATA) then
if (l2p_last_packet = '0') then if (l2p_last_packet = '0') then
-- Increase Address -- Increase Address, check for overflow
-- TODO Not overflow safe ! if (l2p_address_l and (c_L2P_A32_OVERFLOW_MASK)) = c_L2P_A32_OVERFLOW_MASK then
l2p_address_l <= std_logic_vector(unsigned(l2p_address_l) + (c_L2P_MAX_PAYLOAD * 4)); l2p_address_h <= std_logic_vector(unsigned(l2p_address_h) + 1);
l2p_len_cnt <= l2p_len_cnt - c_L2P_MAX_PAYLOAD; l2p_address_l(31 downto c_L2P_MAX_PAYLOAD_NBITS) <= (others => '0');
else
l2p_address_l <= std_logic_vector(
unsigned(l2p_address_l) + (c_L2P_MAX_PAYLOAD_BYTES));
end if;
l2p_len_cnt <= l2p_len_cnt - c_L2P_MAX_PAYLOAD_WORDS;
else else
l2p_len_cnt <= (others => '0'); l2p_len_cnt <= (others => '0');
end if; end if;
......
...@@ -153,7 +153,7 @@ module main; ...@@ -153,7 +153,7 @@ module main;
initial begin initial begin
automatic int ntest = 1; automatic int ntest = 1;
const int tests = 7; const int tests = 8;
uint32_t addr, val, expected; uint32_t addr, val, expected;
...@@ -321,6 +321,48 @@ module main; ...@@ -321,6 +321,48 @@ module main;
#1us; #1us;
end end
$write("Test %0d/%0d: 256B read over DMA with 32bit host address overflow: ",
ntest++, tests);
acc.write('h14, 'h100); // count
acc.write('h20, 'h00); // attrib
acc.write('h0c, 'hffffff80); // hstartL
acc.write('h10, 'h00000000); // hstartH
acc.write('h00, 'h01); // start
// Transfer will be split internally by L2P DMA master in two requests, the first
// one with a 32-bit adress starting at ffff_ff80 and the next one with a 64-bit
// address starting at 1_0000_0000
@(posedge DUT.cmp_wrapped_gn4124.ldm_arb_dframe);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow header", 1, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'h02ff0020);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address", 1, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'hffffff80);
@(posedge DUT.cmp_wrapped_gn4124.ldm_arb_dframe);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow header", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 'h03ff0020);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address high", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 1);
@(posedge DUT.cmp_wrapped_gn4124.sys_clk);
val_check("Host address overflow address low", 2, DUT.cmp_wrapped_gn4124.ldm_arb_data, 0);
@(posedge dma_irq);
// Check irq status
reg_check('h04, 'h04);
if (dma_irq != 1'b1)
$fatal(1, "dma irq should be 1");
// clear irq
acc.write('h04, 'h04);
reg_check('h04, 'h00);
if (dma_irq != 1'b0)
$fatal(1, "dma irq should be 0");
repeat(4) @(posedge clk_125m);
$write("PASS\n");
$display(); $display();
$display("Simulation PASSED"); $display("Simulation PASSED");
......
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