|  |  |  | @ -50,6 +50,11 @@ architecture behaviour of execute1 is | 
		
	
		
			
				|  |  |  |  | 	slow_op_oe : std_ulogic; | 
		
	
		
			
				|  |  |  |  | 	slow_op_xerc : xer_common_t; | 
		
	
		
			
				|  |  |  |  |     end record; | 
		
	
		
			
				|  |  |  |  |     constant reg_type_init : reg_type := | 
		
	
		
			
				|  |  |  |  |         (e => Execute1ToWritebackInit, lr_update => '0', | 
		
	
		
			
				|  |  |  |  |          mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0', | 
		
	
		
			
				|  |  |  |  |          slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init, | 
		
	
		
			
				|  |  |  |  |          others => (others => '0')); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     signal r, rin : reg_type; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -73,6 +78,28 @@ architecture behaviour of execute1 is | 
		
	
		
			
				|  |  |  |  |     signal x_to_divider: Execute1ToDividerType; | 
		
	
		
			
				|  |  |  |  |     signal divider_to_x: DividerToExecute1Type; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     type privilege_level is (USER, SUPER); | 
		
	
		
			
				|  |  |  |  |     type op_privilege_array is array(insn_type_t) of privilege_level; | 
		
	
		
			
				|  |  |  |  |     constant op_privilege: op_privilege_array := ( | 
		
	
		
			
				|  |  |  |  |         OP_ATTN => SUPER, | 
		
	
		
			
				|  |  |  |  |         OP_MFMSR => SUPER, | 
		
	
		
			
				|  |  |  |  |         OP_MTMSRD => SUPER, | 
		
	
		
			
				|  |  |  |  |         OP_RFID => SUPER, | 
		
	
		
			
				|  |  |  |  |         others => USER | 
		
	
		
			
				|  |  |  |  |         ); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     function instr_is_privileged(op: insn_type_t; insn: std_ulogic_vector(31 downto 0)) | 
		
	
		
			
				|  |  |  |  |         return boolean is | 
		
	
		
			
				|  |  |  |  |     begin | 
		
	
		
			
				|  |  |  |  |         if op_privilege(op) = SUPER then | 
		
	
		
			
				|  |  |  |  |             return true; | 
		
	
		
			
				|  |  |  |  |         elsif op = OP_MFSPR or op = OP_MTSPR then | 
		
	
		
			
				|  |  |  |  |             return insn(20) = '1'; | 
		
	
		
			
				|  |  |  |  |         else | 
		
	
		
			
				|  |  |  |  |             return false; | 
		
	
		
			
				|  |  |  |  |         end if; | 
		
	
		
			
				|  |  |  |  |     end; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     procedure set_carry(e: inout Execute1ToWritebackType; | 
		
	
		
			
				|  |  |  |  | 			carry32 : in std_ulogic; | 
		
	
		
			
				|  |  |  |  | 			carry : in std_ulogic) is | 
		
	
	
		
			
				
					|  |  |  | @ -126,11 +153,11 @@ architecture behaviour of execute1 is | 
		
	
		
			
				|  |  |  |  | 	--  tion MSR bits are not saved or restored. | 
		
	
		
			
				|  |  |  |  | 	--  Full function MSR bits lie in the range 0:32, 37:41, and | 
		
	
		
			
				|  |  |  |  | 	--  48:63, and partial function MSR bits lie in the range | 
		
	
		
			
				|  |  |  |  | 	--  33:36 and 42:47. | 
		
	
		
			
				|  |  |  |  | 	--  33:36 and 42:47. (Note this is IBM bit numbering). | 
		
	
		
			
				|  |  |  |  | 	msr_out := (others => '0'); | 
		
	
		
			
				|  |  |  |  | 	msr_out(32 downto 0) := msr(32 downto 0); | 
		
	
		
			
				|  |  |  |  | 	msr_out(41 downto 37) := msr(41 downto 37); | 
		
	
		
			
				|  |  |  |  | 	msr_out(63 downto 48) := msr(63 downto 48); | 
		
	
		
			
				|  |  |  |  | 	msr_out(63 downto 31) := msr(63 downto 31); | 
		
	
		
			
				|  |  |  |  | 	msr_out(26 downto 22) := msr(26 downto 22); | 
		
	
		
			
				|  |  |  |  | 	msr_out(15 downto 0)  := msr(15 downto 0); | 
		
	
		
			
				|  |  |  |  | 	return msr_out; | 
		
	
		
			
				|  |  |  |  |     end; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -195,6 +222,11 @@ begin | 
		
	
		
			
				|  |  |  |  |     execute1_0: process(clk) | 
		
	
		
			
				|  |  |  |  |     begin | 
		
	
		
			
				|  |  |  |  | 	if rising_edge(clk) then | 
		
	
		
			
				|  |  |  |  |             if rst = '1' then | 
		
	
		
			
				|  |  |  |  |                 r <= reg_type_init; | 
		
	
		
			
				|  |  |  |  |                 ctrl.msr <= (MSR_SF => '1', MSR_LE => '1', others => '0'); | 
		
	
		
			
				|  |  |  |  |                 ctrl.irq_state <= WRITE_SRR0; | 
		
	
		
			
				|  |  |  |  |             else | 
		
	
		
			
				|  |  |  |  |                 r <= rin; | 
		
	
		
			
				|  |  |  |  |                 ctrl <= ctrl_tmp; | 
		
	
		
			
				|  |  |  |  |                 assert not (r.lr_update = '1' and e_in.valid = '1') | 
		
	
	
		
			
				
					|  |  |  | @ -204,6 +236,7 @@ begin | 
		
	
		
			
				|  |  |  |  |                     report "LR update to " & to_hstring(r.next_lr); | 
		
	
		
			
				|  |  |  |  |                 end if; | 
		
	
		
			
				|  |  |  |  |             end if; | 
		
	
		
			
				|  |  |  |  | 	end if; | 
		
	
		
			
				|  |  |  |  |     end process; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     execute1_1: process(all) | 
		
	
	
		
			
				
					|  |  |  | @ -372,7 +405,7 @@ begin | 
		
	
		
			
				|  |  |  |  | 	ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	irq_valid := '0'; | 
		
	
		
			
				|  |  |  |  | 	if ctrl.msr(63 - 48) = '1' then | 
		
	
		
			
				|  |  |  |  | 	if ctrl.msr(MSR_EE) = '1' then | 
		
	
		
			
				|  |  |  |  | 	    if ctrl.dec(63) = '1' then | 
		
	
		
			
				|  |  |  |  | 		ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64)); | 
		
	
		
			
				|  |  |  |  | 		report "IRQ valid: DEC"; | 
		
	
	
		
			
				
					|  |  |  | @ -409,21 +442,37 @@ begin | 
		
	
		
			
				|  |  |  |  | 	    v.e.exc_write_reg := fast_spr_num(SPR_SRR1); | 
		
	
		
			
				|  |  |  |  | 	    v.e.exc_write_data := ctrl.srr1; | 
		
	
		
			
				|  |  |  |  |             v.e.exc_write_enable := '1'; | 
		
	
		
			
				|  |  |  |  | 	    ctrl_tmp.msr(63 - 48) <= '0'; -- clear EE | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_SF) <= '1'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_EE) <= '0'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_PR) <= '0'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_IR) <= '0'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_DR) <= '0'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_RI) <= '0'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.msr(MSR_LE) <= '1'; | 
		
	
		
			
				|  |  |  |  | 	    f_out.redirect <= '1'; | 
		
	
		
			
				|  |  |  |  | 	    f_out.redirect_nia <= ctrl.irq_nia; | 
		
	
		
			
				|  |  |  |  | 	    v.e.valid := e_in.valid; | 
		
	
		
			
				|  |  |  |  | 	    report "Writing SRR1: " & to_hstring(ctrl.srr1); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	elsif irq_valid = '1' then | 
		
	
		
			
				|  |  |  |  | 	elsif irq_valid = '1' and e_in.valid = '1' then | 
		
	
		
			
				|  |  |  |  | 	    -- we need two cycles to write srr0 and 1 | 
		
	
		
			
				|  |  |  |  | 	    -- will need more when we have to write DSISR, DAR and HIER | 
		
	
		
			
				|  |  |  |  |             -- Don't deliver the interrupt until we have a valid instruction | 
		
	
		
			
				|  |  |  |  |             -- coming in, so we have a valid NIA to put in SRR0. | 
		
	
		
			
				|  |  |  |  | 	    exception := e_in.valid; | 
		
	
		
			
				|  |  |  |  | 	    exception := '1'; | 
		
	
		
			
				|  |  |  |  | 	    ctrl_tmp.srr1 <= msr_copy(ctrl.msr); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	elsif e_in.valid = '1' then | 
		
	
		
			
				|  |  |  |  |         elsif e_in.valid = '1' and ctrl.msr(MSR_PR) = '1' and | 
		
	
		
			
				|  |  |  |  |             instr_is_privileged(e_in.insn_type, e_in.insn) then | 
		
	
		
			
				|  |  |  |  |             -- generate a program interrupt | 
		
	
		
			
				|  |  |  |  |             exception := '1'; | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64)); | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.srr1 <= msr_copy(ctrl.msr); | 
		
	
		
			
				|  |  |  |  |             -- set bit 45 to indicate privileged instruction type interrupt | 
		
	
		
			
				|  |  |  |  |             ctrl_tmp.srr1(63 - 45) <= '1'; | 
		
	
		
			
				|  |  |  |  |             report "privileged instruction"; | 
		
	
		
			
				|  |  |  |  |              | 
		
	
		
			
				|  |  |  |  | 	elsif e_in.valid = '1' and e_in.unit = ALU then | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	    report "execute nia " & to_hstring(e_in.nia); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -555,7 +604,7 @@ begin | 
		
	
		
			
				|  |  |  |  | 	    when OP_B => | 
		
	
		
			
				|  |  |  |  | 		f_out.redirect <= '1'; | 
		
	
		
			
				|  |  |  |  | 		if (insn_aa(e_in.insn)) then | 
		
	
		
			
				|  |  |  |  | 		    f_out.redirect_nia <= std_ulogic_vector(signed(b_in)); | 
		
	
		
			
				|  |  |  |  | 		    f_out.redirect_nia <= b_in; | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
		
			
				|  |  |  |  | 		    f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in)); | 
		
	
		
			
				|  |  |  |  | 		end if; | 
		
	
	
		
			
				
					|  |  |  | @ -571,7 +620,7 @@ begin | 
		
	
		
			
				|  |  |  |  | 		if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then | 
		
	
		
			
				|  |  |  |  | 		    f_out.redirect <= '1'; | 
		
	
		
			
				|  |  |  |  | 		    if (insn_aa(e_in.insn)) then | 
		
	
		
			
				|  |  |  |  | 			f_out.redirect_nia <= std_ulogic_vector(signed(b_in)); | 
		
	
		
			
				|  |  |  |  | 			f_out.redirect_nia <= b_in; | 
		
	
		
			
				|  |  |  |  | 		    else | 
		
	
		
			
				|  |  |  |  | 			f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in)); | 
		
	
		
			
				|  |  |  |  | 		    end if; | 
		
	
	
		
			
				
					|  |  |  | @ -594,7 +643,17 @@ begin | 
		
	
		
			
				|  |  |  |  | 	    when OP_RFID => | 
		
	
		
			
				|  |  |  |  | 		f_out.redirect <= '1'; | 
		
	
		
			
				|  |  |  |  | 		f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0 | 
		
	
		
			
				|  |  |  |  | 		ctrl_tmp.msr <= msr_copy(std_ulogic_vector(signed(b_in))); -- srr1 | 
		
	
		
			
				|  |  |  |  |                 -- Can't use msr_copy here because the partial function MSR | 
		
	
		
			
				|  |  |  |  |                 -- bits should be left unchanged, not zeroed. | 
		
	
		
			
				|  |  |  |  |                 ctrl_tmp.msr(63 downto 31) <= b_in(63 downto 31); | 
		
	
		
			
				|  |  |  |  |                 ctrl_tmp.msr(26 downto 22) <= b_in(26 downto 22); | 
		
	
		
			
				|  |  |  |  |                 ctrl_tmp.msr(15 downto 0)  <= b_in(15 downto 0); | 
		
	
		
			
				|  |  |  |  |                 if b_in(MSR_PR) = '1' then | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(MSR_EE) <= '1'; | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(MSR_IR) <= '1'; | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(MSR_DR) <= '1'; | 
		
	
		
			
				|  |  |  |  |                 end if; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	    when OP_CMPB => | 
		
	
		
			
				|  |  |  |  | 		result := ppc_cmpb(c_in, b_in); | 
		
	
		
			
				|  |  |  |  | 		result_en := '1'; | 
		
	
	
		
			
				
					|  |  |  | @ -668,7 +727,7 @@ begin | 
		
	
		
			
				|  |  |  |  | 		    end loop; | 
		
	
		
			
				|  |  |  |  | 		end if; | 
		
	
		
			
				|  |  |  |  | 	    when OP_MFMSR => | 
		
	
		
			
				|  |  |  |  | 		result := msr_copy(ctrl.msr); | 
		
	
		
			
				|  |  |  |  | 		result := ctrl.msr; | 
		
	
		
			
				|  |  |  |  | 		result_en := '1'; | 
		
	
		
			
				|  |  |  |  | 	    when OP_MFSPR => | 
		
	
		
			
				|  |  |  |  | 		report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & | 
		
	
	
		
			
				
					|  |  |  | @ -725,8 +784,22 @@ begin | 
		
	
		
			
				|  |  |  |  | 		end if; | 
		
	
		
			
				|  |  |  |  | 		v.e.write_cr_data := c_in(31 downto 0); | 
		
	
		
			
				|  |  |  |  |             when OP_MTMSRD => | 
		
	
		
			
				|  |  |  |  | 		-- FIXME handle just the bits we need to. | 
		
	
		
			
				|  |  |  |  | 		ctrl_tmp.msr <= msr_copy(c_in); | 
		
	
		
			
				|  |  |  |  |                 if e_in.insn(16) = '1' then | 
		
	
		
			
				|  |  |  |  |                     -- just update EE and RI | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(MSR_EE) <= c_in(MSR_EE); | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(MSR_RI) <= c_in(MSR_RI); | 
		
	
		
			
				|  |  |  |  |                 else | 
		
	
		
			
				|  |  |  |  |                     -- Architecture says to leave out bits 3 (HV), 51 (ME) | 
		
	
		
			
				|  |  |  |  |                     -- and 63 (LE) (IBM bit numbering) | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(63 downto 61) <= c_in(63 downto 61); | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(59 downto 13) <= c_in(59 downto 13); | 
		
	
		
			
				|  |  |  |  |                     ctrl_tmp.msr(11 downto 1)  <= c_in(11 downto 1); | 
		
	
		
			
				|  |  |  |  |                     if c_in(MSR_PR) = '1' then | 
		
	
		
			
				|  |  |  |  |                         ctrl_tmp.msr(MSR_EE) <= '1'; | 
		
	
		
			
				|  |  |  |  |                         ctrl_tmp.msr(MSR_IR) <= '1'; | 
		
	
		
			
				|  |  |  |  |                         ctrl_tmp.msr(MSR_DR) <= '1'; | 
		
	
		
			
				|  |  |  |  |                     end if; | 
		
	
		
			
				|  |  |  |  |                 end if; | 
		
	
		
			
				|  |  |  |  | 	    when OP_MTSPR => | 
		
	
		
			
				|  |  |  |  | 		report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & | 
		
	
		
			
				|  |  |  |  | 		    "=" & to_hstring(c_in); | 
		
	
	
		
			
				
					|  |  |  | @ -781,11 +854,6 @@ begin | 
		
	
		
			
				|  |  |  |  | 		stall_out <= '1'; | 
		
	
		
			
				|  |  |  |  | 		x_to_divider.valid <= '1'; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             when OP_LOAD | OP_STORE => | 
		
	
		
			
				|  |  |  |  |                 -- loadstore/dcache has its own port to writeback | 
		
	
		
			
				|  |  |  |  |                 v.e.valid := '0'; | 
		
	
		
			
				|  |  |  |  |                 lv.valid := '1'; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |             when others => | 
		
	
		
			
				|  |  |  |  | 		terminate_out <= '1'; | 
		
	
		
			
				|  |  |  |  | 		report "illegal"; | 
		
	
	
		
			
				
					|  |  |  | @ -811,6 +879,14 @@ begin | 
		
	
		
			
				|  |  |  |  | 		report "Delayed LR update to " & to_hstring(next_nia); | 
		
	
		
			
				|  |  |  |  | 		stall_out <= '1'; | 
		
	
		
			
				|  |  |  |  | 	    end if; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         elsif e_in.valid = '1' then | 
		
	
		
			
				|  |  |  |  |             -- instruction for other units, i.e. LDST | 
		
	
		
			
				|  |  |  |  |             v.e.valid := '0'; | 
		
	
		
			
				|  |  |  |  |             if e_in.unit = LDST then | 
		
	
		
			
				|  |  |  |  |                 lv.valid := '1'; | 
		
	
		
			
				|  |  |  |  |             end if; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	elsif r.lr_update = '1' then | 
		
	
		
			
				|  |  |  |  | 	    result_en := '1'; | 
		
	
		
			
				|  |  |  |  | 	    result := r.next_lr; | 
		
	
	
		
			
				
					|  |  |  | @ -877,9 +953,7 @@ begin | 
		
	
		
			
				|  |  |  |  | 	v.e.write_enable := result_en; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         -- Outputs to loadstore1 (async) | 
		
	
		
			
				|  |  |  |  |         if e_in.insn_type = OP_LOAD then | 
		
	
		
			
				|  |  |  |  |             lv.load := '1'; | 
		
	
		
			
				|  |  |  |  |         end if; | 
		
	
		
			
				|  |  |  |  |         lv.op := e_in.insn_type; | 
		
	
		
			
				|  |  |  |  |         lv.addr1 := a_in; | 
		
	
		
			
				|  |  |  |  |         lv.addr2 := b_in; | 
		
	
		
			
				|  |  |  |  |         lv.data := c_in; | 
		
	
	
		
			
				
					|  |  |  | 
 |