From 337b1042501a84b3f28b11e94e650800177a63ce Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 12 Jul 2022 11:20:17 +1000 Subject: [PATCH] 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 --- common.vhdl | 27 +++-------- core.vhdl | 6 ++- decode1.vhdl | 45 ++++------------- decode2.vhdl | 57 +++++++++++++--------- execute1.vhdl | 117 +++++++++++++++++++++++---------------------- register_file.vhdl | 3 -- 6 files changed, 118 insertions(+), 137 deletions(-) diff --git a/common.vhdl b/common.vhdl index 74341d1..7df451b 100644 --- a/common.vhdl +++ b/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 diff --git a/core.vhdl b/core.vhdl index b2f2704..82c66b4 100644 --- a/core.vhdl +++ b/core.vhdl @@ -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, diff --git a/decode1.vhdl b/decode1.vhdl index fd01d61..b6cea31 100644 --- a/decode1.vhdl +++ b/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 diff --git a/decode2.vhdl b/decode2.vhdl index c76b7f5..928ec94 100644 --- a/decode2.vhdl +++ b/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 diff --git a/execute1.vhdl b/execute1.vhdl index b0b2f98..5ee830b 100644 --- a/execute1.vhdl +++ b/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 diff --git a/register_file.vhdl b/register_file.vhdl index 0235dfc..ed856cb 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -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';