@ -20,7 +20,7 @@ entity execute1 is
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						-- asynchronous
	-- asynchronous
 
			
		
	
		
		
			
				
					
						flush_out : out std_ulogic;
	flush_out : out std_ulogic;
 
			
		
	
		
		
			
				
					
						stall_out : out std_ulogic;
	busy_out : out std_ulogic;
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						e_in  : in Decode2ToExecute1Type;
	e_in  : in Decode2ToExecute1Type;
 
			
		
	
		
		
			
				
					
					        l_in  : in Loadstore1ToExecute1Type;
        l_in  : in Loadstore1ToExecute1Type;
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -48,6 +48,8 @@ end entity execute1;
 
			
		
	
		
		
			
				
					
					architecture behaviour of execute1 is
architecture behaviour of execute1 is
 
			
		
	
		
		
			
				
					
					    type reg_type is record
    type reg_type is record
 
			
		
	
		
		
			
				
					
						e : Execute1ToWritebackType;
	e : Execute1ToWritebackType;
 
			
		
	
		
		
			
				
					
					        busy: std_ulogic;
 
			
		
	
		
		
			
				
					
					        terminate: std_ulogic;
 
			
		
	
		
		
			
				
					
						lr_update : std_ulogic;
	lr_update : std_ulogic;
 
			
		
	
		
		
			
				
					
						next_lr : std_ulogic_vector(63 downto 0);
	next_lr : std_ulogic_vector(63 downto 0);
 
			
		
	
		
		
			
				
					
						mul_in_progress : std_ulogic;
	mul_in_progress : std_ulogic;
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -62,7 +64,7 @@ architecture behaviour of execute1 is
 
			
		
	
		
		
			
				
					
					        log_addr_spr : std_ulogic_vector(31 downto 0);
        log_addr_spr : std_ulogic_vector(31 downto 0);
 
			
		
	
		
		
			
				
					
					    end record;
    end record;
 
			
		
	
		
		
			
				
					
					    constant reg_type_init : reg_type :=
    constant reg_type_init : reg_type :=
 
			
		
	
		
		
			
				
					
					        (e => Execute1ToWritebackInit, lr_update => '0',
        (e => Execute1ToWritebackInit, busy => '0', lr_update => '0', terminate => '0',
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0',
         mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0',
 
			
		
	
		
		
			
				
					
					         slow_op_insn => OP_ILLEGAL, slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
         slow_op_insn => OP_ILLEGAL, slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
 
			
		
	
		
		
			
				
					
					         next_lr => (others => '0'), ldst_nia => (others => '0'), others => (others => '0'));
         next_lr => (others => '0'), ldst_nia => (others => '0'), others => (others => '0'));
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -71,6 +73,7 @@ architecture behaviour of execute1 is
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					    signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
    signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					    signal valid_in : std_ulogic;
 
			
		
	
		
		
			
				
					
					    signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
    signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
 
			
		
	
		
		
			
				
					
					    signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
    signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
 
			
		
	
		
		
			
				
					
					    signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
    signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -241,6 +244,11 @@ begin
 
			
		
	
		
		
			
				
					
					    b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2;
    b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2;
 
			
		
	
		
		
			
				
					
					    c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3;
    c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					    busy_out <= l_in.busy or r.busy;
 
			
		
	
		
		
			
				
					
					    valid_in <= e_in.valid and not busy_out;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					    terminate_out <= r.terminate;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					    execute1_0: process(clk)
    execute1_0: process(clk)
 
			
		
	
		
		
			
				
					
					    begin
    begin
 
			
		
	
		
		
			
				
					
						if rising_edge(clk) then
	if rising_edge(clk) then
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -251,7 +259,7 @@ begin
 
			
		
	
		
		
			
				
					
					            else
            else
 
			
		
	
		
		
			
				
					
					                r <= rin;
                r <= rin;
 
			
		
	
		
		
			
				
					
					                ctrl <= ctrl_tmp;
                ctrl <= ctrl_tmp;
 
			
		
	
		
		
			
				
					
					                assert not (r.lr_update = '1' and e_in.valid = '1')
                assert not (r.lr_update = '1' and valid_in = '1')
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                    report "LR update collision with valid in EX1"
                    report "LR update collision with valid in EX1"
 
			
		
	
		
		
			
				
					
					                    severity failure;
                    severity failure;
 
			
		
	
		
		
			
				
					
					                if r.lr_update = '1' then
                if r.lr_update = '1' then
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -423,9 +431,9 @@ begin
 
			
		
	
		
		
			
				
					
						    end if;
	    end if;
 
			
		
	
		
		
			
				
					
						end if;
	end if;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						terminate_out <= '0';
	v.terminate := '0';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						icache_inval <= '0';
	icache_inval <= '0';
 
			
		
	
		
		
			
				
					
						stall_out <= '0';
	v.busy := '0';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						f_out <= Execute1ToFetch1TypeInit;
	f_out <= Execute1ToFetch1TypeInit;
 
			
		
	
		
		
			
				
					
					        -- send MSR[IR] and ~MSR[PR] up to fetch1
        -- send MSR[IR] and ~MSR[PR] up to fetch1
 
			
		
	
		
		
			
				
					
					        f_out.virt_mode <= ctrl.msr(MSR_IR);
        f_out.virt_mode <= ctrl.msr(MSR_IR);
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -463,10 +471,10 @@ begin
 
			
		
	
		
		
			
				
					
					            f_out.virt_mode <= '0';
            f_out.virt_mode <= '0';
 
			
		
	
		
		
			
				
					
					            f_out.priv_mode <= '1';
            f_out.priv_mode <= '1';
 
			
		
	
		
		
			
				
					
						    f_out.redirect_nia <= ctrl.irq_nia;
	    f_out.redirect_nia <= ctrl.irq_nia;
 
			
		
	
		
		
			
				
					
						    v.e.valid := e_in.valid;
            v.e.valid := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						    report "Writing SRR1: " & to_hstring(ctrl.srr1);
	    report "Writing SRR1: " & to_hstring(ctrl.srr1);
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						elsif irq_valid = '1' and e_in.valid = '1' then
	elsif irq_valid = '1' and valid_in = '1' then
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						    -- we need two cycles to write srr0 and 1
	    -- we need two cycles to write srr0 and 1
 
			
		
	
		
		
			
				
					
						    -- will need more when we have to write HEIR
	    -- will need more when we have to write HEIR
 
			
		
	
		
		
			
				
					
					            -- Don't deliver the interrupt until we have a valid instruction
            -- Don't deliver the interrupt until we have a valid instruction
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -474,7 +482,7 @@ begin
 
			
		
	
		
		
			
				
					
						    exception := '1';
	    exception := '1';
 
			
		
	
		
		
			
				
					
						    ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
	    ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					        elsif e_in.valid = '1' and ctrl.msr(MSR_PR) = '1' and
        elsif valid_in = '1' and ctrl.msr(MSR_PR) = '1' and
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					            instr_is_privileged(e_in.insn_type, e_in.insn) then
            instr_is_privileged(e_in.insn_type, e_in.insn) then
 
			
		
	
		
		
			
				
					
					            -- generate a program interrupt
            -- generate a program interrupt
 
			
		
	
		
		
			
				
					
					            exception := '1';
            exception := '1';
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -484,7 +492,7 @@ begin
 
			
		
	
		
		
			
				
					
					            ctrl_tmp.srr1(63 - 45) <= '1';
            ctrl_tmp.srr1(63 - 45) <= '1';
 
			
		
	
		
		
			
				
					
					            report "privileged instruction";
            report "privileged instruction";
 
			
		
	
		
		
			
				
					
					            
            
 
			
		
	
		
		
			
				
					
						elsif e_in.valid = '1' and e_in.unit = ALU then
	elsif valid_in = '1' and e_in.unit = ALU then
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						    report "execute nia " & to_hstring(e_in.nia);
	    report "execute nia " & to_hstring(e_in.nia);
 
			
		
	
		
		
			
				
					
					 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -519,7 +527,7 @@ begin
 
			
		
	
		
		
			
				
					
					                -- check bits 1-10 of the instruction to make sure it's attn
                -- check bits 1-10 of the instruction to make sure it's attn
 
			
		
	
		
		
			
				
					
					                -- if not then it is illegal
                -- if not then it is illegal
 
			
		
	
		
		
			
				
					
					                if e_in.insn(10 downto 1) = "0100000000" then
                if e_in.insn(10 downto 1) = "0100000000" then
 
			
		
	
		
		
			
				
					
					                    terminate_out <= '1';
                    v.terminate := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                    report "ATTN";
                    report "ATTN";
 
			
		
	
		
		
			
				
					
					                else
                else
 
			
		
	
		
		
			
				
					
					                    illegal := '1';
                    illegal := '1';
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -674,7 +682,7 @@ begin
 
			
		
	
		
		
			
				
					
					            when OP_CNTZ =>
            when OP_CNTZ =>
 
			
		
	
		
		
			
				
					
					                v.e.valid := '0';
                v.e.valid := '0';
 
			
		
	
		
		
			
				
					
					                v.cntz_in_progress := '1';
                v.cntz_in_progress := '1';
 
			
		
	
		
		
			
				
					
					                stall_out <= '1';
                v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					            when OP_EXTS =>
            when OP_EXTS =>
 
			
		
	
		
		
			
				
					
					                -- note data_len is a 1-hot encoding
                -- note data_len is a 1-hot encoding
 
			
		
	
		
		
			
				
					
							negative := (e_in.data_len(0) and c_in(7)) or
		negative := (e_in.data_len(0) and c_in(7)) or
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -876,21 +884,21 @@ begin
 
			
		
	
		
		
			
				
					
						    when OP_MUL_L64 | OP_MUL_H64 | OP_MUL_H32 =>
	    when OP_MUL_L64 | OP_MUL_H64 | OP_MUL_H32 =>
 
			
		
	
		
		
			
				
					
							v.e.valid := '0';
		v.e.valid := '0';
 
			
		
	
		
		
			
				
					
							v.mul_in_progress := '1';
		v.mul_in_progress := '1';
 
			
		
	
		
		
			
				
					
							stall_out <= '1';
		v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							x_to_multiply.valid <= '1';
		x_to_multiply.valid <= '1';
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						    when OP_DIV | OP_DIVE | OP_MOD =>
	    when OP_DIV | OP_DIVE | OP_MOD =>
 
			
		
	
		
		
			
				
					
							v.e.valid := '0';
		v.e.valid := '0';
 
			
		
	
		
		
			
				
					
							v.div_in_progress := '1';
		v.div_in_progress := '1';
 
			
		
	
		
		
			
				
					
							stall_out <= '1';
		v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							x_to_divider.valid <= '1';
		x_to_divider.valid <= '1';
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					            when others =>
            when others =>
 
			
		
	
		
		
			
				
					
							terminate_out <= '1';
		v.terminate := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							report "illegal";
		report "illegal";
 
			
		
	
		
		
			
				
					
						    end case;
	    end case;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						    v.e.rc := e_in.rc and e_in.valid;
	    v.e.rc := e_in.rc and valid_in;
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						    -- Update LR on the next cycle after a branch link
	    -- Update LR on the next cycle after a branch link
 
			
		
	
		
		
			
				
					
						    --
	    --
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -908,10 +916,10 @@ begin
 
			
		
	
		
		
			
				
					
							v.next_lr := next_nia;
		v.next_lr := next_nia;
 
			
		
	
		
		
			
				
					
							v.e.valid := '0';
		v.e.valid := '0';
 
			
		
	
		
		
			
				
					
							report "Delayed LR update to " & to_hstring(next_nia);
		report "Delayed LR update to " & to_hstring(next_nia);
 
			
		
	
		
		
			
				
					
							stall_out <= '1';
		v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						    end if;
	    end if;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					        elsif e_in.valid = '1' then
        elsif valid_in = '1' then
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					            -- instruction for other units, i.e. LDST
            -- instruction for other units, i.e. LDST
 
			
		
	
		
		
			
				
					
					            v.ldst_nia := e_in.nia;
            v.ldst_nia := e_in.nia;
 
			
		
	
		
		
			
				
					
					            v.e.valid := '0';
            v.e.valid := '0';
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -967,7 +975,7 @@ begin
 
			
		
	
		
		
			
				
					
							end if;
		end if;
 
			
		
	
		
		
			
				
					
							v.e.valid := '1';
		v.e.valid := '1';
 
			
		
	
		
		
			
				
					
						    else
	    else
 
			
		
	
		
		
			
				
					
							stall_out <= '1';
		v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							v.mul_in_progress := r.mul_in_progress;
		v.mul_in_progress := r.mul_in_progress;
 
			
		
	
		
		
			
				
					
							v.div_in_progress := r.div_in_progress;
		v.div_in_progress := r.div_in_progress;
 
			
		
	
		
		
			
				
					
						    end if;
	    end if;
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -988,7 +996,8 @@ begin
 
			
		
	
		
		
			
				
					
					                v.e.exc_write_data := next_nia;
                v.e.exc_write_data := next_nia;
 
			
		
	
		
		
			
				
					
					            end if;
            end if;
 
			
		
	
		
		
			
				
					
					            ctrl_tmp.irq_state <= WRITE_SRR1;
            ctrl_tmp.irq_state <= WRITE_SRR1;
 
			
		
	
		
		
			
				
					
					            v.e.valid := '1';
            v.busy := '1';
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					            v.e.valid := '0';
 
			
		
	
		
		
			
				
					
						end if;
	end if;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
						v.e.write_data := result;
	v.e.write_data := result;
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -1020,7 +1029,6 @@ begin
 
			
		
	
		
		
			
				
					
					            v.e.exc_write_data := r.ldst_nia;
            v.e.exc_write_data := r.ldst_nia;
 
			
		
	
		
		
			
				
					
					            report "ldst exception writing srr0=" & to_hstring(r.ldst_nia);
            report "ldst exception writing srr0=" & to_hstring(r.ldst_nia);
 
			
		
	
		
		
			
				
					
					            ctrl_tmp.irq_state <= WRITE_SRR1;
            ctrl_tmp.irq_state <= WRITE_SRR1;
 
			
		
	
		
		
			
				
					
					            v.e.valid := '1';   -- complete the original load or store
 
			
		
	
		
		
			
				
					
					        end if;
        end if;
 
			
		
	
		
		
			
				
					
					 
			
		
	
		
		
			
				
					
					        -- Outputs to loadstore1 (async)
        -- Outputs to loadstore1 (async)
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -1072,7 +1080,7 @@ begin
 
			
		
	
		
		
			
				
					
					                        r.e.write_enable &
                        r.e.write_enable &
 
			
		
	
		
		
			
				
					
					                        r.e.valid &
                        r.e.valid &
 
			
		
	
		
		
			
				
					
					                        f_out.redirect &
                        f_out.redirect &
 
			
		
	
		
		
			
				
					
					                        stall_out &
                        r.busy &
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                        flush_out;
                        flush_out;
 
			
		
	
		
		
			
				
					
					        end if;
        end if;
 
			
		
	
		
		
			
				
					
					    end process;
    end process;