Move LR, CTR and TAR out of the register file

By putting CTR on the odd side and LR and TAR on the even side, we can
read and write CTR for bdnz-style instructions in parallel with
reading LR or TAR for indirect branches and writing LR for branches
with LK=1.  Thus we don't need to double up any of these instructions,
giving a simplification in decode2.

We now have logic for printing LR and CTR at the end of a simulation
in execute1, in addition to the similar logic in register_file and
cr_file.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/379/head
Paul Mackerras 2 years ago
parent bc4d02cb0d
commit 337b104250

@ -132,12 +132,15 @@ package common is
constant RAMSPR_SPRG0 : ramspr_index := 2; constant RAMSPR_SPRG0 : ramspr_index := 2;
constant RAMSPR_SPRG2 : ramspr_index := 3; constant RAMSPR_SPRG2 : ramspr_index := 3;
constant RAMSPR_HSPRG0 : ramspr_index := 4; constant RAMSPR_HSPRG0 : ramspr_index := 4;
constant RAMSPR_LR : ramspr_index := 5; -- must equal RAMSPR_CTR
constant RAMSPR_TAR : ramspr_index := 6;
-- Odd half: -- Odd half:
constant RAMSPR_SRR1 : ramspr_index := 0; constant RAMSPR_SRR1 : ramspr_index := 0;
constant RAMSPR_HSRR1 : ramspr_index := 1; constant RAMSPR_HSRR1 : ramspr_index := 1;
constant RAMSPR_SPRG1 : ramspr_index := 2; constant RAMSPR_SPRG1 : ramspr_index := 2;
constant RAMSPR_SPRG3 : ramspr_index := 3; constant RAMSPR_SPRG3 : ramspr_index := 3;
constant RAMSPR_HSPRG1 : ramspr_index := 4; constant RAMSPR_HSPRG1 : ramspr_index := 4;
constant RAMSPR_CTR : ramspr_index := 5; -- must equal RAMSPR_LR


type ram_spr_info is record type ram_spr_info is record
index : ramspr_index; index : ramspr_index;
@ -322,7 +325,6 @@ package common is
rc: std_ulogic; rc: std_ulogic;
oe: std_ulogic; oe: std_ulogic;
invert_a: std_ulogic; invert_a: std_ulogic;
addm1 : std_ulogic;
invert_out: std_ulogic; invert_out: std_ulogic;
input_carry: carry_in_t; input_carry: carry_in_t;
output_carry: std_ulogic; output_carry: std_ulogic;
@ -350,11 +352,12 @@ package common is
ramspr_wraddr : ramspr_index; ramspr_wraddr : ramspr_index;
ramspr_write_even : std_ulogic; ramspr_write_even : std_ulogic;
ramspr_write_odd : std_ulogic; ramspr_write_odd : std_ulogic;
dec_ctr : std_ulogic;
end record; end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type := constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init, (valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
write_reg_enable => '0', write_reg_enable => '0',
lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0', addm1 => '0', lr => '0', br_abs => '0', rc => '0', oe => '0', invert_a => '0',
invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0', invert_out => '0', input_carry => ZERO, output_carry => '0', input_cr => '0',
output_cr => '0', output_xer => '0', output_cr => '0', output_xer => '0',
is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0', is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0',
@ -366,6 +369,7 @@ package common is
spr_is_ram => '0', spr_is_ram => '0',
ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0', ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0',
ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0', ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0',
dec_ctr => '0',
others => (others => '0')); others => (others => '0'));


type MultiplyInputType is record type MultiplyInputType is record
@ -780,25 +784,8 @@ package body common is
return to_integer(unsigned(insn(15 downto 11) & insn(20 downto 16))); return to_integer(unsigned(insn(15 downto 11) & insn(20 downto 16)));
end; end;
function fast_spr_num(spr: spr_num_t) return gspr_index_t is function fast_spr_num(spr: spr_num_t) return gspr_index_t is
variable n : integer range 0 to 31;
-- tmp variable introduced as workaround for VCS compilation
-- simulation was failing with subtype constraint mismatch error
-- see GitHub PR #173
variable tmp : std_ulogic_vector(4 downto 0);
begin begin
case spr is return "0000000";
when SPR_LR =>
n := 0; -- N.B. decode2 relies on this specific value
when SPR_CTR =>
n := 1; -- N.B. decode2 relies on this specific value
when SPR_TAR =>
n := 13;
when others =>
n := 0;
return "0000000";
end case;
tmp := std_ulogic_vector(to_unsigned(n, 5));
return "01" & tmp;
end; end;


function gspr_to_gpr(i: gspr_index_t) return gpr_index_t is function gspr_to_gpr(i: gspr_index_t) return gpr_index_t is

@ -138,6 +138,7 @@ architecture behave of core is
signal rst_dbg : std_ulogic; signal rst_dbg : std_ulogic;
signal alt_reset_d : std_ulogic; signal alt_reset_d : std_ulogic;


signal sim_ex_dump: std_ulogic;
signal sim_cr_dump: std_ulogic; signal sim_cr_dump: std_ulogic;


-- Debug actions -- Debug actions
@ -326,7 +327,7 @@ begin
dbg_gpr_addr => dbg_gpr_addr, dbg_gpr_addr => dbg_gpr_addr,
dbg_gpr_data => dbg_gpr_data, dbg_gpr_data => dbg_gpr_data,
sim_dump => terminate, sim_dump => terminate,
sim_dump_done => sim_cr_dump, sim_dump_done => sim_ex_dump,
log_out => log_data(255 downto 184) log_out => log_data(255 downto 184)
); );


@ -347,6 +348,7 @@ begin


execute1_0: entity work.execute1 execute1_0: entity work.execute1
generic map ( generic map (
SIM => SIM,
EX1_BYPASS => EX1_BYPASS, EX1_BYPASS => EX1_BYPASS,
HAS_FPU => HAS_FPU, HAS_FPU => HAS_FPU,
HAS_SHORT_MULT => HAS_SHORT_MULT, HAS_SHORT_MULT => HAS_SHORT_MULT,
@ -376,6 +378,8 @@ begin
dc_events => dcache_events, dc_events => dcache_events,
ic_events => icache_events, ic_events => icache_events,
terminate_out => terminate, terminate_out => terminate,
sim_dump => sim_ex_dump,
sim_dump_done => sim_cr_dump,
log_out => log_data(134 downto 120), log_out => log_data(134 downto 120),
log_rd_addr => log_rd_addr, log_rd_addr => log_rd_addr,
log_rd_data => log_rd_data, log_rd_data => log_rd_data,

@ -89,8 +89,8 @@ architecture behaviour of decode1 is
28 => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andi. 28 => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andi.
29 => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andis. 29 => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andis.
0 => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn 0 => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn
18 => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, SPR, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b 18 => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b
16 => (ALU, NONE, OP_BC, SPR, CONST_BD, NONE, SPR , '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc 16 => (ALU, NONE, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc
11 => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi 11 => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi
10 => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli 10 => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli
34 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz 34 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz
@ -177,7 +177,7 @@ architecture behaviour of decode1 is
-- addpcis -- addpcis
2#001# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), 2#001# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
-- bclr, bcctr, bctar -- bclr, bcctr, bctar
2#100# => (ALU, NONE, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), 2#100# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE),
-- isync -- isync
2#111# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), 2#111# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE),
-- rfid -- rfid
@ -530,6 +530,13 @@ architecture behaviour of decode1 is
begin begin
ret := (index => 0, isodd => '0', valid => '1'); ret := (index => 0, isodd => '0', valid => '1');
case sprn is case sprn is
when SPR_LR =>
ret.index := RAMSPR_LR;
when SPR_CTR =>
ret.index := RAMSPR_CTR;
ret.isodd := '1';
when SPR_TAR =>
ret.index := RAMSPR_TAR;
when SPR_SRR0 => when SPR_SRR0 =>
ret.index := RAMSPR_SRR0; ret.index := RAMSPR_SRR0;
when SPR_SRR1 => when SPR_SRR1 =>
@ -683,13 +690,6 @@ begin
end if; end if;


when 16 => when 16 =>
-- CTR may be needed as input to bc
if f_in.insn(23) = '0' then
v.ispr1 := fast_spr_num(SPR_CTR);
v.ispro := fast_spr_num(SPR_CTR);
elsif f_in.insn(0) = '1' then
v.ispro := fast_spr_num(SPR_LR);
end if;
-- Predict backward branches as taken, forward as untaken -- Predict backward branches as taken, forward as untaken
v.br_pred := f_in.insn(15); v.br_pred := f_in.insn(15);
br_offset := resize(signed(f_in.insn(15 downto 2)), 24); br_offset := resize(signed(f_in.insn(15 downto 2)), 24);
@ -698,37 +698,12 @@ begin
-- Unconditional branches are always taken -- Unconditional branches are always taken
v.br_pred := '1'; v.br_pred := '1';
br_offset := signed(f_in.insn(25 downto 2)); br_offset := signed(f_in.insn(25 downto 2));
if f_in.insn(0) = '1' then
v.ispro := fast_spr_num(SPR_LR);
end if;


when 19 => when 19 =>
vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6)))); vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6))));
op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2); op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2);
v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits))); v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits)));


-- Work out ispr1/ispr2 independent of v.decode since they seem to be critical path
if f_in.insn(2) = '0' then
-- Could be OP_BCREG: bclr, bcctr, bctar
-- Branch uses CTR as condition when BO(2) is 0. This is
-- also used to indicate that CTR is modified (they go
-- together).
-- bcctr doesn't update CTR or use it in the branch condition
if f_in.insn(23) = '0' and (f_in.insn(10) = '0' or f_in.insn(6) = '1') then
v.ispr1 := fast_spr_num(SPR_CTR);
v.ispro := fast_spr_num(SPR_CTR);
elsif f_in.insn(0) = '1' then
v.ispro := fast_spr_num(SPR_LR);
end if;
if f_in.insn(10) = '0' then
v.ispr2 := fast_spr_num(SPR_LR);
elsif f_in.insn(6) = '0' then
v.ispr2 := fast_spr_num(SPR_CTR);
else
v.ispr2 := fast_spr_num(SPR_TAR);
end if;
end if;

when 24 => when 24 =>
-- ori, special-case the standard NOP -- ori, special-case the standard NOP
if std_match(f_in.insn, "01100000000000000000000000000000") then if std_match(f_in.insn, "01100000000000000000000000000000") then

@ -406,6 +406,7 @@ begin
variable length : std_ulogic_vector(3 downto 0); variable length : std_ulogic_vector(3 downto 0);
variable op : insn_type_t; variable op : insn_type_t;
variable valid_in : std_ulogic; variable valid_in : std_ulogic;
variable decctr : std_ulogic;
begin begin
v := dc2; v := dc2;


@ -470,17 +471,45 @@ begin
end if; end if;
op := d_in.decode.insn_type; op := d_in.decode.insn_type;


-- Does this instruction decrement CTR?
-- bc, bclr, bctar with BO(2) = 0 do, but not bcctr.
decctr := '0';
if d_in.insn(23) = '0' and
(op = OP_BC or
(op = OP_BCREG and not (d_in.insn(10) = '1' and d_in.insn(6) = '0'))) then
decctr := '1';
end if;
v.e.dec_ctr := decctr;

v.repeat := d_in.decode.repeat; v.repeat := d_in.decode.repeat;
if d_in.decode.repeat /= NONE then if d_in.decode.repeat /= NONE then
v.e.repeat := '1'; v.e.repeat := '1';
elsif v.e.lr = '1' and decoded_reg_a.reg_valid = '1' then
-- bcl/bclrl/bctarl that needs to write both CTR and LR has to be doubled
v.e.repeat := '1';
end if; end if;


v.e.spr_select := d_in.spr_info; v.e.spr_select := d_in.spr_info;


if decctr = '1' then
-- read and write CTR
v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
v.e.ramspr_wraddr := RAMSPR_CTR;
v.e.ramspr_write_odd := '1';
end if;
if v.e.lr = '1' then
-- write LR
v.e.ramspr_wraddr := RAMSPR_LR;
v.e.ramspr_write_even := '1';
end if;

case op is case op is
when OP_BCREG =>
if d_in.insn(10) = '0' then
v.e.ramspr_even_rdaddr := RAMSPR_LR;
elsif d_in.insn(6) = '0' then
v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
v.e.ramspr_rd_odd := '1';
else
v.e.ramspr_even_rdaddr := RAMSPR_TAR;
end if;
when OP_MFSPR => when OP_MFSPR =>
v.e.ramspr_even_rdaddr := d_in.ram_spr.index; v.e.ramspr_even_rdaddr := d_in.ram_spr.index;
v.e.ramspr_odd_rdaddr := d_in.ram_spr.index; v.e.ramspr_odd_rdaddr := d_in.ram_spr.index;
@ -520,7 +549,6 @@ begin
v.e.write_reg := decoded_reg_o.reg; v.e.write_reg := decoded_reg_o.reg;
v.e.write_reg_enable := decoded_reg_o.reg_valid; v.e.write_reg_enable := decoded_reg_o.reg_valid;
v.e.invert_a := d_in.decode.invert_a; v.e.invert_a := d_in.decode.invert_a;
v.e.addm1 := '0';
v.e.insn_type := op; v.e.insn_type := op;
v.e.invert_out := d_in.decode.invert_out; v.e.invert_out := d_in.decode.invert_out;
v.e.input_carry := d_in.decode.input_carry; v.e.input_carry := d_in.decode.input_carry;
@ -536,14 +564,6 @@ begin
v.e.br_pred := d_in.br_pred; v.e.br_pred := d_in.br_pred;
v.e.result_sel := result_select(op); v.e.result_sel := result_select(op);
v.e.sub_select := subresult_select(op); v.e.sub_select := subresult_select(op);
if op = OP_BC or op = OP_BCREG then
if d_in.insn(23) = '0' and
not (d_in.decode.insn_type = OP_BCREG and d_in.insn(10) = '0') then
-- decrement CTR if BO(2) = 0 and not bcctr
v.e.addm1 := '1';
v.e.result_sel := "000"; -- select adder output
end if;
end if;
if op = OP_MFSPR then if op = OP_MFSPR then
if is_fast_spr(d_in.ispr1) = '1' then if is_fast_spr(d_in.ispr1) = '1' then
v.e.result_sel := "000"; -- adder_result, effectively a_in v.e.result_sel := "000"; -- adder_result, effectively a_in
@ -562,16 +582,9 @@ begin
-- dc2.busy = 1 and dc2.e.valid = 1, thus this must be a repeated instruction. -- dc2.busy = 1 and dc2.e.valid = 1, thus this must be a repeated instruction.
-- Set up for the second iteration (if deferred = 1 this will all be ignored) -- Set up for the second iteration (if deferred = 1 this will all be ignored)
v.e.second := '1'; v.e.second := '1';
case dc2.repeat is -- DUPD is the only possibility here:
when DUPD => -- update-form loads, 2nd instruction writes RA
-- update-form loads, 2nd instruction writes RA v.e.write_reg := dc2.e.read_reg1;
v.e.write_reg := dc2.e.read_reg1;
when NONE =>
-- bcl/bclrl/bctarl that needs to write both CTR and LR
v.e.write_reg(0) := '0'; -- point to LR
v.e.result_sel := "110"; -- select NIA (to go to LR)
when others =>
end case;
end if; end if;


-- issue control -- issue control

@ -12,6 +12,7 @@ use work.ppc_fx_insns.all;


entity execute1 is entity execute1 is
generic ( generic (
SIM : boolean := false;
EX1_BYPASS : boolean := true; EX1_BYPASS : boolean := true;
HAS_FPU : boolean := true; HAS_FPU : boolean := true;
HAS_SHORT_MULT : boolean := false; HAS_SHORT_MULT : boolean := false;
@ -54,6 +55,10 @@ entity execute1 is
dc_events : in DcacheEventType; dc_events : in DcacheEventType;
ic_events : in IcacheEventType; ic_events : in IcacheEventType;


-- debug
sim_dump : in std_ulogic;
sim_dump_done : out std_ulogic;

log_out : out std_ulogic_vector(14 downto 0); log_out : out std_ulogic_vector(14 downto 0);
log_rd_addr : out std_ulogic_vector(31 downto 0); log_rd_addr : out std_ulogic_vector(31 downto 0);
log_rd_data : in std_ulogic_vector(63 downto 0); log_rd_data : in std_ulogic_vector(63 downto 0);
@ -92,10 +97,12 @@ architecture behaviour of execute1 is
fp_intr : std_ulogic; fp_intr : std_ulogic;
res2_sel : std_ulogic_vector(1 downto 0); res2_sel : std_ulogic_vector(1 downto 0);
bypass_valid : std_ulogic; bypass_valid : std_ulogic;
ramspr_odd_data : std_ulogic_vector(63 downto 0);
end record; end record;
constant actions_type_init : actions_type := constant actions_type_init : actions_type :=
(e => Execute1ToWritebackInit, se => side_effect_init, (e => Execute1ToWritebackInit, se => side_effect_init,
new_msr => (others => '0'), res2_sel => "00", others => '0'); new_msr => (others => '0'), res2_sel => "00",
ramspr_odd_data => 64x"0", others => '0');


type reg_stage1_type is record type reg_stage1_type is record
e : Execute1ToWritebackType; e : Execute1ToWritebackType;
@ -104,7 +111,6 @@ architecture behaviour of execute1 is
fp_exception_next : std_ulogic; fp_exception_next : std_ulogic;
trace_next : std_ulogic; trace_next : std_ulogic;
prev_op : insn_type_t; prev_op : insn_type_t;
br_taken : std_ulogic;
oe : std_ulogic; oe : std_ulogic;
mul_select : std_ulogic_vector(1 downto 0); mul_select : std_ulogic_vector(1 downto 0);
res2_sel : std_ulogic_vector(1 downto 0); res2_sel : std_ulogic_vector(1 downto 0);
@ -122,11 +128,12 @@ architecture behaviour of execute1 is
xerc : xer_common_t; xerc : xer_common_t;
xerc_valid : std_ulogic; xerc_valid : std_ulogic;
ramspr_wraddr : ramspr_index; ramspr_wraddr : ramspr_index;
ramspr_odd_data : std_ulogic_vector(63 downto 0);
end record; end record;
constant reg_stage1_type_init : reg_stage1_type := constant reg_stage1_type_init : reg_stage1_type :=
(e => Execute1ToWritebackInit, se => side_effect_init, (e => Execute1ToWritebackInit, se => side_effect_init,
busy => '0', busy => '0',
fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL, br_taken => '0', fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL,
oe => '0', mul_select => "00", res2_sel => "00", oe => '0', mul_select => "00", res2_sel => "00",
spr_select => spr_id_init, pmu_spr_num => 5x"0", spr_select => spr_id_init, pmu_spr_num => 5x"0",
mul_in_progress => '0', mul_finish => '0', div_in_progress => '0', mul_in_progress => '0', mul_finish => '0', div_in_progress => '0',
@ -134,7 +141,7 @@ architecture behaviour of execute1 is
taken_branch_event => '0', br_mispredict => '0', taken_branch_event => '0', br_mispredict => '0',
msr => 64x"0", msr => 64x"0",
xerc => xerc_init, xerc_valid => '0', xerc => xerc_init, xerc_valid => '0',
ramspr_wraddr => 0); ramspr_wraddr => 0, ramspr_odd_data => 64x"0");


type reg_stage2_type is record type reg_stage2_type is record
e : Execute1ToWritebackType; e : Execute1ToWritebackType;
@ -514,7 +521,7 @@ begin
odd_wr_data := intr_srr1(ctrl.msr, interrupt_in.srr1); odd_wr_data := intr_srr1(ctrl.msr, interrupt_in.srr1);
else else
even_wr_data := ex1.e.write_data; even_wr_data := ex1.e.write_data;
odd_wr_data := ex1.e.write_data; odd_wr_data := ex1.ramspr_odd_data;
end if; end if;
ramspr_wr_addr <= wr_addr; ramspr_wr_addr <= wr_addr;
ramspr_even_wr_data <= even_wr_data; ramspr_even_wr_data <= even_wr_data;
@ -531,7 +538,7 @@ begin
ramspr_even <= even_rd_data; ramspr_even <= even_rd_data;
end if; end if;
if ex1.se.ramspr_write_odd = '1' and e_in.ramspr_odd_rdaddr = ex1.ramspr_wraddr then if ex1.se.ramspr_write_odd = '1' and e_in.ramspr_odd_rdaddr = ex1.ramspr_wraddr then
ramspr_odd <= ex1.e.write_data; ramspr_odd <= ex1.ramspr_odd_data;
else else
ramspr_odd <= odd_rd_data; ramspr_odd <= odd_rd_data;
end if; end if;
@ -600,7 +607,6 @@ begin
-- Data path for integer instructions (first execute stage) -- Data path for integer instructions (first execute stage)
execute1_dp: process(all) execute1_dp: process(all)
variable a_inv : std_ulogic_vector(63 downto 0); variable a_inv : std_ulogic_vector(63 downto 0);
variable b_or_m1 : std_ulogic_vector(63 downto 0);
variable sum_with_carry : std_ulogic_vector(64 downto 0); variable sum_with_carry : std_ulogic_vector(64 downto 0);
variable sign1, sign2 : std_ulogic; variable sign1, sign2 : std_ulogic;
variable abs1, abs2 : signed(63 downto 0); variable abs1, abs2 : signed(63 downto 0);
@ -635,12 +641,7 @@ begin
else else
a_inv := not a_in; a_inv := not a_in;
end if; end if;
if e_in.addm1 = '0' then sum_with_carry := ppc_adde(a_inv, b_in,
b_or_m1 := b_in;
else
b_or_m1 := (others => '1');
end if;
sum_with_carry := ppc_adde(a_inv, b_or_m1,
decode_input_carry(e_in.input_carry, xerc_in)); decode_input_carry(e_in.input_carry, xerc_in));
adder_result <= sum_with_carry(63 downto 0); adder_result <= sum_with_carry(63 downto 0);
carry_32 <= sum_with_carry(32) xor a_inv(32) xor b_in(32); carry_32 <= sum_with_carry(32) xor a_inv(32) xor b_in(32);
@ -956,6 +957,10 @@ begin


v.se.ramspr_write_even := e_in.ramspr_write_even; v.se.ramspr_write_even := e_in.ramspr_write_even;
v.se.ramspr_write_odd := e_in.ramspr_write_odd; v.se.ramspr_write_odd := e_in.ramspr_write_odd;
v.ramspr_odd_data := c_in;
if e_in.dec_ctr = '1' then
v.ramspr_odd_data := std_ulogic_vector(unsigned(ramspr_odd) - 1);
end if;


-- Note the difference between v.exception and v.trap: -- Note the difference between v.exception and v.trap:
-- v.exception signals a condition that prevents execution of the -- v.exception signals a condition that prevents execution of the
@ -1059,61 +1064,42 @@ begin
end if; end if;
v.se.write_cfar := '1'; v.se.write_cfar := '1';
when OP_BC => when OP_BC =>
-- read_data1 is CTR -- If CTR is being decremented, it is in ramspr_odd.
-- If this instruction updates both CTR and LR, then it is
-- doubled; the first instruction decrements CTR and determines
-- whether the branch is taken, and the second does the
-- redirect and the LR update.
bo := insn_bo(e_in.insn); bo := insn_bo(e_in.insn);
bi := insn_bi(e_in.insn); bi := insn_bi(e_in.insn);
if e_in.second = '0' then v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
v.take_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
else
v.take_branch := ex1.br_taken;
end if;
if v.take_branch = '1' then if v.take_branch = '1' then
v.e.br_offset := b_in; v.e.br_offset := b_in;
v.e.abs_br := insn_aa(e_in.insn); v.e.abs_br := insn_aa(e_in.insn);
end if; end if;
if e_in.repeat = '0' or e_in.second = '1' then -- Mispredicted branches cause a redirect
-- Mispredicted branches cause a redirect if v.take_branch /= e_in.br_pred then
if v.take_branch /= e_in.br_pred then v.e.redirect := '1';
v.e.redirect := '1'; end if;
end if; v.direct_branch := '1';
v.direct_branch := '1'; v.e.br_last := '1';
v.e.br_last := '1'; v.e.br_taken := v.take_branch;
v.e.br_taken := v.take_branch; if ex1.msr(MSR_BE) = '1' then
if ex1.msr(MSR_BE) = '1' then v.do_trace := '1';
v.do_trace := '1';
end if;
v.se.write_cfar := v.take_branch;
end if; end if;
v.se.write_cfar := v.take_branch;
when OP_BCREG => when OP_BCREG =>
-- read_data1 is CTR, read_data2 is target register (CTR, LR or TAR) -- If CTR is being decremented, it is in ramspr_odd.
-- If this instruction updates both CTR and LR, then it is -- The target address is in ramspr_result (LR, CTR or TAR).
-- doubled; the first instruction decrements CTR and determines
-- whether the branch is taken, and the second does the
-- redirect and the LR update.
bo := insn_bo(e_in.insn); bo := insn_bo(e_in.insn);
bi := insn_bi(e_in.insn); bi := insn_bi(e_in.insn);
if e_in.second = '0' then v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
v.take_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
else
v.take_branch := ex1.br_taken;
end if;
if v.take_branch = '1' then if v.take_branch = '1' then
v.e.br_offset := b_in; v.e.br_offset := ramspr_result;
v.e.abs_br := '1'; v.e.abs_br := '1';
end if; end if;
if e_in.repeat = '0' or e_in.second = '1' then -- Indirect branches are never predicted taken
-- Indirect branches are never predicted taken v.e.redirect := v.take_branch;
v.e.redirect := v.take_branch; v.e.br_taken := v.take_branch;
v.e.br_taken := v.take_branch; if ex1.msr(MSR_BE) = '1' then
if ex1.msr(MSR_BE) = '1' then v.do_trace := '1';
v.do_trace := '1';
end if;
v.se.write_cfar := v.take_branch;
end if; end if;
v.se.write_cfar := v.take_branch;


when OP_RFID => when OP_RFID =>
srr1 := ramspr_odd; srr1 := ramspr_odd;
@ -1130,7 +1116,7 @@ begin
v.new_msr(MSR_DR) := '1'; v.new_msr(MSR_DR) := '1';
end if; end if;
v.se.write_msr := '1'; v.se.write_msr := '1';
v.e.br_offset := ramspr_even; v.e.br_offset := ramspr_result;
v.e.abs_br := '1'; v.e.abs_br := '1';
v.e.redirect := '1'; v.e.redirect := '1';
v.se.write_cfar := '1'; v.se.write_cfar := '1';
@ -1343,6 +1329,7 @@ begin
v.mul_select := e_in.sub_select(1 downto 0); v.mul_select := e_in.sub_select(1 downto 0);
v.se := side_effect_init; v.se := side_effect_init;
v.ramspr_wraddr := e_in.ramspr_wraddr; v.ramspr_wraddr := e_in.ramspr_wraddr;
v.ramspr_odd_data := actions.ramspr_odd_data;
end if; end if;


lv := Execute1ToLoadstore1Init; lv := Execute1ToLoadstore1Init;
@ -1430,7 +1417,6 @@ begin
v.e.valid := actions.complete; v.e.valid := actions.complete;
bypass_valid := actions.bypass_valid; bypass_valid := actions.bypass_valid;
v.taken_branch_event := actions.take_branch; v.taken_branch_event := actions.take_branch;
v.br_taken := actions.take_branch;
v.trace_next := actions.do_trace; v.trace_next := actions.do_trace;
v.fp_exception_next := actions.fp_intr; v.fp_exception_next := actions.fp_intr;
v.res2_sel := actions.res2_sel; v.res2_sel := actions.res2_sel;
@ -1759,6 +1745,25 @@ begin
exception_log <= v.e.interrupt; exception_log <= v.e.interrupt;
end process; end process;


sim_dump_test: if SIM generate
dump_exregs: process(all)
variable xer : std_ulogic_vector(63 downto 0);
begin
if sim_dump = '1' then
report "LR " & to_hstring(even_sprs(RAMSPR_LR));
report "CTR " & to_hstring(odd_sprs(RAMSPR_CTR));
sim_dump_done <= '1';
else
sim_dump_done <= '0';
end if;
end process;
end generate;

-- Keep GHDL synthesis happy
sim_dump_test_synth: if not SIM generate
sim_dump_done <= '0';
end generate;

e1_log: if LOG_LENGTH > 0 generate e1_log: if LOG_LENGTH > 0 generate
signal log_data : std_ulogic_vector(14 downto 0); signal log_data : std_ulogic_vector(14 downto 0);
begin begin

@ -130,9 +130,6 @@ begin
loop_0: for i in 0 to 31 loop loop_0: for i in 0 to 31 loop
report "GPR" & integer'image(i) & " " & to_hstring(registers(i)); report "GPR" & integer'image(i) & " " & to_hstring(registers(i));
end loop loop_0; end loop loop_0;

report "LR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_LR)))));
report "CTR " & to_hstring(registers(to_integer(unsigned(fast_spr_num(SPR_CTR)))));
sim_dump_done <= '1'; sim_dump_done <= '1';
else else
sim_dump_done <= '0'; sim_dump_done <= '0';

Loading…
Cancel
Save