-- © IBM Corp. 2020 -- Licensed under the Apache License, Version 2.0 (the "License"), as modified by -- the terms below; you may not use the files in this repository except in -- compliance with the License as modified. -- You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -- -- Modified Terms: -- -- 1) For the purpose of the patent license granted to you in Section 3 of the -- License, the "Work" hereby includes implementations of the work of authorship -- in physical form. -- -- 2) Notwithstanding any terms to the contrary in the License, any licenses -- necessary for implementation of the Work that are available from OpenPOWER -- via the Power ISA End User License Agreement (EULA) are explicitly excluded -- hereunder, and may be obtained from OpenPOWER under the terms and conditions -- of the EULA. -- -- Unless required by applicable law or agreed to in writing, the reference design -- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License -- for the specific language governing permissions and limitations under the License. -- -- Additional rights, including the ability to physically implement a softcore that -- is compliant with the required sections of the Power ISA Specification, are -- available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be -- obtained (along with the Power ISA) here: https://openpowerfoundation.org. -- Description: XU Branch Unit -- library ieee,ibm,support,work,tri; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use support.power_logic_pkg.all; use ibm.std_ulogic_support.all; use ibm.std_ulogic_function_support.all; use tri.tri_latches_pkg.all; use work.xuq_pkg.all; entity xuq_cpl_br is generic( expand_type : integer := 2; threads : integer := 4; eff_ifar : integer := 62; uc_ifar : integer := 21; regsize : integer := 64); port( -- Clocks nclk : in clk_logic; -- Pervasive d_mode_dc : in std_ulogic; delay_lclkr_dc : in std_ulogic; mpw1_dc_b : in std_ulogic; mpw2_dc_b : in std_ulogic; func_sl_thold_0_b : in std_ulogic; func_sl_force : in std_ulogic; sg_0 : in std_ulogic; scan_in : in std_ulogic; scan_out : out std_ulogic; rf1_act : in std_ulogic; ex1_act : in std_ulogic; rf1_tid : in std_ulogic_vector(0 to threads-1); ex1_tid : in std_ulogic_vector(0 to threads-1); ex1_xu_val : in std_ulogic_vector(0 to threads-1); dec_cpl_rf1_ifar : in std_ulogic_vector(62-eff_ifar to 61); ex1_xu_ifar : out std_ulogic_vector(62-eff_ifar to 61); dec_cpl_rf1_pred_taken_cnt : in std_ulogic; dec_cpl_rf1_instr : in std_ulogic_vector(0 to 31); byp_cpl_ex1_cr_bit : in std_ulogic; spr_lr : in std_ulogic_vector(0 to regsize*threads-1); spr_ctr : in std_ulogic_vector(0 to regsize*threads-1); ex2_br_flush : out std_ulogic_vector(0 to threads-1); ex2_br_flush_ifar : out std_ulogic_vector(62-eff_ifar to 61); ex1_branch : out std_ulogic; ex1_br_mispred : out std_ulogic; ex1_br_taken : out std_ulogic; ex1_br_update : out std_ulogic; ex1_is_bcctr : out std_ulogic; ex1_is_bclr : out std_ulogic; ex1_lr_update : out std_ulogic; ex1_ctr_dec_update : out std_ulogic; ex1_instr : out std_ulogic_vector(0 to 31); spr_msr_cm : in std_ulogic_vector(0 to threads-1); br_debug : out std_ulogic_vector(0 to 11); -- Power vdd : inout power_logic; gnd : inout power_logic ); end xuq_cpl_br; architecture xuq_cpl_br of xuq_cpl_br is signal ex1_instr_q : std_ulogic_vector(0 to 31); signal ex1_is_b_q : std_ulogic; signal ex1_is_bcctr_q : std_ulogic; signal ex1_is_bclr_q : std_ulogic; signal ex1_ctr_ok_q, ex1_ctr_ok_d : std_ulogic; signal ex1_pred_taken_cnt_q : std_ulogic; signal ex1_is_branch_cond_q, ex1_is_branch_cond_d : std_ulogic; signal ex1_xu_ifar_q : std_ulogic_vector(62-eff_ifar to 61); signal ex2_br_flush_q, ex2_br_flush_d : std_ulogic_vector(0 to threads-1); signal ex2_br_flush_ifar_q, ex2_br_flush_ifar_d : std_ulogic_vector(62-eff_ifar to 61); -- Scanchains constant ex1_instr_offset : integer := 0; constant ex1_is_b_offset : integer := ex1_instr_offset + ex1_instr_q'length; constant ex1_is_bcctr_offset : integer := ex1_is_b_offset + 1; constant ex1_is_bclr_offset : integer := ex1_is_bcctr_offset + 1; constant ex1_ctr_ok_offset : integer := ex1_is_bclr_offset + 1; constant ex1_pred_taken_cnt_offset : integer := ex1_ctr_ok_offset + 1; constant ex1_is_branch_cond_offset : integer := ex1_pred_taken_cnt_offset + 1; constant ex1_ifar_offset : integer := ex1_is_branch_cond_offset + 1; constant ex2_br_flush_offset : integer := ex1_ifar_offset + ex1_xu_ifar_q'length; constant ex2_br_flush_ifar_offset : integer := ex2_br_flush_offset + ex2_br_flush_q'length; constant scan_right : integer := ex2_br_flush_ifar_offset + ex2_br_flush_ifar_q'length; -- Scanchains signal siv : std_ulogic_vector(0 to scan_right-1); signal sov : std_ulogic_vector(0 to scan_right-1); -- Signals signal tiup : std_ulogic; signal rf1_ctr : std_ulogic_vector(64-regsize to 63); signal rf1_instr : std_ulogic_vector(0 to 31); signal rf1_msr_cm : std_ulogic; signal rf1_opcode_is_19 : boolean; signal rf1_is_b,rf1_is_bc,rf1_is_bcctr,rf1_is_bclr : std_ulogic; signal rf1_ctr_low_zero, rf1_ctr_hi_zero : std_ulogic; signal rf1_ctr_zero, rf1_ctr_one, rf1_ctr_one_b : std_ulogic; signal ex1_br_mispred_int,ex1_bcctr_flush : std_ulogic; signal ex1_imm,ex1_cia : std_ulogic_vector(62-eff_ifar to 61); signal ex1_br_t_trgt,ex1_br_nt_trgt,ex1_br_imm_trgt: std_ulogic_vector(62-eff_ifar to 61); signal ex1_br_flush_ifar : std_ulogic_vector(62-eff_ifar to 61); signal ex1_lr,ex1_ctr : std_ulogic_vector(64-regsize to 63); signal ex1_taken : std_ulogic; begin tiup <= '1'; rf1_instr <= dec_cpl_rf1_instr; -- T(AA=1) T(AA=0) NT --========================================================== -- b IMM(6:29) CIA+IMM(6:29) N/A -- bc IMM(16:29) CIA+IMM(16:29) CIA+4 -- bclr LR CIA+4 -- bcctr CTR CIA+4 -- Deocodes rf1_opcode_is_19 <= rf1_instr( 0 to 5) = "010011"; -- 19 rf1_is_b <= '1' when rf1_instr( 0 to 5) = "010010" else '0'; -- 18 rf1_is_bc <= '1' when rf1_instr( 0 to 5) = "010000" else '0'; -- 16 rf1_is_bcctr <= '1' when rf1_opcode_is_19 and rf1_instr(21 to 30) = "1000010000" else '0'; -- 19/528 rf1_is_bclr <= '1' when rf1_opcode_is_19 and rf1_instr(21 to 30) = "0000010000" else '0'; -- 19/16 -- The CTR is always decremented before the test rf1_msr_cm <= or_reduce(spr_msr_cm and rf1_tid); rf1_ctr <= mux_t(spr_ctr,rf1_tid); rf1_ctr_low_zero <= not or_reduce(rf1_ctr(32 to 62)); xuq_cpl_ctr_cmp_0 : if regsize > 32 generate rf1_ctr_hi_zero <= not or_reduce(rf1_ctr(64-regsize to 31)); end generate; xuq_cpl_ctr_cmp_1 : if regsize <= 32 generate rf1_ctr_hi_zero <= '1'; end generate; rf1_ctr_zero <= rf1_ctr_low_zero and (rf1_ctr_hi_zero or not rf1_msr_cm); rf1_ctr_one <= rf1_ctr_zero and rf1_ctr(63); rf1_ctr_one_b <= not rf1_ctr_one; ex1_ctr_ok_d <= rf1_instr(8) or (rf1_ctr_one_b xor rf1_instr(9)); ex1_taken <= (ex1_instr_q(6) or (byp_cpl_ex1_cr_bit xnor ex1_instr_q(7))) and ex1_ctr_ok_q; ex1_is_branch_cond_d <= rf1_is_bc or rf1_is_bclr or rf1_is_bcctr; ex1_cia <= ex1_xu_ifar_q and not (62-eff_ifar to 61=>ex1_instr_q(30)); ex1_imm(62-eff_ifar to 37) <= (others=>ex1_imm(38)); with ex1_is_b_q select ex1_imm(38 to 47) <= ex1_instr_q( 6 to 15) when '1', (38 to 47=>ex1_imm(48)) when others; ex1_imm(48 to 61) <= ex1_instr_q(16 to 29); ex1_br_nt_trgt <= std_ulogic_vector(unsigned(ex1_xu_ifar_q) + 1); ex1_br_imm_trgt <= std_ulogic_vector(unsigned(ex1_cia) + unsigned(ex1_imm)); ex1_lr <= mux_t(spr_lr,ex1_tid); ex1_ctr <= mux_t(spr_ctr,ex1_tid); with s2'(ex1_is_bcctr_q & ex1_is_bclr_q) select ex1_br_t_trgt <= ex1_ctr(64-regsize to 61) when "10", ex1_lr(64-regsize to 61) when "01", ex1_br_imm_trgt when others; with (ex1_is_b_q or ex1_taken) select ex1_br_flush_ifar <= ex1_br_t_trgt when '1', ex1_br_nt_trgt when others; ex2_br_flush_ifar_d <= ex1_br_flush_ifar; ex1_br_mispred_int <= ex1_is_branch_cond_q and (ex1_taken xor ex1_pred_taken_cnt_q); ex1_bcctr_flush <= ex1_is_bcctr_q and ex1_taken; ex2_br_flush_d <= ex1_xu_val and (0 to threads-1=>(ex1_br_mispred_int or ex1_bcctr_flush)); ex2_br_flush_ifar <= ex2_br_flush_ifar_q; ex2_br_flush <= ex2_br_flush_q; ex1_xu_ifar <= ex1_xu_ifar_q; ex1_branch <= ex1_is_branch_cond_q or ex1_is_b_q; ex1_br_mispred <= ex1_br_mispred_int; ex1_br_taken <= (ex1_taken and ex1_is_branch_cond_q) or ex1_is_b_q; ex1_br_update <= ex1_is_b_q or (ex1_is_branch_cond_q and ex1_taken); ex1_is_bcctr <= ex1_is_bcctr_q; ex1_is_bclr <= ex1_is_bclr_q; ex1_ctr_dec_update <= ex1_is_branch_cond_q and not ex1_instr_q(8); -- !B02 ex1_lr_update <= (ex1_is_branch_cond_q or ex1_is_b_q) and ex1_instr_q(31); ex1_instr <= ex1_instr_q; mark_unused(ex1_lr(62 to 63)); mark_unused(ex1_ctr(62 to 63)); br_debug <= rf1_msr_cm & rf1_ctr_low_zero & rf1_ctr_hi_zero & rf1_ctr_one & ex1_ctr_ok_q & ex1_taken & ex1_pred_taken_cnt_q & byp_cpl_ex1_cr_bit & ex2_br_flush_q; -- Latch Instances ex1_instr_latch : tri_rlmreg_p generic map (width => ex1_instr_q'length, init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_instr_offset to ex1_instr_offset + ex1_instr_q'length-1), scout => sov(ex1_instr_offset to ex1_instr_offset + ex1_instr_q'length-1), din => rf1_instr, dout => ex1_instr_q); ex1_is_b_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_is_b_offset), scout => sov(ex1_is_b_offset), din => rf1_is_b, dout => ex1_is_b_q); ex1_is_bcctr_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_is_bcctr_offset), scout => sov(ex1_is_bcctr_offset), din => rf1_is_bcctr, dout => ex1_is_bcctr_q); ex1_is_bclr_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_is_bclr_offset), scout => sov(ex1_is_bclr_offset), din => rf1_is_bclr, dout => ex1_is_bclr_q); ex1_ctr_ok_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_ctr_ok_offset), scout => sov(ex1_ctr_ok_offset), din => ex1_ctr_ok_d, dout => ex1_ctr_ok_q); ex1_pred_taken_cnt_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_pred_taken_cnt_offset), scout => sov(ex1_pred_taken_cnt_offset), din => dec_cpl_rf1_pred_taken_cnt, dout => ex1_pred_taken_cnt_q); ex1_is_branch_cond_latch : tri_rlmlatch_p generic map (init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_is_branch_cond_offset), scout => sov(ex1_is_branch_cond_offset), din => ex1_is_branch_cond_d, dout => ex1_is_branch_cond_q); ex1_ifar_latch : tri_rlmreg_p generic map (width => ex1_xu_ifar_q'length, init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => rf1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex1_ifar_offset to ex1_ifar_offset + ex1_xu_ifar_q'length-1), scout => sov(ex1_ifar_offset to ex1_ifar_offset + ex1_xu_ifar_q'length-1), din => dec_cpl_rf1_ifar, dout => ex1_xu_ifar_q); ex2_br_flush_latch : tri_rlmreg_p generic map (width => ex2_br_flush_q'length, init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => tiup, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex2_br_flush_offset to ex2_br_flush_offset + ex2_br_flush_q'length-1), scout => sov(ex2_br_flush_offset to ex2_br_flush_offset + ex2_br_flush_q'length-1), din => ex2_br_flush_d, dout => ex2_br_flush_q); ex2_br_flush_ifar_latch : tri_rlmreg_p generic map (width => ex2_br_flush_ifar_q'length, init => 0, expand_type => expand_type, needs_sreset => 1) port map (nclk => nclk, vd => vdd, gd => gnd, act => ex1_act, forcee => func_sl_force, d_mode => d_mode_dc, delay_lclkr => delay_lclkr_dc, mpw1_b => mpw1_dc_b, mpw2_b => mpw2_dc_b, thold_b => func_sl_thold_0_b, sg => sg_0, scin => siv(ex2_br_flush_ifar_offset to ex2_br_flush_ifar_offset + ex2_br_flush_ifar_q'length-1), scout => sov(ex2_br_flush_ifar_offset to ex2_br_flush_ifar_offset + ex2_br_flush_ifar_q'length-1), din => ex2_br_flush_ifar_d, dout => ex2_br_flush_ifar_q); siv(0 to scan_right-1) <= sov(1 to scan_right-1) & scan_in; scan_out <= sov(0); end architecture xuq_cpl_br;