]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/commitdiff
Attempt to fix forward from memory read to write over when Tumbl is being to stop.
authorPavel Pisa <ppisa@pikron.com>
Wed, 31 Dec 2014 08:12:52 +0000 (09:12 +0100)
committerPavel Pisa <ppisa@pikron.com>
Wed, 31 Dec 2014 08:12:52 +0000 (09:12 +0100)
Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/core_ctrl.vhd
hw/mbl_pkg.vhd
hw/mem.vhd

index 7e91261978b0186f83d29829f4f4f180dd72cb2d..9cd778d297ffe187d72bceeaf1701d086dffea82 100644 (file)
@@ -92,6 +92,8 @@ ARCHITECTURE rtl OF core_ctrl IS
        SIGNAL reset_s         : STD_LOGIC;
        SIGNAL core_clken_s    : STD_LOGIC;
 
+       SIGNAL EX2MEM_REG_r    : EX2MEM_Type;
+       SIGNAL MEM_REG_r       : MEM_REG_Type;
        SIGNAL ID2EX_REG_r     : ID2EX_Type;
        SIGNAL EX2IF_REG_r     : EX2IF_Type;
        SIGNAL IMM_LOCK_r      : IMM_LOCK_Type;
@@ -109,9 +111,9 @@ ARCHITECTURE rtl OF core_ctrl IS
 
        SIGNAL setup_int_r     : STD_LOGIC;
        SIGNAL int_busy_r      : STD_LOGIC;
-       SIGNAL repeat_mem_r    : STD_LOGIC;
 
        SIGNAL wait_for_mem_s  : STD_LOGIC;
+       SIGNAL finish_wrb_mem_s: STD_LOGIC;
 
 BEGIN
 
@@ -125,16 +127,21 @@ BEGIN
        core_clken_s  <= reset_s OR (((NOT trace_i) AND (NOT exeq_halt_i)) OR trace_kick_i);
        core_clken_o  <= core_clken_s;
        -- clock/wait control lines
-       clken_s        <= (NOT MEM2CTRL_i.bus_wait AND NOT MEM2CTRL_i.bus_taken) OR rst_i;
+       finish_wrb_mem_s <= NOT MEM2CTRL_i.bus_wait WHEN (MEM_REG_r.wrb_Action = WRB_MEM AND MEM2CTRL_i.bus_taken = '1') ELSE '0';
+       wait_for_mem_s <= MEM2CTRL_i.bus_wait OR MEM2CTRL_i.bus_taken;
+       clken_s        <= NOT wait_for_mem_s OR rst_i;
        clken_pipe_s   <= clken_s AND (NOT HAZARD_WRB_i.hazard);
        imem_clken_o   <= clken_pipe_s;
-       gprf_clken_o   <= clken_s;
+
+       gprf_clken_o   <= clken_s OR finish_wrb_mem_s;
        -- signals for clearing the ID2EX and EX2MEM registers during branches
        flush_ID2EX_s  <= ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch) WHEN COMPATIBILITY_MODE_g = TRUE
                                                                                ELSE ((EX2IF_REG_i.take_branch AND (NOT delayBit_r)) OR EX2IF_REG_r.take_branch OR EX2CTRL_REG_i.flush_first OR
                                                                                                flush_first_r OR ((NOT EX2CTRL_REG_i.ignore_state) AND (NOT ignore_state_r) AND flush_second_2r));
        flush_EX2MEM_s <= HAZARD_WRB_i.hazard;
        -- outputs that need to be readable too, so needing shadowing signals
+       EX2MEM_REG_o   <= EX2MEM_REG_r;
+       MEM_REG_o      <= MEM_REG_r;
        ID2EX_REG_o    <= ID2EX_REG_r;
        delay_bit_o    <= delayBit_r;
        EX2IF_REG_o    <= EX2IF_REG_r;
@@ -145,8 +152,6 @@ BEGIN
        INT_CTRL_o.rti_target  <= ID2EX_REG_r.program_counter;
        INT_CTRL_o.int_busy    <= int_busy_r;
 
-       wait_for_mem_s <= MEM2CTRL_i.bus_wait OR MEM2CTRL_i.bus_taken;
-
 regd_proc:
        PROCESS
 
@@ -190,12 +195,12 @@ regd_proc:
 
        PROCEDURE lp_rst_EX2MEM_REG IS
        BEGIN
-               EX2MEM_REG_o.mem_Action  <= NO_MEM;
-               EX2MEM_REG_o.wrb_Action  <= NO_WRB;
-               EX2MEM_REG_o.exeq_result <= (OTHERS => '0');
-               EX2MEM_REG_o.data_rD     <= (OTHERS => '0');
-               EX2MEM_REG_o.byte_Enable <= (OTHERS => '0');
-               EX2MEM_REG_o.wrix_rD     <= (OTHERS => '0');
+               EX2MEM_REG_r.mem_Action  <= NO_MEM;
+               EX2MEM_REG_r.wrb_Action  <= NO_WRB;
+               EX2MEM_REG_r.exeq_result <= (OTHERS => '0');
+               EX2MEM_REG_r.data_rD     <= (OTHERS => '0');
+               EX2MEM_REG_r.byte_Enable <= (OTHERS => '0');
+               EX2MEM_REG_r.wrix_rD     <= (OTHERS => '0');
        END PROCEDURE;
 
        PROCEDURE lp_rst_IMM_LOCK IS
@@ -227,20 +232,19 @@ regd_proc:
 
        PROCEDURE lp_rst_MEM_REG IS
        BEGIN
-               MEM_REG_o.wrb_Action  <= NO_WRB;
-               MEM_REG_o.exeq_result <= (OTHERS => '0');
-               MEM_REG_o.byte_Enable <= (OTHERS => '0');
-               MEM_REG_o.wrix_rD     <= (OTHERS => '0');
+               MEM_REG_r.wrb_Action  <= NO_WRB;
+               MEM_REG_r.exeq_result <= (OTHERS => '0');
+               MEM_REG_r.byte_Enable <= (OTHERS => '0');
+               MEM_REG_r.wrix_rD     <= (OTHERS => '0');
        END PROCEDURE;
 
        BEGIN
 
        WAIT UNTIL clk_i'event AND clk_i = '1';
 
-       IF wait_for_mem_s = '0' AND  halt_i = '0' AND core_clken_s = '1' AND repeat_mem_r = '0' THEN
-                       rst_r <= rst_i;
+       IF (wait_for_mem_s = '0' AND  halt_i = '0' AND core_clken_s = '1') OR rst_i = '1' THEN
+               rst_r <= rst_i;
 
-               repeat_mem_r  <= '0';
                IF (reset_s = '1') THEN     -- synchronous reset ...
                        lp_rst_IF2ID_REG;       -- ... so lasts at least one clock_cycle
                        lp_rst_MSR;
@@ -282,7 +286,7 @@ regd_proc:
                                END IF;
                        END IF;
                        HAZARD_WRB_r  <= HAZARD_WRB_i;
-                       MEM_REG_o     <= MEM_REG_i;
+                       MEM_REG_r     <= MEM_REG_i;
                        int_busy_r    <= ID2CTRL_i.int_busy;
                END IF;
                -- decode-to-exeq unit registers
@@ -323,24 +327,20 @@ regd_proc:
                                -- next test to prevent a flush from disrupting
                                -- the write-back pipeline
                                IF (flush_ID2EX_r = '0') THEN
-                                       EX2MEM_REG_o <= EX2MEM_REG_i;
+                                       EX2MEM_REG_r <= EX2MEM_REG_i;
                                END IF;
                                IMM_LOCK_r <= IMM_LOCK_i;
                                MSR_o      <= MSR_i;
                        END IF;
                END IF;
        ELSE
-               IF MEM_REG_i.wrb_Action = WRB_MEM THEN
-                       IF MEM2CTRL_i.bus_wait = '0' THEN
-                               MEM_REG_o.wrb_Action  <= NO_WRB;
-                               MEM_REG_o.wrix_rD     <= (OTHERS => '0');
-                       ELSIF MEM2CTRL_i.bus_taken = '1' THEN
-                               repeat_mem_r  <= '1';
-                       ELSE
-                               repeat_mem_r  <= '0';
+               IF finish_wrb_mem_s = '1' THEN
+                       MEM_REG_r.wrb_Action  <= NO_WRB;
+                       MEM_REG_r.wrix_rD     <= (OTHERS => '0');
+                       MEM_REG_r.byte_Enable <= (OTHERS => '0');
+                       IF MEM2CTRL_i.need_keep = '1' THEN
+                               EX2MEM_REG_r.data_rD <= MEM2CTRL_i.read_data;
                        END IF;
-               ELSE
-                       repeat_mem_r  <= '0';
                END IF;
        END IF;     -- rising edge clk_i ...
        END PROCESS regd_proc;
index 944ac52e6d681a3b5368b7ef7c91e7f8455ace20..78ffcdd998c569bf293423dcbbe0af26fba8db96 100644 (file)
@@ -164,6 +164,8 @@ PACKAGE mbl_pkg IS
                bus_taken   : STD_LOGIC;
                bus_wait    : STD_LOGIC;
                int         : STD_LOGIC;
+               need_keep   : STD_LOGIC;
+               read_data   : STD_LOGIC_VECTOR (31 DOWNTO 0);
        END RECORD;
 
        TYPE CORE2DMEMB_Type IS RECORD
index 4e0c848a6bb4b3c7d048a1e8a3ab418cb86cb4ec..18417293711bfec7abaf1c8a9b9c5f886e60f9ed 100644 (file)
@@ -76,6 +76,9 @@ p_mem:
                        WHEN OTHERS => dmem_data_v :=              DMEMB_i.data;
                END CASE;
 
+               MEM2CTRL_o.read_data <= dmem_data_v;
+               MEM2CTRL_o.need_keep <= '0';
+
                -- output to dmem-bus
                CASE EX2MEM_i.mem_Action IS
 
@@ -94,6 +97,7 @@ p_mem:
                                                WHEN OTHERS  =>
                                                        -- forward mem_data just read, to handle e.g. lhu rD,mem[x]; sh rD,mem[y]; ...
                                                        exeq_data_v := dmem_data_v;
+                                                       MEM2CTRL_o.need_keep <= '1';
                                        END CASE;
                                ELSE
                                        exeq_data_v := EX2MEM_i.data_rD;