@ -80,6 +80,9 @@ architecture behave of loadstore1 is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        dsisr        : std_ulogic_vector(31 downto 0);
 
					 
					 
					 
					        dsisr        : std_ulogic_vector(31 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        instr_fault  : std_ulogic;
 
					 
					 
					 
					        instr_fault  : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        sprval       : std_ulogic_vector(63 downto 0);
 
					 
					 
					 
					        sprval       : std_ulogic_vector(63 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        busy         : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        wait_dcache  : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        wait_mmu     : std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end record;
 
					 
					 
					 
					    end record;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    type byte_sel_t is array(0 to 7) of std_ulogic;
 
					 
					 
					 
					    type byte_sel_t is array(0 to 7) of std_ulogic;
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -128,6 +131,9 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        if rising_edge(clk) then
 
					 
					 
					 
					        if rising_edge(clk) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            if rst = '1' then
 
					 
					 
					 
					            if rst = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                r.state <= IDLE;
 
					 
					 
					 
					                r.state <= IDLE;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                r.busy <= '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                r.wait_dcache <= '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                r.wait_mmu <= '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            else
 
					 
					 
					 
					            else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                r <= rin;
 
					 
					 
					 
					                r <= rin;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -228,8 +234,17 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- compute (addr + 8) & ~7 for the second doubleword when unaligned
 
					 
					 
					 
					        -- compute (addr + 8) & ~7 for the second doubleword when unaligned
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        next_addr := std_ulogic_vector(unsigned(r.addr(63 downto 3)) + 1) & "000";
 
					 
					 
					 
					        next_addr := std_ulogic_vector(unsigned(r.addr(63 downto 3)) + 1) & "000";
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- Busy calculation.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- We need to minimize the delay from clock to busy valid because it
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- gates the start of execution of the next instruction.
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        busy := r.busy or (r.wait_dcache and not d_in.valid) or (r.wait_mmu and not m_in.done);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        done := '0';
 
					 
					 
					 
					        done := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if r.state /= IDLE and busy = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            done := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        exception := '0';
 
					 
					 
					 
					        exception := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        case r.state is
 
					 
					 
					 
					        case r.state is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        when IDLE =>
 
					 
					 
					 
					        when IDLE =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -255,7 +270,6 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 38) := not r.load;
 
					 
					 
					 
					                    dsisr(63 - 38) := not r.load;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    -- XXX there is no architected bit for this
 
					 
					 
					 
					                    -- XXX there is no architected bit for this
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 35) := d_in.cache_paradox;
 
					 
					 
					 
					                    dsisr(63 - 35) := d_in.cache_paradox;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                else
 
					 
					 
					 
					                else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    -- Look up the translation for TLB miss
 
					 
					 
					 
					                    -- Look up the translation for TLB miss
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    -- and also for permission error and RC error
 
					 
					 
					 
					                    -- and also for permission error and RC error
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -279,8 +293,6 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    else
 
					 
					 
					 
					                    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        -- stores write back rA update in this cycle
 
					 
					 
					 
					                        -- stores write back rA update in this cycle
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        do_update := r.update;
 
					 
					 
					 
					                        do_update := r.update;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        done := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    end if;
 
					 
					 
					 
					                    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                end if;
 
					 
					 
					 
					                end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -294,53 +306,36 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                byte_sel := r.first_bytes;
 
					 
					 
					 
					                byte_sel := r.first_bytes;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            if m_in.done = '1' then
 
					 
					 
					 
					            if m_in.done = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                if m_in.invalid = '0' and m_in.perm_error = '0' and m_in.rc_error = '0' and
 
					 
					 
					 
					                if r.instr_fault = '0' then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                    m_in.badtree = '0' and m_in.segerr = '0' then
 
					 
					 
					 
					                    -- retry the request now that the MMU has installed a TLB entry
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                    if r.instr_fault = '0' then
 
					 
					 
					 
					                    req := '1';
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                        -- retry the request now that the MMU has installed a TLB entry
 
					 
					 
					 
					                    if r.last_dword = '0' then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                        req := '1';
 
					 
					 
					 
					                        v.state := SECOND_REQ;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                        if r.last_dword = '0' then
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            v.state := SECOND_REQ;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        else
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            v.state := ACK_WAIT;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                    else
 
					 
					 
					 
					                    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        -- nothing to do, the icache retries automatically
 
					 
					 
					 
					                        v.state := ACK_WAIT;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                        done := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                    end if;
 
					 
					 
					 
					                    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                else
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    exception := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 33) := m_in.invalid;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 36) := m_in.perm_error;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 38) := not r.load;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 44) := m_in.badtree;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    dsisr(63 - 45) := m_in.rc_error;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                end if;
 
					 
					 
					 
					                end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            if m_in.err = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                exception := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                dsisr(63 - 33) := m_in.invalid;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                dsisr(63 - 36) := m_in.perm_error;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                dsisr(63 - 38) := not r.load;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                dsisr(63 - 44) := m_in.badtree;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                dsisr(63 - 45) := m_in.rc_error;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        when TLBIE_WAIT =>
 
					 
					 
					 
					        when TLBIE_WAIT =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            if m_in.done = '1' then
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                -- tlbie is finished
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                done := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        when LD_UPDATE =>
 
					 
					 
					 
					        when LD_UPDATE =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            do_update := '1';
 
					 
					 
					 
					            do_update := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            done := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        when SPR_CMPLT =>
 
					 
					 
					 
					        when SPR_CMPLT =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            done := '1';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            v.state := IDLE;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end case;
 
					 
					 
					 
					        end case;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        busy := '1';
 
					 
					 
					 
					        if done = '1' or exception = '1' then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        if r.state = IDLE or done = '1' then
 
					 
					 
					 
					            v.state := IDLE;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					            busy := '0';
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- Note that l_in.valid is gated with busy inside execute1
 
					 
					 
					 
					        -- Note that l_in.valid is gated with busy inside execute1
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -450,6 +445,31 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- Work out whether we'll be busy next cycle
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        v.busy := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        v.wait_dcache := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        v.wait_mmu := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        case v.state is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            when SECOND_REQ =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                v.busy := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            when ACK_WAIT =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                if v.last_dword = '0' or (v.load = '1' and v.update = '1') then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    v.busy := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    v.wait_dcache := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            when MMU_LOOKUP =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                if v.instr_fault = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    v.busy := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                    v.wait_mmu := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            when TLBIE_WAIT =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                v.wait_mmu := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            when others =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                -- not busy next cycle
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end case;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- Update outputs to dcache
 
					 
					 
					 
					        -- Update outputs to dcache
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        d_out.valid <= req;
 
					 
					 
					 
					        d_out.valid <= req;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        d_out.load <= v.load;
 
					 
					 
					 
					        d_out.load <= v.load;