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>
pull/169/head
Paul Mackerras 4 years ago
parent 5d282a950c
commit dd2e71930c

@ -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
);


@ -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;

@ -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 =>

@ -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;

@ -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)

Loading…
Cancel
Save