From ea0b843662b37dbf36c09d8837408cf29ef2b897 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 18 Jul 2020 16:37:03 +1000 Subject: [PATCH] loadstore1: Better expression for store data formatting This rearranges the code used for store data formatting so that the "for i in 0 to 7" loop indexes the output bytes rather than the input bytes. The new expression is formally identical to the old but is easier to synthesize. This reduces the number of LUTs by about 250 on the Artix-7 and improves timing. Signed-off-by: Paul Mackerras --- loadstore1.vhdl | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 87f4710..62914c0 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -159,6 +159,7 @@ begin variable done : std_ulogic; variable data_permuted : std_ulogic_vector(63 downto 0); variable data_trimmed : std_ulogic_vector(63 downto 0); + variable store_data : std_ulogic_vector(63 downto 0); variable use_second : byte_sel_t; variable trim_ctl : trim_ctl_t; variable negative : std_ulogic; @@ -232,6 +233,23 @@ begin end case; end loop; + -- Byte reversing and rotating for stores + -- Done in the first cycle (when l_in.valid = 1) + store_data := r.store_data; + if l_in.valid = '1' then + byte_offset := unsigned(lsu_sum(2 downto 0)); + brev_lenm1 := "000"; + if l_in.byte_reverse = '1' then + brev_lenm1 := unsigned(l_in.length(2 downto 0)) - 1; + end if; + for i in 0 to 7 loop + k := (to_unsigned(i, 3) - byte_offset) xor brev_lenm1; + j := to_integer(k) * 8; + store_data(i * 8 + 7 downto i * 8) := l_in.data(j + 7 downto j); + end loop; + end if; + v.store_data := store_data; + -- compute (addr + 8) & ~7 for the second doubleword when unaligned next_addr := std_ulogic_vector(unsigned(r.addr(63 downto 3)) + 1) & "000"; @@ -379,18 +397,6 @@ begin v.first_bytes := byte_sel; v.second_bytes := long_sel(15 downto 8); - -- Do byte reversing and rotating for stores in the first cycle - byte_offset := unsigned(lsu_sum(2 downto 0)); - brev_lenm1 := "000"; - if l_in.byte_reverse = '1' then - brev_lenm1 := unsigned(l_in.length(2 downto 0)) - 1; - end if; - for i in 0 to 7 loop - k := (to_unsigned(i, 3) xor brev_lenm1) + byte_offset; - j := to_integer(k) * 8; - v.store_data(j + 7 downto j) := l_in.data(i * 8 + 7 downto i * 8); - end loop; - case l_in.op is when OP_STORE => req := '1'; @@ -465,7 +471,7 @@ begin d_out.nc <= v.nc; d_out.reserve <= v.reserve; d_out.addr <= addr; - d_out.data <= v.store_data; + d_out.data <= store_data; d_out.byte_sel <= byte_sel; d_out.virt_mode <= v.virt_mode; d_out.priv_mode <= v.priv_mode;