dcache: Remove dependency of r1.wb.adr/dat/sel on req_op
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 10 Jul 2020 23:10:24 +0000 (09:10 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 14 Jul 2020 23:48:43 +0000 (09:48 +1000)
This improves timing by setting r1.wb.{adr,dat,sel} to the next
request when doing a write cycle on the wishbone before we know
whether the next request has a TLB and cache hit or not, i.e.
without depending on req_op.  r1.wb.stb still depends on req_op.

This contains a workaround for what is probably a bug elsewhere,
in that changing r1.wb.sel unconditionally once we see stall=0
from the wishbone causes incorrect behaviour.  Making it
conditional on there being a valid following request appears
to fix the problem.

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

index 4d9843ebf6616755bfdc491bdac3c1cd5675b1ca..4c1db9b64f73429c10f8417d05497eededd3d07d 100644 (file)
@@ -226,6 +226,7 @@ architecture rtl of dcache is
 
     type mem_access_request_t is record
         op        : op_t;
+        valid     : std_ulogic;
         dcbz      : std_ulogic;
         real_addr : std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
         data      : std_ulogic_vector(63 downto 0);
@@ -309,6 +310,7 @@ architecture rtl of dcache is
     signal req_op      : op_t;
     signal req_data    : std_ulogic_vector(63 downto 0);
     signal req_same_tag : std_ulogic;
+    signal req_go      : std_ulogic;
 
     signal early_req_row  : row_t;
 
@@ -856,6 +858,7 @@ begin
             end if;
         end if;
        req_op <= op;
+        req_go <= go;
 
         -- Version of the row number that is valid one cycle earlier
         -- in the cases where we need to read the cache data BRAM.
@@ -1240,6 +1243,7 @@ begin
                     req := r1.req;
                 else
                     req.op := req_op;
+                    req.valid := req_go;
                     req.dcbz := r0.req.dcbz;
                     req.real_addr := ra;
                     req.data := r0.req.data;
@@ -1402,11 +1406,14 @@ begin
                     if wishbone_in.stall = '0' then
                         -- See if there is another store waiting to be done
                         -- which is in the same real page.
-                        if acks < 7 and req.same_tag = '1' and
-                            (req.op = OP_STORE_MISS or req.op = OP_STORE_HIT) then
-                            r1.wb.adr <= req.real_addr(r1.wb.adr'left downto 0);
+                        if req.valid = '1' then
+                            r1.wb.adr(SET_SIZE_BITS - 1 downto 0) <=
+                                req.real_addr(SET_SIZE_BITS - 1 downto 0);
                             r1.wb.dat <= req.data;
                             r1.wb.sel <= req.byte_sel;
+                        end if;
+                        if acks < 7 and req.same_tag = '1' and
+                            (req.op = OP_STORE_MISS or req.op = OP_STORE_HIT) then
                             r1.wb.stb <= '1';
                             stbs_done := false;
                             if req.op = OP_STORE_HIT then