|
|
@ -12,25 +12,25 @@ entity core_debug is
|
|
|
|
LOG_LENGTH : natural := 512
|
|
|
|
LOG_LENGTH : natural := 512
|
|
|
|
);
|
|
|
|
);
|
|
|
|
port (
|
|
|
|
port (
|
|
|
|
clk : in std_logic;
|
|
|
|
clk : in std_logic;
|
|
|
|
rst : in std_logic;
|
|
|
|
rst : in std_logic;
|
|
|
|
|
|
|
|
|
|
|
|
dmi_addr : in std_ulogic_vector(3 downto 0);
|
|
|
|
dmi_addr : in std_ulogic_vector(3 downto 0);
|
|
|
|
dmi_din : in std_ulogic_vector(63 downto 0);
|
|
|
|
dmi_din : in std_ulogic_vector(63 downto 0);
|
|
|
|
dmi_dout : out std_ulogic_vector(63 downto 0);
|
|
|
|
dmi_dout : out std_ulogic_vector(63 downto 0);
|
|
|
|
dmi_req : in std_ulogic;
|
|
|
|
dmi_req : in std_ulogic;
|
|
|
|
dmi_wr : in std_ulogic;
|
|
|
|
dmi_wr : in std_ulogic;
|
|
|
|
dmi_ack : out std_ulogic;
|
|
|
|
dmi_ack : out std_ulogic;
|
|
|
|
|
|
|
|
|
|
|
|
-- Debug actions
|
|
|
|
-- Debug actions
|
|
|
|
core_stop : out std_ulogic;
|
|
|
|
core_stop : out std_ulogic;
|
|
|
|
core_rst : out std_ulogic;
|
|
|
|
core_rst : out std_ulogic;
|
|
|
|
icache_rst : out std_ulogic;
|
|
|
|
icache_rst : out std_ulogic;
|
|
|
|
|
|
|
|
|
|
|
|
-- Core status inputs
|
|
|
|
-- Core status inputs
|
|
|
|
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);
|
|
|
|
msr : in std_ulogic_vector(63 downto 0);
|
|
|
|
|
|
|
|
|
|
|
|
-- GSPR register read port
|
|
|
|
-- GSPR register read port
|
|
|
@ -45,8 +45,8 @@ entity core_debug is
|
|
|
|
log_read_data : out std_ulogic_vector(63 downto 0);
|
|
|
|
log_read_data : out std_ulogic_vector(63 downto 0);
|
|
|
|
log_write_addr : out std_ulogic_vector(31 downto 0);
|
|
|
|
log_write_addr : out std_ulogic_vector(31 downto 0);
|
|
|
|
|
|
|
|
|
|
|
|
-- Misc
|
|
|
|
-- Misc
|
|
|
|
terminated_out : out std_ulogic
|
|
|
|
terminated_out : out std_ulogic
|
|
|
|
);
|
|
|
|
);
|
|
|
|
end core_debug;
|
|
|
|
end core_debug;
|
|
|
|
|
|
|
|
|
|
|
@ -60,7 +60,7 @@ architecture behave of core_debug is
|
|
|
|
-- bit 2 : Icache reset
|
|
|
|
-- bit 2 : Icache reset
|
|
|
|
-- bit 3 : Single step
|
|
|
|
-- bit 3 : Single step
|
|
|
|
-- bit 4 : Core start
|
|
|
|
-- bit 4 : Core start
|
|
|
|
constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000";
|
|
|
|
constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000";
|
|
|
|
constant DBG_CORE_CTRL_STOP : integer := 0;
|
|
|
|
constant DBG_CORE_CTRL_STOP : integer := 0;
|
|
|
|
constant DBG_CORE_CTRL_RESET : integer := 1;
|
|
|
|
constant DBG_CORE_CTRL_RESET : integer := 1;
|
|
|
|
constant DBG_CORE_CTRL_ICRESET : integer := 2;
|
|
|
|
constant DBG_CORE_CTRL_ICRESET : integer := 2;
|
|
|
@ -71,13 +71,13 @@ architecture behave of core_debug is
|
|
|
|
-- bit 0 : Core stopping (wait til bit 1 set)
|
|
|
|
-- bit 0 : Core stopping (wait til bit 1 set)
|
|
|
|
-- bit 1 : Core stopped
|
|
|
|
-- bit 1 : Core stopped
|
|
|
|
-- bit 2 : Core terminated (clears with start or reset)
|
|
|
|
-- bit 2 : Core terminated (clears with start or reset)
|
|
|
|
constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001";
|
|
|
|
constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001";
|
|
|
|
constant DBG_CORE_STAT_STOPPING : integer := 0;
|
|
|
|
constant DBG_CORE_STAT_STOPPING : integer := 0;
|
|
|
|
constant DBG_CORE_STAT_STOPPED : integer := 1;
|
|
|
|
constant DBG_CORE_STAT_STOPPED : integer := 1;
|
|
|
|
constant DBG_CORE_STAT_TERM : integer := 2;
|
|
|
|
constant DBG_CORE_STAT_TERM : integer := 2;
|
|
|
|
|
|
|
|
|
|
|
|
-- 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)
|
|
|
|
-- MSR (read only)
|
|
|
|
constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
|
|
|
|
constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
|
|
|
@ -107,14 +107,14 @@ architecture behave of core_debug is
|
|
|
|
signal do_gspr_rd : std_ulogic;
|
|
|
|
signal do_gspr_rd : std_ulogic;
|
|
|
|
signal gspr_index : gspr_index_t;
|
|
|
|
signal gspr_index : gspr_index_t;
|
|
|
|
|
|
|
|
|
|
|
|
signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
|
|
|
|
signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
|
|
|
|
signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0');
|
|
|
|
signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0');
|
|
|
|
signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0');
|
|
|
|
signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0');
|
|
|
|
signal do_log_trigger : std_ulogic := '0';
|
|
|
|
signal do_log_trigger : std_ulogic := '0';
|
|
|
|
signal do_dmi_log_rd : std_ulogic;
|
|
|
|
signal do_dmi_log_rd : std_ulogic;
|
|
|
|
signal dmi_read_log_data : std_ulogic;
|
|
|
|
signal dmi_read_log_data : std_ulogic;
|
|
|
|
signal dmi_read_log_data_1 : std_ulogic;
|
|
|
|
signal dmi_read_log_data_1 : std_ulogic;
|
|
|
|
signal log_trigger_delay : integer range 0 to 255 := 0;
|
|
|
|
signal log_trigger_delay : integer range 0 to 255 := 0;
|
|
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
-- Single cycle register accesses on DMI except for GSPR data
|
|
|
|
-- Single cycle register accesses on DMI except for GSPR data
|
|
|
@ -125,36 +125,36 @@ begin
|
|
|
|
|
|
|
|
|
|
|
|
-- Status register read composition
|
|
|
|
-- Status register read composition
|
|
|
|
stat_reg <= (2 => terminated,
|
|
|
|
stat_reg <= (2 => terminated,
|
|
|
|
1 => core_stopped,
|
|
|
|
1 => core_stopped,
|
|
|
|
0 => stopping,
|
|
|
|
0 => stopping,
|
|
|
|
others => '0');
|
|
|
|
others => '0');
|
|
|
|
|
|
|
|
|
|
|
|
-- DMI read data mux
|
|
|
|
-- DMI read data mux
|
|
|
|
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,
|
|
|
|
msr when DBG_CORE_MSR,
|
|
|
|
dbg_gpr_data when DBG_CORE_GSPR_DATA,
|
|
|
|
dbg_gpr_data when DBG_CORE_GSPR_DATA,
|
|
|
|
log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
|
|
|
|
log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
|
|
|
|
log_dmi_data when DBG_CORE_LOG_DATA,
|
|
|
|
log_dmi_data when DBG_CORE_LOG_DATA,
|
|
|
|
log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
|
|
|
|
log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
|
|
|
|
(others => '0') when others;
|
|
|
|
(others => '0') when others;
|
|
|
|
|
|
|
|
|
|
|
|
-- DMI writes
|
|
|
|
-- DMI writes
|
|
|
|
reg_write: process(clk)
|
|
|
|
reg_write: process(clk)
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
if rising_edge(clk) then
|
|
|
|
if rising_edge(clk) then
|
|
|
|
-- Reset the 1-cycle "do" signals
|
|
|
|
-- Reset the 1-cycle "do" signals
|
|
|
|
do_step <= '0';
|
|
|
|
do_step <= '0';
|
|
|
|
do_reset <= '0';
|
|
|
|
do_reset <= '0';
|
|
|
|
do_icreset <= '0';
|
|
|
|
do_icreset <= '0';
|
|
|
|
do_dmi_log_rd <= '0';
|
|
|
|
do_dmi_log_rd <= '0';
|
|
|
|
|
|
|
|
|
|
|
|
if (rst) then
|
|
|
|
if (rst) then
|
|
|
|
stopping <= '0';
|
|
|
|
stopping <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
log_trigger_delay <= 0;
|
|
|
|
log_trigger_delay <= 0;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
if do_log_trigger = '1' or log_trigger_delay /= 0 then
|
|
|
|
if do_log_trigger = '1' or log_trigger_delay /= 0 then
|
|
|
|
if log_trigger_delay = 255 then
|
|
|
|
if log_trigger_delay = 255 then
|
|
|
|
log_dmi_trigger(1) <= '1';
|
|
|
|
log_dmi_trigger(1) <= '1';
|
|
|
@ -163,32 +163,32 @@ begin
|
|
|
|
log_trigger_delay <= log_trigger_delay + 1;
|
|
|
|
log_trigger_delay <= log_trigger_delay + 1;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
-- Edge detect on dmi_req for 1-shot pulses
|
|
|
|
-- Edge detect on dmi_req for 1-shot pulses
|
|
|
|
dmi_req_1 <= dmi_req;
|
|
|
|
dmi_req_1 <= dmi_req;
|
|
|
|
if dmi_req = '1' and dmi_req_1 = '0' then
|
|
|
|
if dmi_req = '1' and dmi_req_1 = '0' then
|
|
|
|
if dmi_wr = '1' then
|
|
|
|
if dmi_wr = '1' then
|
|
|
|
report("DMI write to " & to_hstring(dmi_addr));
|
|
|
|
report("DMI write to " & to_hstring(dmi_addr));
|
|
|
|
|
|
|
|
|
|
|
|
-- Control register actions
|
|
|
|
-- Control register actions
|
|
|
|
if dmi_addr = DBG_CORE_CTRL then
|
|
|
|
if dmi_addr = DBG_CORE_CTRL then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_RESET) = '1' then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_RESET) = '1' then
|
|
|
|
do_reset <= '1';
|
|
|
|
do_reset <= '1';
|
|
|
|
terminated <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if dmi_din(DBG_CORE_CTRL_STOP) = '1' then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_STOP) = '1' then
|
|
|
|
stopping <= '1';
|
|
|
|
stopping <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if dmi_din(DBG_CORE_CTRL_STEP) = '1' then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_STEP) = '1' then
|
|
|
|
do_step <= '1';
|
|
|
|
do_step <= '1';
|
|
|
|
terminated <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then
|
|
|
|
do_icreset <= '1';
|
|
|
|
do_icreset <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
if dmi_din(DBG_CORE_CTRL_START) = '1' then
|
|
|
|
if dmi_din(DBG_CORE_CTRL_START) = '1' then
|
|
|
|
stopping <= '0';
|
|
|
|
stopping <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
terminated <= '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
elsif dmi_addr = DBG_CORE_GSPR_INDEX then
|
|
|
|
elsif dmi_addr = DBG_CORE_GSPR_INDEX then
|
|
|
|
gspr_index <= dmi_din(gspr_index_t'left downto 0);
|
|
|
|
gspr_index <= dmi_din(gspr_index_t'left downto 0);
|
|
|
|
elsif dmi_addr = DBG_CORE_LOG_ADDR then
|
|
|
|
elsif dmi_addr = DBG_CORE_LOG_ADDR then
|
|
|
@ -196,17 +196,17 @@ begin
|
|
|
|
do_dmi_log_rd <= '1';
|
|
|
|
do_dmi_log_rd <= '1';
|
|
|
|
elsif dmi_addr = DBG_CORE_LOG_TRIGGER then
|
|
|
|
elsif dmi_addr = DBG_CORE_LOG_TRIGGER then
|
|
|
|
log_dmi_trigger <= dmi_din;
|
|
|
|
log_dmi_trigger <= dmi_din;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
report("DMI read from " & to_string(dmi_addr));
|
|
|
|
report("DMI read from " & to_string(dmi_addr));
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
elsif dmi_read_log_data = '0' and dmi_read_log_data_1 = '1' then
|
|
|
|
elsif dmi_read_log_data = '0' and dmi_read_log_data_1 = '1' then
|
|
|
|
-- Increment log_dmi_addr after the end of a read from DBG_CORE_LOG_DATA
|
|
|
|
-- Increment log_dmi_addr after the end of a read from DBG_CORE_LOG_DATA
|
|
|
|
log_dmi_addr(LOG_INDEX_BITS + 1 downto 0) <=
|
|
|
|
log_dmi_addr(LOG_INDEX_BITS + 1 downto 0) <=
|
|
|
|
std_ulogic_vector(unsigned(log_dmi_addr(LOG_INDEX_BITS+1 downto 0)) + 1);
|
|
|
|
std_ulogic_vector(unsigned(log_dmi_addr(LOG_INDEX_BITS+1 downto 0)) + 1);
|
|
|
|
do_dmi_log_rd <= '1';
|
|
|
|
do_dmi_log_rd <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
dmi_read_log_data_1 <= dmi_read_log_data;
|
|
|
|
dmi_read_log_data_1 <= dmi_read_log_data;
|
|
|
|
if dmi_req = '1' and dmi_addr = DBG_CORE_LOG_DATA then
|
|
|
|
if dmi_req = '1' and dmi_addr = DBG_CORE_LOG_DATA then
|
|
|
|
dmi_read_log_data <= '1';
|
|
|
|
dmi_read_log_data <= '1';
|
|
|
@ -214,15 +214,15 @@ begin
|
|
|
|
dmi_read_log_data <= '0';
|
|
|
|
dmi_read_log_data <= '0';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
|
|
|
|
|
|
|
|
-- Set core stop on terminate. We'll be stopping some time *after*
|
|
|
|
-- Set core stop on terminate. We'll be stopping some time *after*
|
|
|
|
-- the offending instruction, at least until we can do back flushes
|
|
|
|
-- the offending instruction, at least until we can do back flushes
|
|
|
|
-- that preserve NIA which we can't just yet.
|
|
|
|
-- that preserve NIA which we can't just yet.
|
|
|
|
if terminate = '1' then
|
|
|
|
if terminate = '1' then
|
|
|
|
stopping <= '1';
|
|
|
|
stopping <= '1';
|
|
|
|
terminated <= '1';
|
|
|
|
terminated <= '1';
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end if;
|
|
|
|
end process;
|
|
|
|
end process;
|
|
|
|
|
|
|
|
|
|
|
|
dbg_gpr_addr <= gspr_index;
|
|
|
|
dbg_gpr_addr <= gspr_index;
|
|
|
@ -237,15 +237,15 @@ begin
|
|
|
|
maybe_log: if LOG_LENGTH > 0 generate
|
|
|
|
maybe_log: if LOG_LENGTH > 0 generate
|
|
|
|
subtype log_ptr_t is unsigned(LOG_INDEX_BITS - 1 downto 0);
|
|
|
|
subtype log_ptr_t is unsigned(LOG_INDEX_BITS - 1 downto 0);
|
|
|
|
type log_array_t is array(0 to LOG_LENGTH - 1) of std_ulogic_vector(255 downto 0);
|
|
|
|
type log_array_t is array(0 to LOG_LENGTH - 1) of std_ulogic_vector(255 downto 0);
|
|
|
|
signal log_array : log_array_t;
|
|
|
|
signal log_array : log_array_t;
|
|
|
|
signal log_rd_ptr : log_ptr_t;
|
|
|
|
signal log_rd_ptr : log_ptr_t;
|
|
|
|
signal log_wr_ptr : log_ptr_t;
|
|
|
|
signal log_wr_ptr : log_ptr_t;
|
|
|
|
signal log_toggle : std_ulogic;
|
|
|
|
signal log_toggle : std_ulogic;
|
|
|
|
signal log_wr_enable : std_ulogic;
|
|
|
|
signal log_wr_enable : std_ulogic;
|
|
|
|
signal log_rd_ptr_latched : log_ptr_t;
|
|
|
|
signal log_rd_ptr_latched : log_ptr_t;
|
|
|
|
signal log_rd : std_ulogic_vector(255 downto 0);
|
|
|
|
signal log_rd : std_ulogic_vector(255 downto 0);
|
|
|
|
signal log_dmi_reading : std_ulogic;
|
|
|
|
signal log_dmi_reading : std_ulogic;
|
|
|
|
signal log_dmi_read_done : std_ulogic;
|
|
|
|
signal log_dmi_read_done : std_ulogic;
|
|
|
|
|
|
|
|
|
|
|
|
function select_dword(data : std_ulogic_vector(255 downto 0);
|
|
|
|
function select_dword(data : std_ulogic_vector(255 downto 0);
|
|
|
|
addr : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
|
|
|
|
addr : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
|
|
|
|