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 <paulus@ozlabs.org>
jtag-port
Paul Mackerras 5 years ago
parent 5d282a950c
commit dd2e71930c

@ -95,6 +95,13 @@ architecture behave of core is
signal dbg_core_rst: std_ulogic; signal dbg_core_rst: std_ulogic;
signal dbg_icache_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 -- Debug status
signal dbg_core_is_stopped: std_ulogic; signal dbg_core_is_stopped: std_ulogic;


@ -213,6 +220,10 @@ begin
d_in => decode2_to_register_file, d_in => decode2_to_register_file,
d_out => register_file_to_decode2, d_out => register_file_to_decode2,
w_in => writeback_to_register_file, 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 => terminate,
sim_dump_done => sim_cr_dump sim_dump_done => sim_cr_dump
); );
@ -244,6 +255,7 @@ begin
f_out => execute1_to_fetch1, f_out => execute1_to_fetch1,
e_out => execute1_to_writeback, e_out => execute1_to_writeback,
icache_inval => ex1_icache_inval, icache_inval => ex1_icache_inval,
dbg_msr_out => msr,
terminate_out => terminate terminate_out => terminate
); );


@ -301,6 +313,11 @@ begin
terminate => terminate, terminate => terminate,
core_stopped => dbg_core_is_stopped, core_stopped => dbg_core_is_stopped,
nia => fetch1_to_icache.nia, 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 terminated_out => terminated_out
); );



@ -26,6 +26,13 @@ entity core_debug is
terminate : in std_ulogic; terminate : in std_ulogic;
core_stopped : in std_ulogic; core_stopped : in std_ulogic;
nia : in std_ulogic_vector(63 downto 0); 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 -- Misc
terminated_out : out std_ulogic terminated_out : out std_ulogic
@ -61,6 +68,15 @@ architecture behave of core_debug is
-- NIA register (read only for now) -- NIA register (read only for now)
constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010"; 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 -- Some internal wires
signal stat_reg : std_ulogic_vector(63 downto 0); 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_reset : std_ulogic;
signal do_icreset : std_ulogic; signal do_icreset : std_ulogic;
signal terminated : std_ulogic; signal terminated : std_ulogic;
signal do_gspr_rd : std_ulogic;
signal gspr_index : gspr_index_t;


begin begin
-- Single cycle register accesses on DMI -- Single cycle register accesses on DMI except for GSPR data
dmi_ack <= dmi_req; 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 -- Status register read composition
stat_reg <= (2 => terminated, stat_reg <= (2 => terminated,
@ -85,6 +106,8 @@ begin
with dmi_addr select dmi_dout <= with dmi_addr select dmi_dout <=
stat_reg when DBG_CORE_STAT, stat_reg when DBG_CORE_STAT,
nia when DBG_CORE_NIA, nia when DBG_CORE_NIA,
msr when DBG_CORE_MSR,
dbg_gpr_data when DBG_CORE_GSPR_DATA,
(others => '0') when others; (others => '0') when others;


-- DMI writes -- DMI writes
@ -126,6 +149,8 @@ begin
stopping <= '0'; stopping <= '0';
terminated <= '0'; terminated <= '0';
end if; end if;
elsif dmi_addr = DBG_CORE_GSPR_INDEX then
gspr_index <= dmi_din(gspr_index_t'left downto 0);
end if; end if;
else else
report("DMI read from " & to_string(dmi_addr)); report("DMI read from " & to_string(dmi_addr));
@ -143,6 +168,8 @@ begin
end if; end if;
end process; end process;


dbg_gpr_addr <= gspr_index;

-- Core control signals generated by the debug module -- Core control signals generated by the debug module
core_stop <= stopping and not do_step; core_stop <= stopping and not do_step;
core_rst <= do_reset; core_rst <= do_reset;

@ -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_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); 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.read1_enable <= decoded_reg_a.reg_valid and d_in.valid;
r_out.read2_enable <= decoded_reg_b.reg_valid; r_out.read2_enable <= decoded_reg_b.reg_valid and d_in.valid;
r_out.read3_enable <= decoded_reg_c.reg_valid; r_out.read3_enable <= decoded_reg_c.reg_valid and d_in.valid;


case d_in.decode.length is case d_in.decode.length is
when is1B => when is1B =>

@ -32,6 +32,8 @@ entity execute1 is


e_out : out Execute1ToWritebackType; e_out : out Execute1ToWritebackType;


dbg_msr_out : out std_ulogic_vector(63 downto 0);

icache_inval : out std_ulogic; icache_inval : out std_ulogic;
terminate_out : out std_ulogic terminate_out : out std_ulogic
); );
@ -217,6 +219,8 @@ begin
d_out => divider_to_x 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; 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; 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; c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3;

@ -17,6 +17,11 @@ entity register_file is


w_in : in WritebackToRegisterFileType; 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 -- debug
sim_dump : in std_ulogic; sim_dump : in std_ulogic;
sim_dump_done : out std_ulogic sim_dump_done : out std_ulogic
@ -26,6 +31,9 @@ end entity register_file;
architecture behaviour of register_file is architecture behaviour of register_file is
type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0); type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0);
signal registers : regfile := (others => (others => '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 begin
-- synchronous writes -- synchronous writes
register_write_0: process(clk) register_write_0: process(clk)
@ -45,6 +53,7 @@ begin


-- asynchronous reads -- asynchronous reads
register_read_0: process(all) register_read_0: process(all)
variable b_addr : gspr_index_t;
begin begin
if d_in.read1_enable = '1' then 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)))); 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)))); report "Reading GPR " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg))));
end if; end if;
d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg))); 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)))); d_out.read3_data <= registers(to_integer(unsigned(gpr_to_gspr(d_in.read3_reg))));


-- Forward any written data -- Forward any written data
@ -73,6 +89,24 @@ begin
end if; end if;
end process register_read_0; 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 -- Dump registers if core terminates
sim_dump_test: if SIM generate sim_dump_test: if SIM generate
dump_registers: process(all) dump_registers: process(all)

Loading…
Cancel
Save