litedram: Pipeline store acks in L2
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 10 Jun 2020 13:45:42 +0000 (23:45 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 12 Jun 2020 11:01:34 +0000 (21:01 +1000)
There is a long timing path to generate the ack signal from
the L2 cache as it's fully combinational for stores, including
signals coming from litedram.

Instead, pipeline the store acks. This will introduce a cycle
latency but should improve timing. Also the core will eventually
be smart enough not to wait for store acks to complete them anyway.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
litedram/extras/litedram-wrapper-l2.vhdl

index a6f682a8fd3d3f1763719847b2cbb9b496dd80be..33aff2859e87c6fc331cb4722e19cced1a0939ed 100644 (file)
@@ -245,13 +245,17 @@ architecture behaviour of litedram_wrapper is
     signal wb_stash : wishbone_master_out := wishbone_master_out_init;
 
     -- Read pipeline (to handle cache RAM latency)
-    signal read_ack_0  : std_ulogic;
-    signal read_ack_1  : std_ulogic;
+    signal read_ack_0  : std_ulogic := '0';
+    signal read_ack_1  : std_ulogic := '0';
     signal read_ad3_0  : std_ulogic;
     signal read_ad3_1  : std_ulogic;
     signal read_way_0  : way_t;
     signal read_way_1  : way_t;
 
+    -- Store ack pipeline
+    signal store_ack_0 : std_ulogic := '0';
+    signal store_ack_1 : std_ulogic := '0';
+
     -- Async signals decoding latched request
     type req_op_t is (OP_NONE,
                       OP_LOAD_HIT,
@@ -625,7 +629,6 @@ begin
     -- Stall when stash is full
     wb_out.stall <= wb_stash.cyc;
 
-    --
     --
     -- Read response pipeline
     --
@@ -657,6 +660,16 @@ begin
         end if;
     end process;
 
+    --
+    -- Store acks pipeline
+    --
+    store_ack_pipe: process(system_clk)
+    begin
+        if rising_edge(system_clk) then
+            store_ack_1 <= store_ack_0;
+        end if;
+    end process;
+
     wb_reponse: process(all)
         variable rdata      : std_ulogic_vector(DRAM_DBITS-1 downto 0);
         variable store_done : std_ulogic;
@@ -717,15 +730,16 @@ begin
             store_done := '0';
         end if;
 
-        -- Generate ACKs on read hits and store complete
+        -- Pipeline store acks
+        store_ack_0 <= store_done;
+
+        -- Generate Wishbone ACKs on read hits and store complete
         --
-        -- XXXX TODO: This can happen on store right behind loads !
-        -- This probably need to be fixed by putting store acks in
-        -- the same pipeline as the read acks. TOOD: Create a testbench
-        -- to exercise those corner cases as the core can't yet.
+        -- This can happen on store right behind loads ! This is why
+        -- we don't accept a new store right behind a load ack above.
         --
-        wb_out.ack <= read_ack_1 or store_done;
-        assert read_ack_0 = '0' or store_done = '0' report
+        wb_out.ack <= read_ack_1 or store_ack_1;
+        assert read_ack_1 = '0' or store_ack_1 = '0' report
             "Read ack and store ack collision !"
             severity failure;
     end process;