mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-10 22:31:45 +00:00
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>
This commit is contained in:
17
core.vhdl
17
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
|
||||
);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user