loadstore1: Eliminate two_dwords variable
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 10 Jul 2020 10:11:15 +0000 (20:11 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 14 Jul 2020 23:45:23 +0000 (09:45 +1000)
The computation of two_dwords from r.second_bytes has shown up as
part of a critical path at times.  Instead we add a 'last_dword'
flag to the reg_stage_t record which tells us more directly
whether a valid flag coming in from dcache means that the
instruction is done, thereby shortening the path to the busy output
back to execute1.

This also simplifies some of the trim_ctl logic.  The two_dwords = 0
case could never have use_second(i) = 1 for any of the bytes being
transferred, so "not use_second(i)" is always 1.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
loadstore1.vhdl

index cf009870b5ed3336dc8548221d1fe9d454c119c4..dd112211584e4b8f047e5007518d2aa8b2b8e606 100644 (file)
@@ -69,6 +69,7 @@ architecture behave of loadstore1 is
         priv_mode    : std_ulogic;
         state        : state_t;
         dwords_done  : std_ulogic;
+        last_dword   : std_ulogic;
         first_bytes  : std_ulogic_vector(7 downto 0);
         second_bytes : std_ulogic_vector(7 downto 0);
         dar          : std_ulogic_vector(63 downto 0);
@@ -146,7 +147,6 @@ begin
         variable wdata : std_ulogic_vector(63 downto 0);
         variable write_enable : std_ulogic;
         variable do_update : std_ulogic;
-        variable two_dwords : std_ulogic;
         variable done : std_ulogic;
         variable data_permuted : std_ulogic_vector(63 downto 0);
         variable data_trimmed : std_ulogic_vector(63 downto 0);
@@ -174,7 +174,6 @@ begin
 
         write_enable := '0';
         do_update := '0';
-        two_dwords := or (r.second_bytes);
 
         -- load data formatting
         byte_offset := unsigned(r.addr(2 downto 0));
@@ -204,10 +203,10 @@ begin
         -- trim and sign-extend
         for i in 0 to 7 loop
             if i < to_integer(unsigned(r.length)) then
-                if two_dwords = '1' then
+                if r.dwords_done = '1' then
                     trim_ctl(i) := '1' & not use_second(i);
                 else
-                    trim_ctl(i) := not use_second(i) & '0';
+                    trim_ctl(i) := "10";
                 end if;
             else
                 trim_ctl(i) := '0' & (negative and r.sign_extend);
@@ -237,6 +236,7 @@ begin
             byte_sel := r.second_bytes;
             req := '1';
             v.state := ACK_WAIT;
+            v.last_dword := '0';
 
         when ACK_WAIT =>
             if d_in.valid = '1' then
@@ -263,8 +263,9 @@ begin
                         v.state := MMU_LOOKUP;
                     end if;
                 else
-                    if two_dwords = '1' and r.dwords_done = '0' then
+                    if r.last_dword = '0' then
                         v.dwords_done := '1';
+                        v.last_dword := '1';
                         if r.load = '1' then
                             v.load_data := data_permuted;
                         end if;
@@ -297,7 +298,7 @@ begin
                     if r.instr_fault = '0' then
                         -- retry the request now that the MMU has installed a TLB entry
                         req := '1';
-                        if two_dwords = '1' and r.dwords_done = '0' then
+                        if r.last_dword = '0' then
                             v.state := SECOND_REQ;
                         else
                             v.state := ACK_WAIT;
@@ -349,6 +350,7 @@ begin
             v.tlbie := '0';
             v.instr_fault := '0';
             v.dwords_done := '0';
+            v.last_dword := '1';
             v.write_reg := l_in.write_reg;
             v.length := l_in.length;
             v.byte_reverse := l_in.byte_reverse;