mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-05-05 15:54:17 +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_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,
|
||||||
|
|||||||
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.
|
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
|
||||||
|
|||||||
57
decode2.vhdl
57
decode2.vhdl
@@ -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
|
||||||
|
|||||||
117
execute1.vhdl
117
execute1.vhdl
@@ -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;
|
|
||||||
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;
|
|
||||||
end if;
|
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 =>
|
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';
|
||||||
|
|||||||
Reference in New Issue
Block a user