You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
19 KiB
VHDL

-- © 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;