From dd2e71930c6854f2d251526ff29041c5d90e8e24 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 2 May 2020 13:26:30 +1000 Subject: [PATCH] debug: Provide a way to examine GPRs, fast SPRs and MSR This provides commands on the debug interface to read the value of the MSR or any of the 64 GSPR register file entries. The GSPR values are read using the B port of the register file in a cycle when decode2 is not using it. Signed-off-by: Paul Mackerras --- core.vhdl | 17 +++++++++++++++++ core_debug.vhdl | 31 +++++++++++++++++++++++++++++-- decode2.vhdl | 6 +++--- execute1.vhdl | 4 ++++ register_file.vhdl | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 88 insertions(+), 6 deletions(-) diff --git a/core.vhdl b/core.vhdl index 0e60905..acb37cc 100644 --- a/core.vhdl +++ b/core.vhdl @@ -95,6 +95,13 @@ architecture behave of core is signal dbg_core_rst: std_ulogic; signal dbg_icache_rst: std_ulogic; + signal dbg_gpr_req : std_ulogic; + signal dbg_gpr_ack : std_ulogic; + signal dbg_gpr_addr : gspr_index_t; + signal dbg_gpr_data : std_ulogic_vector(63 downto 0); + + signal msr : std_ulogic_vector(63 downto 0); + -- Debug status signal dbg_core_is_stopped: std_ulogic; @@ -213,6 +220,10 @@ begin d_in => decode2_to_register_file, d_out => register_file_to_decode2, w_in => writeback_to_register_file, + dbg_gpr_req => dbg_gpr_req, + dbg_gpr_ack => dbg_gpr_ack, + dbg_gpr_addr => dbg_gpr_addr, + dbg_gpr_data => dbg_gpr_data, sim_dump => terminate, sim_dump_done => sim_cr_dump ); @@ -244,6 +255,7 @@ begin f_out => execute1_to_fetch1, e_out => execute1_to_writeback, icache_inval => ex1_icache_inval, + dbg_msr_out => msr, terminate_out => terminate ); @@ -301,6 +313,11 @@ begin terminate => terminate, core_stopped => dbg_core_is_stopped, nia => fetch1_to_icache.nia, + msr => msr, + dbg_gpr_req => dbg_gpr_req, + dbg_gpr_ack => dbg_gpr_ack, + dbg_gpr_addr => dbg_gpr_addr, + dbg_gpr_data => dbg_gpr_data, terminated_out => terminated_out ); diff --git a/core_debug.vhdl b/core_debug.vhdl index ae4414e..c97213b 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -26,6 +26,13 @@ entity core_debug is terminate : in std_ulogic; core_stopped : in std_ulogic; nia : in std_ulogic_vector(63 downto 0); + msr : in std_ulogic_vector(63 downto 0); + + -- GSPR register read port + dbg_gpr_req : out std_ulogic; + dbg_gpr_ack : in std_ulogic; + dbg_gpr_addr : out gspr_index_t; + dbg_gpr_data : in std_ulogic_vector(63 downto 0); -- Misc terminated_out : out std_ulogic @@ -61,6 +68,15 @@ architecture behave of core_debug is -- NIA register (read only for now) constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010"; + -- MSR (read only) + constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011"; + + -- GSPR register index + constant DBG_CORE_GSPR_INDEX : std_ulogic_vector(3 downto 0) := "0100"; + + -- GSPR register data + constant DBG_CORE_GSPR_DATA : std_ulogic_vector(3 downto 0) := "0101"; + -- Some internal wires signal stat_reg : std_ulogic_vector(63 downto 0); @@ -70,10 +86,15 @@ architecture behave of core_debug is signal do_reset : std_ulogic; signal do_icreset : std_ulogic; signal terminated : std_ulogic; + signal do_gspr_rd : std_ulogic; + signal gspr_index : gspr_index_t; begin - -- Single cycle register accesses on DMI - dmi_ack <= dmi_req; + -- Single cycle register accesses on DMI except for GSPR data + dmi_ack <= dmi_req when dmi_addr /= DBG_CORE_GSPR_DATA + else dbg_gpr_ack; + dbg_gpr_req <= dmi_req when dmi_addr = DBG_CORE_GSPR_DATA + else '0'; -- Status register read composition stat_reg <= (2 => terminated, @@ -85,6 +106,8 @@ begin with dmi_addr select dmi_dout <= stat_reg when DBG_CORE_STAT, nia when DBG_CORE_NIA, + msr when DBG_CORE_MSR, + dbg_gpr_data when DBG_CORE_GSPR_DATA, (others => '0') when others; -- DMI writes @@ -126,6 +149,8 @@ begin stopping <= '0'; terminated <= '0'; end if; + elsif dmi_addr = DBG_CORE_GSPR_INDEX then + gspr_index <= dmi_din(gspr_index_t'left downto 0); end if; else report("DMI read from " & to_string(dmi_addr)); @@ -143,6 +168,8 @@ begin end if; end process; + dbg_gpr_addr <= gspr_index; + -- Core control signals generated by the debug module core_stop <= stopping and not do_step; core_rst <= do_reset; diff --git a/decode2.vhdl b/decode2.vhdl index edcc50c..b239392 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -285,9 +285,9 @@ begin decoded_reg_c := decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn, r_in.read3_data); decoded_reg_o := decode_output_reg (d_in.decode.output_reg_a, d_in.insn, d_in.ispr1); - r_out.read1_enable <= decoded_reg_a.reg_valid; - r_out.read2_enable <= decoded_reg_b.reg_valid; - r_out.read3_enable <= decoded_reg_c.reg_valid; + r_out.read1_enable <= decoded_reg_a.reg_valid and d_in.valid; + r_out.read2_enable <= decoded_reg_b.reg_valid and d_in.valid; + r_out.read3_enable <= decoded_reg_c.reg_valid and d_in.valid; case d_in.decode.length is when is1B => diff --git a/execute1.vhdl b/execute1.vhdl index c479a45..82776e2 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -32,6 +32,8 @@ entity execute1 is e_out : out Execute1ToWritebackType; + dbg_msr_out : out std_ulogic_vector(63 downto 0); + icache_inval : out std_ulogic; terminate_out : out std_ulogic ); @@ -217,6 +219,8 @@ begin d_out => divider_to_x ); + dbg_msr_out <= ctrl.msr; + a_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data1 = '1' else e_in.read_data1; b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2; c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3; diff --git a/register_file.vhdl b/register_file.vhdl index 6a4c989..2cffeea 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -17,6 +17,11 @@ entity register_file is w_in : in WritebackToRegisterFileType; + dbg_gpr_req : in std_ulogic; + dbg_gpr_ack : out std_ulogic; + dbg_gpr_addr : in gspr_index_t; + dbg_gpr_data : out std_ulogic_vector(63 downto 0); + -- debug sim_dump : in std_ulogic; sim_dump_done : out std_ulogic @@ -26,6 +31,9 @@ end entity register_file; architecture behaviour of register_file is type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0); signal registers : regfile := (others => (others => '0')); + signal rd_port_b : std_ulogic_vector(63 downto 0); + signal dbg_data : std_ulogic_vector(63 downto 0); + signal dbg_ack : std_ulogic; begin -- synchronous writes register_write_0: process(clk) @@ -45,6 +53,7 @@ begin -- asynchronous reads register_read_0: process(all) + variable b_addr : gspr_index_t; begin if d_in.read1_enable = '1' then report "Reading GPR " & to_hstring(d_in.read1_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read1_reg)))); @@ -56,7 +65,14 @@ begin report "Reading GPR " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg)))); end if; d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg))); - d_out.read2_data <= registers(to_integer(unsigned(d_in.read2_reg))); + -- B read port is multiplexed with reads from the debug circuitry + if d_in.read2_enable = '0' and dbg_gpr_req = '1' and dbg_ack = '0' then + b_addr := dbg_gpr_addr; + else + b_addr := d_in.read2_reg; + end if; + rd_port_b <= registers(to_integer(unsigned(b_addr))); + d_out.read2_data <= rd_port_b; d_out.read3_data <= registers(to_integer(unsigned(gpr_to_gspr(d_in.read3_reg)))); -- Forward any written data @@ -73,6 +89,24 @@ begin end if; end process register_read_0; + -- Latch read data and ack if dbg read requested and B port not busy + dbg_register_read: process(clk) + begin + if rising_edge(clk) then + if dbg_gpr_req = '1' then + if d_in.read2_enable = '0' and dbg_ack = '0' then + dbg_data <= rd_port_b; + dbg_ack <= '1'; + end if; + else + dbg_ack <= '0'; + end if; + end if; + end process; + + dbg_gpr_ack <= dbg_ack; + dbg_gpr_data <= dbg_data; + -- Dump registers if core terminates sim_dump_test: if SIM generate dump_registers: process(all)