decode1: Work out register addresses in decode1

This adds some relatively simple logic to decode1 to compute the
GPR/FPR addresses that an instruction will access.  It always computes
three addresses regardless of whether the instruction will actually
use all of them.  The main things it computes are whether the
instruction uses the RS field or the RC field for the 3rd operand, and
whether the operands are FPRs or GPRs (it is possible for RS to be an
FPR but RA and RB to be GPRs, as for example with stfdx).

At the moment all we do with these computed register addresses is to
assert that they are identical to the ones coming from decode2 one
cycle later.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/379/head
Paul Mackerras 2 years ago
parent 047be5c0c3
commit 06c13d4988

@ -276,6 +276,12 @@ package common is
redirect_nia : std_ulogic_vector(63 downto 0);
end record;

type Decode1ToRegisterFileType is record
reg_1_addr : gspr_index_t;
reg_2_addr : gspr_index_t;
reg_3_addr : gspr_index_t;
end record;

type bypass_data_t is record
tag : instr_tag_t;
data : std_ulogic_vector(63 downto 0);

@ -63,6 +63,7 @@ architecture behave of core is
-- decode signals
signal decode1_to_decode2: Decode1ToDecode2Type;
signal decode1_to_fetch1: Decode1ToFetch1Type;
signal decode1_to_register_file: Decode1ToRegisterFileType;
signal decode2_to_execute1: Decode2ToExecute1Type;

-- register file signals
@ -285,6 +286,7 @@ begin
f_in => icache_to_decode1,
d_out => decode1_to_decode2,
f_out => decode1_to_fetch1,
r_out => decode1_to_register_file,
log_out => log_data(109 downto 97)
);

@ -329,6 +331,8 @@ begin
)
port map (
clk => clk,
stall => decode2_stall_out,
d1_in => decode1_to_register_file,
d_in => decode2_to_register_file,
d_out => register_file_to_decode2,
w_in => writeback_to_register_file,

@ -5,6 +5,7 @@ use ieee.numeric_std.all;
library work;
use work.common.all;
use work.decode_types.all;
use work.insn_helpers.all;

entity decode1 is
generic (
@ -24,6 +25,7 @@ entity decode1 is
f_in : in IcacheToDecode1Type;
f_out : out Decode1ToFetch1Type;
d_out : out Decode1ToDecode2Type;
r_out : out Decode1ToRegisterFileType;
log_out : out std_ulogic_vector(12 downto 0)
);
end entity decode1;
@ -628,6 +630,7 @@ begin

decode1_1: process(all)
variable v : Decode1ToDecode2Type;
variable vr : Decode1ToRegisterFileType;
variable vi : reg_internal_t;
variable majorop : major_opcode_t;
variable minor4op : std_ulogic_vector(10 downto 0);
@ -636,6 +639,8 @@ begin
variable br_target : std_ulogic_vector(61 downto 0);
variable br_offset : signed(23 downto 0);
variable bv : br_predictor_t;
variable fprs, fprabc : std_ulogic;
variable in3rc : std_ulogic;
begin
v := Decode1ToDecode2Init;
vi := reg_internal_t_init;
@ -646,6 +651,10 @@ begin
v.stop_mark := f_in.stop_mark;
v.big_endian := f_in.big_endian;

fprs := '0';
fprabc := '0';
in3rc := '0';

if f_in.valid = '1' then
report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia);
end if;
@ -665,6 +674,7 @@ begin
minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6);
vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op)));
v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0))));
in3rc := '1';

when 31 =>
-- major opcode 31, lots of things
@ -688,6 +698,10 @@ begin
when others =>
end case;
end if;
if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then
-- lower half of column 23 has FP loads and stores
fprs := '1';
end if;

when 16 =>
-- Predict backward branches as taken, forward as untaken
@ -715,6 +729,12 @@ begin
when 30 =>
v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1))));

when 52 | 53 | 54 | 55 =>
-- stfd[u] and stfs[u]
if HAS_FPU then
fprs := '1';
end if;

when 58 =>
v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0))));

@ -725,6 +745,9 @@ begin
if f_in.insn(5) = '0' and not std_match(f_in.insn(10 downto 1), "11-1001110") then
vi.override := '1';
end if;
in3rc := '1';
fprabc := '1';
fprs := '1';
end if;

when 62 =>
@ -738,11 +761,23 @@ begin
else
v.decode := decode_op_63h_array(to_integer(unsigned(f_in.insn(4 downto 1))));
end if;
in3rc := '1';
fprabc := '1';
fprs := '1';
end if;

when others =>
end case;

-- Work out GPR/FPR read addresses
vr.reg_1_addr := fprabc & insn_ra(f_in.insn);
vr.reg_2_addr := fprabc & insn_rb(f_in.insn);
if in3rc = '1' then
vr.reg_3_addr := fprabc & insn_rcreg(f_in.insn);
else
vr.reg_3_addr := fprs & insn_rs(f_in.insn);
end if;

if f_in.fetch_failed = '1' then
v.valid := '1';
vi.override := '1';
@ -788,6 +823,8 @@ begin
f_out.redirect <= br.predict;
f_out.redirect_nia <= br_target & "00";
flush_out <= bv.predict or br.predict;

r_out <= vr;
end process;

d1_log: if LOG_LENGTH > 0 generate

@ -14,7 +14,9 @@ entity register_file is
);
port(
clk : in std_logic;
stall : in std_ulogic;

d1_in : in Decode1ToRegisterFileType;
d_in : in Decode2ToRegisterFileType;
d_out : out RegisterFileToDecode2Type;

@ -39,9 +41,13 @@ architecture behaviour of register_file is
signal rd_port_b : std_ulogic_vector(63 downto 0);
signal dbg_data : std_ulogic_vector(63 downto 0);
signal dbg_ack : std_ulogic;
signal addr_1_reg : gspr_index_t;
signal addr_2_reg : gspr_index_t;
signal addr_3_reg : gspr_index_t;
begin
-- synchronous writes
register_write_0: process(clk)
variable a_addr, b_addr, c_addr : gspr_index_t;
variable w_addr : gspr_index_t;
begin
if rising_edge(clk) then
@ -56,6 +62,19 @@ begin
assert not(is_x(w_in.write_data)) and not(is_x(w_in.write_reg)) severity failure;
registers(to_integer(unsigned(w_addr))) <= w_in.write_data;
end if;

a_addr := d1_in.reg_1_addr;
b_addr := d1_in.reg_2_addr;
c_addr := d1_in.reg_3_addr;

if stall = '0' then
addr_1_reg <= a_addr;
addr_2_reg <= b_addr;
addr_3_reg <= c_addr;
end if;
assert (d_in.read1_enable = '0') or (d_in.read1_reg = addr_1_reg) severity failure;
assert (d_in.read2_enable = '0') or (d_in.read2_reg = addr_2_reg) severity failure;
assert (d_in.read3_enable = '0') or (d_in.read3_reg = addr_3_reg) severity failure;
end if;
end process register_write_0;


Loading…
Cancel
Save