mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-05 04:35:00 +00:00
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>
This commit is contained in:
27
common.vhdl
27
common.vhdl
@@ -132,12 +132,15 @@ package common is
|
||||
constant RAMSPR_SPRG0 : ramspr_index := 2;
|
||||
constant RAMSPR_SPRG2 : ramspr_index := 3;
|
||||
constant RAMSPR_HSPRG0 : ramspr_index := 4;
|
||||
constant RAMSPR_LR : ramspr_index := 5; -- must equal RAMSPR_CTR
|
||||
constant RAMSPR_TAR : ramspr_index := 6;
|
||||
-- Odd half:
|
||||
constant RAMSPR_SRR1 : ramspr_index := 0;
|
||||
constant RAMSPR_HSRR1 : ramspr_index := 1;
|
||||
constant RAMSPR_SPRG1 : ramspr_index := 2;
|
||||
constant RAMSPR_SPRG3 : ramspr_index := 3;
|
||||
constant RAMSPR_HSPRG1 : ramspr_index := 4;
|
||||
constant RAMSPR_CTR : ramspr_index := 5; -- must equal RAMSPR_LR
|
||||
|
||||
type ram_spr_info is record
|
||||
index : ramspr_index;
|
||||
@@ -322,7 +325,6 @@ package common is
|
||||
rc: std_ulogic;
|
||||
oe: std_ulogic;
|
||||
invert_a: std_ulogic;
|
||||
addm1 : std_ulogic;
|
||||
invert_out: std_ulogic;
|
||||
input_carry: carry_in_t;
|
||||
output_carry: std_ulogic;
|
||||
@@ -350,11 +352,12 @@ package common is
|
||||
ramspr_wraddr : ramspr_index;
|
||||
ramspr_write_even : std_ulogic;
|
||||
ramspr_write_odd : std_ulogic;
|
||||
dec_ctr : std_ulogic;
|
||||
end record;
|
||||
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
|
||||
(valid => '0', unit => NONE, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
|
||||
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',
|
||||
output_cr => '0', output_xer => '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',
|
||||
ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0',
|
||||
ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0',
|
||||
dec_ctr => '0',
|
||||
others => (others => '0'));
|
||||
|
||||
type MultiplyInputType is record
|
||||
@@ -780,25 +784,8 @@ package body common is
|
||||
return to_integer(unsigned(insn(15 downto 11) & insn(20 downto 16)));
|
||||
end;
|
||||
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
|
||||
case spr is
|
||||
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;
|
||||
return "0000000";
|
||||
end;
|
||||
|
||||
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 alt_reset_d : std_ulogic;
|
||||
|
||||
signal sim_ex_dump: std_ulogic;
|
||||
signal sim_cr_dump: std_ulogic;
|
||||
|
||||
-- Debug actions
|
||||
@@ -326,7 +327,7 @@ begin
|
||||
dbg_gpr_addr => dbg_gpr_addr,
|
||||
dbg_gpr_data => dbg_gpr_data,
|
||||
sim_dump => terminate,
|
||||
sim_dump_done => sim_cr_dump,
|
||||
sim_dump_done => sim_ex_dump,
|
||||
log_out => log_data(255 downto 184)
|
||||
);
|
||||
|
||||
@@ -347,6 +348,7 @@ begin
|
||||
|
||||
execute1_0: entity work.execute1
|
||||
generic map (
|
||||
SIM => SIM,
|
||||
EX1_BYPASS => EX1_BYPASS,
|
||||
HAS_FPU => HAS_FPU,
|
||||
HAS_SHORT_MULT => HAS_SHORT_MULT,
|
||||
@@ -376,6 +378,8 @@ begin
|
||||
dc_events => dcache_events,
|
||||
ic_events => icache_events,
|
||||
terminate_out => terminate,
|
||||
sim_dump => sim_ex_dump,
|
||||
sim_dump_done => sim_cr_dump,
|
||||
log_out => log_data(134 downto 120),
|
||||
log_rd_addr => log_rd_addr,
|
||||
log_rd_data => log_rd_data,
|
||||
|
||||
45
decode1.vhdl
45
decode1.vhdl
@@ -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.
|
||||
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
|
||||
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
|
||||
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
|
||||
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, 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
|
||||
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
|
||||
@@ -177,7 +177,7 @@ architecture behaviour of decode1 is
|
||||
-- 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),
|
||||
-- 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
|
||||
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
|
||||
@@ -530,6 +530,13 @@ architecture behaviour of decode1 is
|
||||
begin
|
||||
ret := (index => 0, isodd => '0', valid => '1');
|
||||
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 =>
|
||||
ret.index := RAMSPR_SRR0;
|
||||
when SPR_SRR1 =>
|
||||
@@ -683,13 +690,6 @@ begin
|
||||
end if;
|
||||
|
||||
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
|
||||
v.br_pred := f_in.insn(15);
|
||||
br_offset := resize(signed(f_in.insn(15 downto 2)), 24);
|
||||
@@ -698,37 +698,12 @@ begin
|
||||
-- Unconditional branches are always taken
|
||||
v.br_pred := '1';
|
||||
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 =>
|
||||
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);
|
||||
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 =>
|
||||
-- ori, special-case the standard NOP
|
||||
if std_match(f_in.insn, "01100000000000000000000000000000") then
|
||||
|
||||
57
decode2.vhdl
57
decode2.vhdl
@@ -406,6 +406,7 @@ begin
|
||||
variable length : std_ulogic_vector(3 downto 0);
|
||||
variable op : insn_type_t;
|
||||
variable valid_in : std_ulogic;
|
||||
variable decctr : std_ulogic;
|
||||
begin
|
||||
v := dc2;
|
||||
|
||||
@@ -470,17 +471,45 @@ begin
|
||||
end if;
|
||||
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;
|
||||
if d_in.decode.repeat /= NONE then
|
||||
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;
|
||||
|
||||
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
|
||||
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 =>
|
||||
v.e.ramspr_even_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_enable := decoded_reg_o.reg_valid;
|
||||
v.e.invert_a := d_in.decode.invert_a;
|
||||
v.e.addm1 := '0';
|
||||
v.e.insn_type := op;
|
||||
v.e.invert_out := d_in.decode.invert_out;
|
||||
v.e.input_carry := d_in.decode.input_carry;
|
||||
@@ -536,14 +564,6 @@ begin
|
||||
v.e.br_pred := d_in.br_pred;
|
||||
v.e.result_sel := result_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 is_fast_spr(d_in.ispr1) = '1' then
|
||||
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.
|
||||
-- Set up for the second iteration (if deferred = 1 this will all be ignored)
|
||||
v.e.second := '1';
|
||||
case dc2.repeat is
|
||||
when DUPD =>
|
||||
-- update-form loads, 2nd instruction writes RA
|
||||
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;
|
||||
-- DUPD is the only possibility here:
|
||||
-- update-form loads, 2nd instruction writes RA
|
||||
v.e.write_reg := dc2.e.read_reg1;
|
||||
end if;
|
||||
|
||||
-- issue control
|
||||
|
||||
117
execute1.vhdl
117
execute1.vhdl
@@ -12,6 +12,7 @@ use work.ppc_fx_insns.all;
|
||||
|
||||
entity execute1 is
|
||||
generic (
|
||||
SIM : boolean := false;
|
||||
EX1_BYPASS : boolean := true;
|
||||
HAS_FPU : boolean := true;
|
||||
HAS_SHORT_MULT : boolean := false;
|
||||
@@ -54,6 +55,10 @@ entity execute1 is
|
||||
dc_events : in DcacheEventType;
|
||||
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_rd_addr : out std_ulogic_vector(31 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;
|
||||
res2_sel : std_ulogic_vector(1 downto 0);
|
||||
bypass_valid : std_ulogic;
|
||||
ramspr_odd_data : std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
constant actions_type_init : actions_type :=
|
||||
(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
|
||||
e : Execute1ToWritebackType;
|
||||
@@ -104,7 +111,6 @@ architecture behaviour of execute1 is
|
||||
fp_exception_next : std_ulogic;
|
||||
trace_next : std_ulogic;
|
||||
prev_op : insn_type_t;
|
||||
br_taken : std_ulogic;
|
||||
oe : std_ulogic;
|
||||
mul_select : 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_valid : std_ulogic;
|
||||
ramspr_wraddr : ramspr_index;
|
||||
ramspr_odd_data : std_ulogic_vector(63 downto 0);
|
||||
end record;
|
||||
constant reg_stage1_type_init : reg_stage1_type :=
|
||||
(e => Execute1ToWritebackInit, se => side_effect_init,
|
||||
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",
|
||||
spr_select => spr_id_init, pmu_spr_num => 5x"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',
|
||||
msr => 64x"0",
|
||||
xerc => xerc_init, xerc_valid => '0',
|
||||
ramspr_wraddr => 0);
|
||||
ramspr_wraddr => 0, ramspr_odd_data => 64x"0");
|
||||
|
||||
type reg_stage2_type is record
|
||||
e : Execute1ToWritebackType;
|
||||
@@ -514,7 +521,7 @@ begin
|
||||
odd_wr_data := intr_srr1(ctrl.msr, interrupt_in.srr1);
|
||||
else
|
||||
even_wr_data := ex1.e.write_data;
|
||||
odd_wr_data := ex1.e.write_data;
|
||||
odd_wr_data := ex1.ramspr_odd_data;
|
||||
end if;
|
||||
ramspr_wr_addr <= wr_addr;
|
||||
ramspr_even_wr_data <= even_wr_data;
|
||||
@@ -531,7 +538,7 @@ begin
|
||||
ramspr_even <= even_rd_data;
|
||||
end if;
|
||||
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
|
||||
ramspr_odd <= odd_rd_data;
|
||||
end if;
|
||||
@@ -600,7 +607,6 @@ begin
|
||||
-- Data path for integer instructions (first execute stage)
|
||||
execute1_dp: process(all)
|
||||
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 sign1, sign2 : std_ulogic;
|
||||
variable abs1, abs2 : signed(63 downto 0);
|
||||
@@ -635,12 +641,7 @@ begin
|
||||
else
|
||||
a_inv := not a_in;
|
||||
end if;
|
||||
if e_in.addm1 = '0' then
|
||||
b_or_m1 := b_in;
|
||||
else
|
||||
b_or_m1 := (others => '1');
|
||||
end if;
|
||||
sum_with_carry := ppc_adde(a_inv, b_or_m1,
|
||||
sum_with_carry := ppc_adde(a_inv, b_in,
|
||||
decode_input_carry(e_in.input_carry, xerc_in));
|
||||
adder_result <= sum_with_carry(63 downto 0);
|
||||
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_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:
|
||||
-- v.exception signals a condition that prevents execution of the
|
||||
@@ -1059,61 +1064,42 @@ begin
|
||||
end if;
|
||||
v.se.write_cfar := '1';
|
||||
when OP_BC =>
|
||||
-- read_data1 is CTR
|
||||
-- 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.
|
||||
-- If CTR is being decremented, it is in ramspr_odd.
|
||||
bo := insn_bo(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, a_in);
|
||||
else
|
||||
v.take_branch := ex1.br_taken;
|
||||
end if;
|
||||
v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
|
||||
if v.take_branch = '1' then
|
||||
v.e.br_offset := b_in;
|
||||
v.e.abs_br := insn_aa(e_in.insn);
|
||||
end if;
|
||||
if e_in.repeat = '0' or e_in.second = '1' then
|
||||
-- Mispredicted branches cause a redirect
|
||||
if v.take_branch /= e_in.br_pred then
|
||||
v.e.redirect := '1';
|
||||
end if;
|
||||
v.direct_branch := '1';
|
||||
v.e.br_last := '1';
|
||||
v.e.br_taken := v.take_branch;
|
||||
if ex1.msr(MSR_BE) = '1' then
|
||||
v.do_trace := '1';
|
||||
end if;
|
||||
v.se.write_cfar := v.take_branch;
|
||||
-- Mispredicted branches cause a redirect
|
||||
if v.take_branch /= e_in.br_pred then
|
||||
v.e.redirect := '1';
|
||||
end if;
|
||||
v.direct_branch := '1';
|
||||
v.e.br_last := '1';
|
||||
v.e.br_taken := v.take_branch;
|
||||
if ex1.msr(MSR_BE) = '1' then
|
||||
v.do_trace := '1';
|
||||
end if;
|
||||
v.se.write_cfar := v.take_branch;
|
||||
when OP_BCREG =>
|
||||
-- read_data1 is CTR, read_data2 is target register (CTR, LR or TAR)
|
||||
-- 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.
|
||||
-- If CTR is being decremented, it is in ramspr_odd.
|
||||
-- The target address is in ramspr_result (LR, CTR or TAR).
|
||||
bo := insn_bo(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, a_in);
|
||||
else
|
||||
v.take_branch := ex1.br_taken;
|
||||
end if;
|
||||
v.take_branch := ppc_bc_taken(bo, bi, cr_in, ramspr_odd);
|
||||
if v.take_branch = '1' then
|
||||
v.e.br_offset := b_in;
|
||||
v.e.br_offset := ramspr_result;
|
||||
v.e.abs_br := '1';
|
||||
end if;
|
||||
if e_in.repeat = '0' or e_in.second = '1' then
|
||||
-- Indirect branches are never predicted taken
|
||||
v.e.redirect := v.take_branch;
|
||||
v.e.br_taken := v.take_branch;
|
||||
if ex1.msr(MSR_BE) = '1' then
|
||||
v.do_trace := '1';
|
||||
end if;
|
||||
v.se.write_cfar := v.take_branch;
|
||||
-- Indirect branches are never predicted taken
|
||||
v.e.redirect := v.take_branch;
|
||||
v.e.br_taken := v.take_branch;
|
||||
if ex1.msr(MSR_BE) = '1' then
|
||||
v.do_trace := '1';
|
||||
end if;
|
||||
v.se.write_cfar := v.take_branch;
|
||||
|
||||
when OP_RFID =>
|
||||
srr1 := ramspr_odd;
|
||||
@@ -1130,7 +1116,7 @@ begin
|
||||
v.new_msr(MSR_DR) := '1';
|
||||
end if;
|
||||
v.se.write_msr := '1';
|
||||
v.e.br_offset := ramspr_even;
|
||||
v.e.br_offset := ramspr_result;
|
||||
v.e.abs_br := '1';
|
||||
v.e.redirect := '1';
|
||||
v.se.write_cfar := '1';
|
||||
@@ -1343,6 +1329,7 @@ begin
|
||||
v.mul_select := e_in.sub_select(1 downto 0);
|
||||
v.se := side_effect_init;
|
||||
v.ramspr_wraddr := e_in.ramspr_wraddr;
|
||||
v.ramspr_odd_data := actions.ramspr_odd_data;
|
||||
end if;
|
||||
|
||||
lv := Execute1ToLoadstore1Init;
|
||||
@@ -1430,7 +1417,6 @@ begin
|
||||
v.e.valid := actions.complete;
|
||||
bypass_valid := actions.bypass_valid;
|
||||
v.taken_branch_event := actions.take_branch;
|
||||
v.br_taken := actions.take_branch;
|
||||
v.trace_next := actions.do_trace;
|
||||
v.fp_exception_next := actions.fp_intr;
|
||||
v.res2_sel := actions.res2_sel;
|
||||
@@ -1759,6 +1745,25 @@ begin
|
||||
exception_log <= v.e.interrupt;
|
||||
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
|
||||
signal log_data : std_ulogic_vector(14 downto 0);
|
||||
begin
|
||||
|
||||
@@ -130,9 +130,6 @@ begin
|
||||
loop_0: for i in 0 to 31 loop
|
||||
report "GPR" & integer'image(i) & " " & to_hstring(registers(i));
|
||||
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';
|
||||
else
|
||||
sim_dump_done <= '0';
|
||||
|
||||
Reference in New Issue
Block a user