dcache: Fix obscure bug and minor cleanups
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 21 Feb 2020 01:34:23 +0000 (12:34 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 21 Feb 2020 01:34:23 +0000 (12:34 +1100)
The obscure bug is that a non-cacheable load with update would never
do the update and would never complete the instruction.  This is fixed
by making state NC_LOAD_WAIT_ACK go to LOAD_UPDATE2 if r1.req.update
is set.

The slow load forms with update can go to LOAD_UPDATE2 at the end
rather than LOAD_UPDATE, thus saving a cycle.  Loads with a cache
hit need the LOAD_UPDATE state in the third cycle since they are
not writing back until the 4th cycle, when the state is LOAD_UPDATE2.
Slow loads (cacheable loads that miss and non-cacheable loads)
currently go to LOAD_UPDATE in the cycle after they see
r1.wb.ack = 1 for the last time, but that cycle is the cycle where
they write back, and the following cycle does nothing.  Going to
LOAD_UPDATE2 in those cases saves a cycle and makes them consistent
with the load hit case.

The logic in the RELOAD_WAIT_ACK case doesn't need to check
r1.req.load = '1' since we only ever use RELOAD_WAIT_ACK for loads.

There are also some whitespace fixes and a typo fix.

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

index df54c955ad2ec7746c6361b660ffbf1e955df9d6..ddc4769edb319d4218a9d39412fe8c0dd727c52a 100644 (file)
@@ -500,7 +500,7 @@ begin
            -- If it's not a load with update, complete it now
            if r2.load_is_update = '0' then
                d_out.valid <= '1';
-               end if;
+            end if;
        end if;
 
        -- Slow ops (load miss, NC, stores)
@@ -508,7 +508,7 @@ begin
            -- If it's a load, enable register writeback and switch
            -- mux accordingly
            --
-           if r1.req.load then     
+           if r1.req.load then
                d_out.write_reg <= r1.req.write_reg;
                d_out.write_enable <= '1';
 
@@ -679,7 +679,7 @@ begin
     end process;
 
     --
-    -- Every other case is handled by this stage machine:
+    -- Every other case is handled by this state machine:
     --
     --   * Cache load miss/reload (in conjunction with "rams")
     --   * Load hits for update forms
@@ -835,8 +835,8 @@ begin
                            -- we also need to do the deferred update cycle.
                            --
                            r1.slow_valid <= '1';
-                           if r1.req.load = '1' and r1.req.update = '1' then
-                               r1.state <= LOAD_UPDATE;
+                           if r1.req.update = '1' then
+                               r1.state <= LOAD_UPDATE2;
                                report "completing miss with load-update !";
                            else
                                r1.state <= IDLE;
@@ -864,13 +864,16 @@ begin
 
                    -- Got ack ? complete.
                    if wishbone_in.ack = '1' then
+                       r1.state <= IDLE;
                        if r1.state = NC_LOAD_WAIT_ACK then
                            r1.slow_data <= wishbone_in.dat;
+                            if r1.req.update = '1' then
+                                r1.state <= LOAD_UPDATE2;
+                            end if;
                        end if;
                        r1.slow_valid <= '1';
                        r1.wb.cyc <= '0';
                        r1.wb.stb <= '0';
-                       r1.state <= IDLE;
                    end if;
                end case;
            end if;