mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 06:07:52 -04:00
[OCD.DM] add support for legacy spec mode
+ hardware cleanups and optimizations
This commit is contained in:
parent
71ea85a668
commit
aeacd06f44
1 changed files with 157 additions and 185 deletions
|
@ -1,8 +1,8 @@
|
|||
-- #################################################################################################
|
||||
-- # << NEORV32 - RISC-V-Compatible Debug Module (DM) >> #
|
||||
-- # ********************************************************************************************* #
|
||||
-- # Compatible to the "Minimal RISC-V External Debug Spec. Version 1.0" using "execution-based" #
|
||||
-- # debugging scheme (via the program buffer). #
|
||||
-- # Compatible to the "Minimal RISC-V External Debug Spec. Version 1.0 [Sdext]" (or v0.13) using #
|
||||
-- # "execution-based" debugging scheme (via the program buffer). FOR A SINGLE HART ONLY! #
|
||||
-- # ********************************************************************************************* #
|
||||
-- # Key features: #
|
||||
-- # * register access commands only #
|
||||
|
@ -10,12 +10,6 @@
|
|||
-- # * for a single hart only #
|
||||
-- # * 2 general purpose program buffer entries #
|
||||
-- # * 1 general purpose data buffer entry #
|
||||
-- # #
|
||||
-- # CPU access: #
|
||||
-- # * ROM for "park loop" code #
|
||||
-- # * program buffer #
|
||||
-- # * data buffer #
|
||||
-- # * control and status register #
|
||||
-- # ********************************************************************************************* #
|
||||
-- # BSD 3-Clause License #
|
||||
-- # #
|
||||
|
@ -57,36 +51,30 @@ use neorv32.neorv32_package.all;
|
|||
|
||||
entity neorv32_debug_dm is
|
||||
generic (
|
||||
CPU_BASE_ADDR : std_ulogic_vector(31 downto 0)
|
||||
CPU_BASE_ADDR : std_ulogic_vector(31 downto 0);
|
||||
LEGACY_MODE : boolean -- false = spec. v1.0, true = spec. v0.13
|
||||
);
|
||||
port (
|
||||
-- global control --
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
rstn_i : in std_ulogic; -- global reset line, low-active
|
||||
cpu_debug_i : in std_ulogic; -- CPU is in debug mode
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
rstn_i : in std_ulogic; -- global reset line, low-active
|
||||
cpu_debug_i : in std_ulogic; -- CPU is in debug mode
|
||||
-- debug module interface (DMI) --
|
||||
dmi_req_valid_i : in std_ulogic;
|
||||
dmi_req_ready_o : out std_ulogic; -- DMI is allowed to make new requests when set
|
||||
dmi_req_address_i : in std_ulogic_vector(05 downto 0);
|
||||
dmi_req_op_i : in std_ulogic_vector(01 downto 0);
|
||||
dmi_req_data_i : in std_ulogic_vector(31 downto 0);
|
||||
dmi_rsp_valid_o : out std_ulogic; -- response valid when set
|
||||
dmi_rsp_ready_i : in std_ulogic; -- ready to receive respond
|
||||
dmi_rsp_data_o : out std_ulogic_vector(31 downto 0);
|
||||
dmi_rsp_op_o : out std_ulogic_vector(01 downto 0);
|
||||
dmi_req_i : in dmi_req_t; -- request
|
||||
dmi_rsp_o : out dmi_rsp_t; -- response
|
||||
-- CPU bus access --
|
||||
bus_req_i : in bus_req_t; -- bus request
|
||||
bus_rsp_o : out bus_rsp_t; -- bus response
|
||||
bus_req_i : in bus_req_t; -- bus request
|
||||
bus_rsp_o : out bus_rsp_t; -- bus response
|
||||
-- CPU control --
|
||||
cpu_ndmrstn_o : out std_ulogic; -- soc reset
|
||||
cpu_halt_req_o : out std_ulogic -- request hart to halt (enter debug mode)
|
||||
cpu_ndmrstn_o : out std_ulogic; -- soc reset
|
||||
cpu_halt_req_o : out std_ulogic -- request hart to halt (enter debug mode)
|
||||
);
|
||||
end neorv32_debug_dm;
|
||||
|
||||
architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
||||
|
||||
-- **********************************************************
|
||||
-- DM Layout
|
||||
-- DM Memory Layout
|
||||
-- **********************************************************
|
||||
constant dm_code_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"00"); -- base address of code ROM (park loop)
|
||||
constant dm_pbuf_base_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(CPU_BASE_ADDR) + x"40"); -- base address of program buffer (PBUF)
|
||||
|
@ -97,24 +85,19 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
|||
-- DMI Access
|
||||
-- **********************************************************
|
||||
|
||||
-- DM operations --
|
||||
constant dmi_nop_c : std_ulogic_vector(1 downto 0) := "00"; -- no operation
|
||||
constant dmi_read_c : std_ulogic_vector(1 downto 0) := "01"; -- read data
|
||||
constant dmi_write_c : std_ulogic_vector(1 downto 0) := "10"; -- write data
|
||||
constant dmi_reserved_c : std_ulogic_vector(1 downto 0) := "11"; -- reserved
|
||||
|
||||
-- available DMI registers --
|
||||
constant addr_data0_c : std_ulogic_vector(5 downto 0) := "00" & x"4";
|
||||
constant addr_dmcontrol_c : std_ulogic_vector(5 downto 0) := "01" & x"0";
|
||||
constant addr_dmstatus_c : std_ulogic_vector(5 downto 0) := "01" & x"1";
|
||||
constant addr_hartinfo_c : std_ulogic_vector(5 downto 0) := "01" & x"2";
|
||||
constant addr_abstractcs_c : std_ulogic_vector(5 downto 0) := "01" & x"6";
|
||||
constant addr_command_c : std_ulogic_vector(5 downto 0) := "01" & x"7";
|
||||
constant addr_abstractauto_c : std_ulogic_vector(5 downto 0) := "01" & x"8";
|
||||
constant addr_nextdm_c : std_ulogic_vector(5 downto 0) := "01" & x"d";
|
||||
constant addr_progbuf0_c : std_ulogic_vector(5 downto 0) := "10" & x"0";
|
||||
constant addr_progbuf1_c : std_ulogic_vector(5 downto 0) := "10" & x"1";
|
||||
constant addr_sbcs_c : std_ulogic_vector(5 downto 0) := "11" & x"8";
|
||||
constant addr_data0_c : std_ulogic_vector(6 downto 0) := "000" & x"4";
|
||||
constant addr_dmcontrol_c : std_ulogic_vector(6 downto 0) := "001" & x"0";
|
||||
constant addr_dmstatus_c : std_ulogic_vector(6 downto 0) := "001" & x"1";
|
||||
constant addr_hartinfo_c : std_ulogic_vector(6 downto 0) := "001" & x"2";
|
||||
constant addr_abstractcs_c : std_ulogic_vector(6 downto 0) := "001" & x"6";
|
||||
constant addr_command_c : std_ulogic_vector(6 downto 0) := "001" & x"7";
|
||||
constant addr_abstractauto_c : std_ulogic_vector(6 downto 0) := "001" & x"8";
|
||||
constant addr_nextdm_c : std_ulogic_vector(6 downto 0) := "001" & x"d";
|
||||
constant addr_progbuf0_c : std_ulogic_vector(6 downto 0) := "010" & x"0";
|
||||
constant addr_progbuf1_c : std_ulogic_vector(6 downto 0) := "010" & x"1";
|
||||
constant addr_sbcs_c : std_ulogic_vector(6 downto 0) := "011" & x"8";
|
||||
constant addr_haltsum0_c : std_ulogic_vector(6 downto 0) := "100" & x"0";
|
||||
|
||||
-- RISC-V 32-bit instruction prototypes --
|
||||
constant instr_nop_c : std_ulogic_vector(31 downto 0) := x"00000013"; -- nop
|
||||
|
@ -156,10 +139,11 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
|||
-- **********************************************************
|
||||
|
||||
-- DM configuration --
|
||||
constant nscratch_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of dscratch registers in CPU
|
||||
constant datasize_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of data registers in memory/CSR space
|
||||
constant nscratch_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of dscratch registers in CPU (=1)
|
||||
constant datasize_c : std_ulogic_vector(03 downto 0) := "0001"; -- number of data registers in memory/CSR space (=1)
|
||||
constant dataaddr_c : std_ulogic_vector(11 downto 0) := dm_data_base_c(11 downto 0); -- signed base address of data registers in memory/CSR space
|
||||
constant dataaccess_c : std_ulogic := '1'; -- 1: abstract data is memory-mapped, 0: abstract data is CSR-mapped
|
||||
constant dm_version_c : std_ulogic_vector(03 downto 0) := cond_sel_suv_f(LEGACY_MODE, "0010", "0011"); -- version: v0.13 / v1.0
|
||||
|
||||
-- debug module controller --
|
||||
type dm_ctrl_state_t is (CMD_IDLE, CMD_EXE_CHECK, CMD_EXE_PREPARE, CMD_EXE_TRIGGER, CMD_EXE_BUSY, CMD_EXE_ERROR);
|
||||
|
@ -181,9 +165,12 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
|||
end record;
|
||||
signal dm_ctrl : dm_ctrl_t;
|
||||
|
||||
-- program buffer access --
|
||||
type prog_buf_t is array (0 to 3) of std_ulogic_vector(31 downto 0);
|
||||
signal prog_buf : prog_buf_t;
|
||||
|
||||
-- **********************************************************
|
||||
-- CPU Bus Interface
|
||||
-- CPU Bus and Debug Interfaces
|
||||
-- **********************************************************
|
||||
|
||||
-- status and control register - bits --
|
||||
|
@ -230,24 +217,21 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
|
|||
exception_ack : std_ulogic; -- CPU has detected an exception (single-shot)
|
||||
progbuf : std_ulogic_vector(255 downto 0); -- program buffer, 4 32-bit entries
|
||||
data_we : std_ulogic; -- write abstract data
|
||||
wdata : std_ulogic_vector(31 downto 0); -- abstract write data
|
||||
rdata : std_ulogic_vector(31 downto 0); -- abstract read data
|
||||
data_reg : std_ulogic_vector(31 downto 0); -- memory-mapped data exchange register
|
||||
end record;
|
||||
signal dci : dci_t;
|
||||
|
||||
-- data buffer --
|
||||
signal data_buf : std_ulogic_vector(31 downto 0);
|
||||
|
||||
-- program buffer access --
|
||||
type prog_buf_t is array (0 to 3) of std_ulogic_vector(31 downto 0);
|
||||
signal prog_buf : prog_buf_t;
|
||||
|
||||
begin
|
||||
|
||||
-- Info -----------------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
assert not (LEGACY_MODE = true) report "NEORV32 [OCD] on-chip debugger: DM compatible to debug spec. version 0.13" severity note;
|
||||
assert not (LEGACY_MODE = false) report "NEORV32 [OCD] on-chip debugger: DM compatible to debug spec. version 1.0" severity note;
|
||||
|
||||
-- DMI Access -----------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
dmi_wren <= '1' when (dmi_req_valid_i = '1') and (dmi_req_op_i = dmi_write_c) else '0';
|
||||
dmi_rden <= '1' when (dmi_req_valid_i = '1') and (dmi_req_op_i = dmi_read_c) else '0';
|
||||
dmi_wren <= '1' when (dmi_req_i.op = dmi_req_wr_c) else '0';
|
||||
dmi_rden <= '1' when (dmi_req_i.op = dmi_req_rd_c) else '0';
|
||||
|
||||
|
||||
-- Debug Module Command Controller --------------------------------------------------------
|
||||
|
@ -277,7 +261,7 @@ begin
|
|||
when CMD_IDLE => -- wait for new abstract command
|
||||
-- ------------------------------------------------------------
|
||||
if (dmi_wren = '1') then -- valid DM write access
|
||||
if (dmi_req_address_i = addr_command_c) then
|
||||
if (dmi_req_i.addr = addr_command_c) then
|
||||
if (dm_ctrl.cmderr = "000") then -- only execute if no error
|
||||
dm_ctrl.state <= CMD_EXE_CHECK;
|
||||
end if;
|
||||
|
@ -299,7 +283,7 @@ begin
|
|||
dm_ctrl.illegal_state <= '1';
|
||||
dm_ctrl.state <= CMD_EXE_ERROR;
|
||||
end if;
|
||||
else -- invalid command
|
||||
else -- error! invalid command
|
||||
dm_ctrl.illegal_cmd <= '1';
|
||||
dm_ctrl.state <= CMD_EXE_ERROR;
|
||||
end if;
|
||||
|
@ -458,63 +442,63 @@ begin
|
|||
if (dmi_wren = '1') then -- valid DMI write request
|
||||
|
||||
-- debug module control --
|
||||
if (dmi_req_address_i = addr_dmcontrol_c) then
|
||||
dm_reg.halt_req <= dmi_req_data_i(31); -- haltreq (-/w): write 1 to request halt; has to be cleared again by debugger
|
||||
dm_reg.resume_req <= dmi_req_data_i(30); -- resumereq (-/w1): write 1 to request resume; auto-clears
|
||||
dm_reg.reset_ack <= dmi_req_data_i(28); -- ackhavereset (-/w1): write 1 to ACK reset; auto-clears
|
||||
dm_reg.dmcontrol_ndmreset <= dmi_req_data_i(01); -- ndmreset (r/w): soc reset
|
||||
dm_reg.dmcontrol_dmactive <= dmi_req_data_i(00); -- dmactive (r/w): DM reset
|
||||
if (dmi_req_i.addr = addr_dmcontrol_c) then
|
||||
dm_reg.halt_req <= dmi_req_i.data(31); -- haltreq (-/w): write 1 to request halt; has to be cleared again by debugger
|
||||
dm_reg.resume_req <= dmi_req_i.data(30); -- resumereq (-/w1): write 1 to request resume; auto-clears
|
||||
dm_reg.reset_ack <= dmi_req_i.data(28); -- ackhavereset (-/w1): write 1 to ACK reset; auto-clears
|
||||
dm_reg.dmcontrol_ndmreset <= dmi_req_i.data(01); -- ndmreset (r/w): soc reset
|
||||
dm_reg.dmcontrol_dmactive <= dmi_req_i.data(00); -- dmactive (r/w): DM reset
|
||||
end if;
|
||||
|
||||
-- write abstract command --
|
||||
if (dmi_req_address_i = addr_command_c) then
|
||||
if (dmi_req_i.addr = addr_command_c) then
|
||||
if (dm_ctrl.busy = '0') and (dm_ctrl.cmderr = "000") then -- idle and no errors yet
|
||||
dm_reg.command <= dmi_req_data_i;
|
||||
dm_reg.command <= dmi_req_i.data;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- write abstract command autoexec --
|
||||
if (dmi_req_address_i = addr_abstractauto_c) then
|
||||
if (dmi_req_i.addr = addr_abstractauto_c) then
|
||||
if (dm_ctrl.busy = '0') then -- idle and no errors yet
|
||||
dm_reg.abstractauto_autoexecdata <= dmi_req_data_i(00);
|
||||
dm_reg.abstractauto_autoexecprogbuf(0) <= dmi_req_data_i(16);
|
||||
dm_reg.abstractauto_autoexecprogbuf(1) <= dmi_req_data_i(17);
|
||||
dm_reg.abstractauto_autoexecdata <= dmi_req_i.data(00);
|
||||
dm_reg.abstractauto_autoexecprogbuf(0) <= dmi_req_i.data(16);
|
||||
dm_reg.abstractauto_autoexecprogbuf(1) <= dmi_req_i.data(17);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- auto execution trigger --
|
||||
if ((dmi_req_address_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
||||
((dmi_req_address_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
||||
((dmi_req_address_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
||||
if ((dmi_req_i.addr = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
||||
((dmi_req_i.addr = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
||||
((dmi_req_i.addr = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
||||
dm_reg.autoexec_wr <= '1';
|
||||
end if;
|
||||
|
||||
-- acknowledge command error --
|
||||
if (dmi_req_address_i = addr_abstractcs_c) then
|
||||
if (dmi_req_data_i(10 downto 8) = "111") then
|
||||
if (dmi_req_i.addr = addr_abstractcs_c) then
|
||||
if (dmi_req_i.data(10 downto 8) = "111") then
|
||||
dm_reg.clr_acc_err <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- write program buffer --
|
||||
if (dmi_req_address_i(dmi_req_address_i'left downto 1) = addr_progbuf0_c(dmi_req_address_i'left downto 1)) then
|
||||
if (dmi_req_i.addr(dmi_req_i.addr'left downto 1) = addr_progbuf0_c(dmi_req_i.addr'left downto 1)) then
|
||||
if (dm_ctrl.busy = '0') then -- idle
|
||||
if (dmi_req_address_i(0) = addr_progbuf0_c(0)) then
|
||||
dm_reg.progbuf(0) <= dmi_req_data_i;
|
||||
if (dmi_req_i.addr(0) = addr_progbuf0_c(0)) then
|
||||
dm_reg.progbuf(0) <= dmi_req_i.data;
|
||||
else
|
||||
dm_reg.progbuf(1) <= dmi_req_data_i;
|
||||
dm_reg.progbuf(1) <= dmi_req_i.data;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- invalid access while command is executing --
|
||||
if (dm_ctrl.busy = '1') then -- busy
|
||||
if (dmi_req_address_i = addr_abstractcs_c) or
|
||||
(dmi_req_address_i = addr_command_c) or
|
||||
(dmi_req_address_i = addr_abstractauto_c) or
|
||||
(dmi_req_address_i = addr_data0_c) or
|
||||
(dmi_req_address_i = addr_progbuf0_c) or
|
||||
(dmi_req_address_i = addr_progbuf1_c) then
|
||||
if (dmi_req_i.addr = addr_abstractcs_c) or
|
||||
(dmi_req_i.addr = addr_command_c) or
|
||||
(dmi_req_i.addr = addr_abstractauto_c) or
|
||||
(dmi_req_i.addr = addr_data0_c) or
|
||||
(dmi_req_i.addr = addr_progbuf0_c) or
|
||||
(dmi_req_i.addr = addr_progbuf1_c) then
|
||||
dm_reg.wr_acc_err <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
@ -527,8 +511,7 @@ begin
|
|||
-- Direct Control -------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
-- write to abstract data register --
|
||||
dci.data_we <= '1' when (dmi_wren = '1') and (dmi_req_address_i = addr_data0_c) and (dm_ctrl.busy = '0') else '0';
|
||||
dci.wdata <= dmi_req_data_i;
|
||||
dci.data_we <= '1' when (dmi_wren = '1') and (dmi_req_i.addr = addr_data0_c) and (dm_ctrl.busy = '0') else '0';
|
||||
|
||||
-- CPU halt/resume request --
|
||||
cpu_halt_req_o <= dm_reg.halt_req and dm_reg.dmcontrol_dmactive; -- single-shot
|
||||
|
@ -543,112 +526,112 @@ begin
|
|||
cpu_progbuf(2) <= instr_nop_c when (dm_ctrl.pbuf_en = '0') else dm_reg.progbuf(1);
|
||||
cpu_progbuf(3) <= instr_ebreak_c; -- implicit ebreak instruction
|
||||
|
||||
-- DMI status --
|
||||
dmi_rsp_op_o <= "00"; -- operation success
|
||||
dmi_req_ready_o <= '1'; -- always ready for new read/write access
|
||||
|
||||
|
||||
-- Debug Module Interface - Read Access ---------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
dmi_read_access: process(clk_i)
|
||||
begin
|
||||
if rising_edge(clk_i) then
|
||||
dmi_rsp_valid_o <= dmi_req_valid_i; -- DMI transfer ack
|
||||
dmi_rsp_data_o <= (others => '0'); -- default
|
||||
dmi_rsp_o.ack <= dmi_wren or dmi_rden; -- always ACK any request
|
||||
dmi_rsp_o.data <= (others => '0'); -- default
|
||||
dm_reg.rd_acc_err <= '0';
|
||||
dm_reg.autoexec_rd <= '0';
|
||||
|
||||
case dmi_req_address_i is
|
||||
case dmi_req_i.addr is
|
||||
|
||||
-- debug module status register --
|
||||
when addr_dmstatus_c =>
|
||||
dmi_rsp_data_o(31 downto 23) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(22) <= '1'; -- impebreak (r/-): there is an implicit ebreak instruction after the visible program buffer
|
||||
dmi_rsp_data_o(21 downto 20) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(19) <= dm_ctrl.hart_reset; -- allhavereset (r/-): there is only one hart that can be reset
|
||||
dmi_rsp_data_o(18) <= dm_ctrl.hart_reset; -- anyhavereset (r/-): there is only one hart that can be reset
|
||||
dmi_rsp_data_o(17) <= dm_ctrl.hart_resume_ack; -- allresumeack (r/-): there is only one hart that can acknowledge resume request
|
||||
dmi_rsp_data_o(16) <= dm_ctrl.hart_resume_ack; -- anyresumeack (r/-): there is only one hart that can acknowledge resume request
|
||||
dmi_rsp_data_o(15) <= '0'; -- allnonexistent (r/-): there is only one hart that is always existent
|
||||
dmi_rsp_data_o(14) <= '0'; -- anynonexistent (r/-): there is only one hart that is always existent
|
||||
dmi_rsp_data_o(13) <= dm_reg.dmcontrol_ndmreset; -- allunavail (r/-): there is only one hart that is unavailable during reset
|
||||
dmi_rsp_data_o(12) <= dm_reg.dmcontrol_ndmreset; -- anyunavail (r/-): there is only one hart that is unavailable during reset
|
||||
dmi_rsp_data_o(11) <= not dm_ctrl.hart_halted; -- allrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_data_o(10) <= not dm_ctrl.hart_halted; -- anyrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_data_o(09) <= dm_ctrl.hart_halted; -- allhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_data_o(08) <= dm_ctrl.hart_halted; -- anyhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_data_o(07) <= '1'; -- authenticated (r/-): authentication passed since there is no authentication
|
||||
dmi_rsp_data_o(06) <= '0'; -- authbusy (r/-): always ready since there is no authentication
|
||||
dmi_rsp_data_o(05) <= '0'; -- hasresethaltreq (r/-): halt-on-reset not implemented
|
||||
dmi_rsp_data_o(04) <= '0'; -- confstrptrvalid (r/-): no configuration string available
|
||||
dmi_rsp_data_o(03 downto 00) <= "0011"; -- version (r/-): compatible to spec. version 1.0
|
||||
dmi_rsp_o.data(31 downto 23) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(22) <= '1'; -- impebreak (r/-): there is an implicit ebreak instruction after the visible program buffer
|
||||
dmi_rsp_o.data(21 downto 20) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(19) <= dm_ctrl.hart_reset; -- allhavereset (r/-): there is only one hart that can be reset
|
||||
dmi_rsp_o.data(18) <= dm_ctrl.hart_reset; -- anyhavereset (r/-): there is only one hart that can be reset
|
||||
dmi_rsp_o.data(17) <= dm_ctrl.hart_resume_ack; -- allresumeack (r/-): there is only one hart that can acknowledge resume request
|
||||
dmi_rsp_o.data(16) <= dm_ctrl.hart_resume_ack; -- anyresumeack (r/-): there is only one hart that can acknowledge resume request
|
||||
dmi_rsp_o.data(15) <= '0'; -- allnonexistent (r/-): there is only one hart that is always existent
|
||||
dmi_rsp_o.data(14) <= '0'; -- anynonexistent (r/-): there is only one hart that is always existent
|
||||
dmi_rsp_o.data(13) <= dm_reg.dmcontrol_ndmreset; -- allunavail (r/-): there is only one hart that is unavailable during reset
|
||||
dmi_rsp_o.data(12) <= dm_reg.dmcontrol_ndmreset; -- anyunavail (r/-): there is only one hart that is unavailable during reset
|
||||
dmi_rsp_o.data(11) <= not dm_ctrl.hart_halted; -- allrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_o.data(10) <= not dm_ctrl.hart_halted; -- anyrunning (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_o.data(09) <= dm_ctrl.hart_halted; -- allhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_o.data(08) <= dm_ctrl.hart_halted; -- anyhalted (r/-): there is only one hart that can be RUNNING or HALTED
|
||||
dmi_rsp_o.data(07) <= '1'; -- authenticated (r/-): authentication passed since there is no authentication
|
||||
dmi_rsp_o.data(06) <= '0'; -- authbusy (r/-): always ready since there is no authentication
|
||||
dmi_rsp_o.data(05) <= '0'; -- hasresethaltreq (r/-): halt-on-reset not implemented
|
||||
dmi_rsp_o.data(04) <= '0'; -- confstrptrvalid (r/-): no configuration string available
|
||||
dmi_rsp_o.data(03 downto 00) <= dm_version_c; -- version (r/-): DM spec. version
|
||||
|
||||
-- debug module control --
|
||||
when addr_dmcontrol_c =>
|
||||
dmi_rsp_data_o(31) <= '0'; -- haltreq (-/w): write-only
|
||||
dmi_rsp_data_o(30) <= '0'; -- resumereq (-/w1): write-only
|
||||
dmi_rsp_data_o(29) <= '0'; -- hartreset (r/w): not supported
|
||||
dmi_rsp_data_o(28) <= '0'; -- ackhavereset (-/w1): write-only
|
||||
dmi_rsp_data_o(27) <= '0'; -- reserved (r/-)
|
||||
dmi_rsp_data_o(26) <= '0'; -- hasel (r/-) - there is a single currently selected hart
|
||||
dmi_rsp_data_o(25 downto 16) <= (others => '0'); -- hartsello (r/-) - there is only one hart
|
||||
dmi_rsp_data_o(15 downto 06) <= (others => '0'); -- hartselhi (r/-) - there is only one hart
|
||||
dmi_rsp_data_o(05 downto 04) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(03) <= '0'; -- setresethaltreq (-/w1): halt-on-reset request - halt-on-reset not implemented
|
||||
dmi_rsp_data_o(02) <= '0'; -- clrresethaltreq (-/w1): halt-on-reset ack - halt-on-reset not implemented
|
||||
dmi_rsp_data_o(01) <= dm_reg.dmcontrol_ndmreset; -- ndmreset (r/w): soc reset
|
||||
dmi_rsp_data_o(00) <= dm_reg.dmcontrol_dmactive; -- dmactive (r/w): DM reset
|
||||
dmi_rsp_o.data(31) <= '0'; -- haltreq (-/w): write-only
|
||||
dmi_rsp_o.data(30) <= '0'; -- resumereq (-/w1): write-only
|
||||
dmi_rsp_o.data(29) <= '0'; -- hartreset (r/w): not supported
|
||||
dmi_rsp_o.data(28) <= '0'; -- ackhavereset (-/w1): write-only
|
||||
dmi_rsp_o.data(27) <= '0'; -- reserved (r/-)
|
||||
dmi_rsp_o.data(26) <= '0'; -- hasel (r/-) - only a single hart can be selected at once
|
||||
dmi_rsp_o.data(25 downto 16) <= (others => '0'); -- hartsello (r/-) - there is only one hart
|
||||
dmi_rsp_o.data(15 downto 06) <= (others => '0'); -- hartselhi (r/-) - there is only one hart
|
||||
dmi_rsp_o.data(05 downto 04) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(03) <= '0'; -- setresethaltreq (-/w1): halt-on-reset request - halt-on-reset not implemented
|
||||
dmi_rsp_o.data(02) <= '0'; -- clrresethaltreq (-/w1): halt-on-reset ack - halt-on-reset not implemented
|
||||
dmi_rsp_o.data(01) <= dm_reg.dmcontrol_ndmreset; -- ndmreset (r/w): soc reset
|
||||
dmi_rsp_o.data(00) <= dm_reg.dmcontrol_dmactive; -- dmactive (r/w): DM reset
|
||||
|
||||
-- hart info --
|
||||
when addr_hartinfo_c =>
|
||||
dmi_rsp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(23 downto 20) <= nscratch_c; -- nscratch (r/-): number of dscratch CSRs
|
||||
dmi_rsp_data_o(19 downto 17) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(16) <= dataaccess_c; -- dataaccess (r/-): 1: data registers are memory-mapped, 0: data reisters are CSR-mapped
|
||||
dmi_rsp_data_o(15 downto 12) <= datasize_c; -- datasize (r/-): number data registers in memory/CSR space
|
||||
dmi_rsp_data_o(11 downto 00) <= dataaddr_c(11 downto 0); -- dataaddr (r/-): data registers base address (memory/CSR)
|
||||
dmi_rsp_o.data(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(23 downto 20) <= nscratch_c; -- nscratch (r/-): number of dscratch CSRs
|
||||
dmi_rsp_o.data(19 downto 17) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(16) <= dataaccess_c; -- dataaccess (r/-): 1: data registers are memory-mapped, 0: data registers are CSR-mapped
|
||||
dmi_rsp_o.data(15 downto 12) <= datasize_c; -- datasize (r/-): number data registers in memory/CSR space
|
||||
dmi_rsp_o.data(11 downto 00) <= dataaddr_c(11 downto 0); -- dataaddr (r/-): data registers base address (memory/CSR)
|
||||
|
||||
-- abstract control and status --
|
||||
when addr_abstractcs_c =>
|
||||
dmi_rsp_data_o(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(28 downto 24) <= "00010"; -- progbufsize (r/-): number of words in program buffer = 2
|
||||
dmi_rsp_data_o(12) <= dm_ctrl.busy; -- busy (r/-): abstract command in progress (1) / idle (0)
|
||||
dmi_rsp_data_o(11) <= '1'; -- relaxedpriv (r/-): PMP rules are ignored when in debug-mode
|
||||
dmi_rsp_data_o(10 downto 08) <= dm_ctrl.cmderr; -- cmderr (r/w1c): any error during execution?
|
||||
dmi_rsp_data_o(07 downto 04) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_data_o(03 downto 00) <= "0001"; -- datacount (r/-): number of implemented data registers = 1
|
||||
dmi_rsp_o.data(31 downto 24) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(28 downto 24) <= "00010"; -- progbufsize (r/-): number of words in program buffer = 2
|
||||
dmi_rsp_o.data(12) <= dm_ctrl.busy; -- busy (r/-): abstract command in progress (1) / idle (0)
|
||||
dmi_rsp_o.data(11) <= '1'; -- relaxedpriv (r/-): PMP rules are ignored when in debug-mode
|
||||
dmi_rsp_o.data(10 downto 08) <= dm_ctrl.cmderr; -- cmderr (r/w1c): any error during execution?
|
||||
dmi_rsp_o.data(07 downto 04) <= (others => '0'); -- reserved (r/-)
|
||||
dmi_rsp_o.data(03 downto 00) <= "0001"; -- datacount (r/-): number of implemented data registers = 1
|
||||
|
||||
-- -- abstract command (-/w) --
|
||||
-- when addr_command_c =>
|
||||
-- dmi_rsp_data_o <= (others => '0'); -- register is write-only
|
||||
-- abstract command (-/w) --
|
||||
when addr_command_c =>
|
||||
dmi_rsp_o.data <= (others => '0'); -- register is write-only
|
||||
|
||||
-- abstract command autoexec (r/w) --
|
||||
when addr_abstractauto_c =>
|
||||
dmi_rsp_data_o(00) <= dm_reg.abstractauto_autoexecdata; -- autoexecdata(0): read/write access to data0 triggers execution of program buffer
|
||||
dmi_rsp_data_o(16) <= dm_reg.abstractauto_autoexecprogbuf(0); -- autoexecprogbuf(0): read/write access to progbuf0 triggers execution of program buffer
|
||||
dmi_rsp_data_o(17) <= dm_reg.abstractauto_autoexecprogbuf(1); -- autoexecprogbuf(1): read/write access to progbuf1 triggers execution of program buffer
|
||||
dmi_rsp_o.data(00) <= dm_reg.abstractauto_autoexecdata; -- autoexecdata(0): read/write access to data0 triggers execution of program buffer
|
||||
dmi_rsp_o.data(16) <= dm_reg.abstractauto_autoexecprogbuf(0); -- autoexecprogbuf(0): read/write access to progbuf0 triggers execution of program buffer
|
||||
dmi_rsp_o.data(17) <= dm_reg.abstractauto_autoexecprogbuf(1); -- autoexecprogbuf(1): read/write access to progbuf1 triggers execution of program buffer
|
||||
|
||||
-- -- next debug module (r/-) --
|
||||
-- when addr_nextdm_c =>
|
||||
-- dmi_rsp_data_o <= (others => '0'); -- this is the only DM
|
||||
-- next debug module (r/-) --
|
||||
when addr_nextdm_c =>
|
||||
dmi_rsp_o.data <= (others => '0'); -- this is the only DM
|
||||
|
||||
-- abstract data 0 (r/w) --
|
||||
when addr_data0_c =>
|
||||
dmi_rsp_data_o <= dci.rdata;
|
||||
dmi_rsp_o.data <= dci.data_reg;
|
||||
|
||||
-- -- program buffer (-/w) --
|
||||
-- when addr_progbuf0_c =>
|
||||
-- dmi_rsp_data_o <= dm_reg.progbuf(0); -- program buffer 0, register is write-only
|
||||
-- when addr_progbuf1_c =>
|
||||
-- dmi_rsp_data_o <= dm_reg.progbuf(1); -- program buffer 1, register is write-only
|
||||
-- program buffer (r/w) --
|
||||
when addr_progbuf0_c =>
|
||||
if (LEGACY_MODE = true) then dmi_rsp_o.data <= dm_reg.progbuf(0); else dmi_rsp_o.data <= (others => '0'); end if; -- program buffer 0
|
||||
when addr_progbuf1_c =>
|
||||
if (LEGACY_MODE = true) then dmi_rsp_o.data <= dm_reg.progbuf(1); else dmi_rsp_o.data <= (others => '0'); end if; -- program buffer 1
|
||||
|
||||
-- -- system bus access control and status (r/-) --
|
||||
-- when addr_sbcs_c =>
|
||||
-- dmi_rsp_data_o <= (others => '0'); -- bus access not implemented
|
||||
-- system bus access control and status (r/-) --
|
||||
when addr_sbcs_c =>
|
||||
dmi_rsp_o.data <= (others => '0'); -- system bus access not implemented
|
||||
|
||||
-- halt summary 0 (r/-) --
|
||||
when addr_haltsum0_c =>
|
||||
dmi_rsp_o.data(0) <= dm_ctrl.hart_halted; -- hart 0 is halted
|
||||
|
||||
-- not implemented (r/-) --
|
||||
when others =>
|
||||
dmi_rsp_data_o <= (others => '0');
|
||||
dmi_rsp_o.data <= (others => '0');
|
||||
|
||||
end case;
|
||||
|
||||
|
@ -656,9 +639,9 @@ begin
|
|||
-- ------------------------------------------------------------
|
||||
if (dmi_rden = '1') then -- valid DMI read request
|
||||
if (dm_ctrl.busy = '1') then -- busy
|
||||
if (dmi_req_address_i = addr_data0_c) or
|
||||
(dmi_req_address_i = addr_progbuf0_c) or
|
||||
(dmi_req_address_i = addr_progbuf1_c) then
|
||||
if (dmi_req_i.addr = addr_data0_c) or
|
||||
(dmi_req_i.addr = addr_progbuf0_c) or
|
||||
(dmi_req_i.addr = addr_progbuf1_c) then
|
||||
dm_reg.rd_acc_err <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
@ -667,9 +650,9 @@ begin
|
|||
-- auto execution trigger --
|
||||
-- ------------------------------------------------------------
|
||||
if (dmi_rden = '1') then -- valid DMI read request
|
||||
if ((dmi_req_address_i = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
||||
((dmi_req_address_i = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
||||
((dmi_req_address_i = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
||||
if ((dmi_req_i.addr = addr_data0_c) and (dm_reg.abstractauto_autoexecdata = '1')) or
|
||||
((dmi_req_i.addr = addr_progbuf0_c) and (dm_reg.abstractauto_autoexecprogbuf(0) = '1')) or
|
||||
((dmi_req_i.addr = addr_progbuf1_c) and (dm_reg.abstractauto_autoexecprogbuf(1) = '1')) then
|
||||
dm_reg.autoexec_rd <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
@ -693,7 +676,7 @@ begin
|
|||
write_access: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
data_buf <= (others => '0');
|
||||
dci.data_reg <= (others => '0');
|
||||
dci.halt_ack <= '0';
|
||||
dci.resume_ack <= '0';
|
||||
dci.execute_ack <= '0';
|
||||
|
@ -701,9 +684,9 @@ begin
|
|||
elsif rising_edge(clk_i) then
|
||||
-- data buffer --
|
||||
if (dci.data_we = '1') then -- DM write access
|
||||
data_buf <= dci.wdata;
|
||||
dci.data_reg <= dmi_req_i.data;
|
||||
elsif (bus_req_i.addr(7 downto 6) = dm_data_base_c(7 downto 6)) and (wren = '1') then -- CPU write access
|
||||
data_buf <= bus_req_i.data;
|
||||
dci.data_reg <= bus_req_i.data;
|
||||
end if;
|
||||
-- control and status register CPU write access --
|
||||
-- NOTE: we only check the individual BYTE ACCESSES - not the actual write data --
|
||||
|
@ -712,25 +695,14 @@ begin
|
|||
dci.execute_ack <= '0';
|
||||
dci.exception_ack <= '0';
|
||||
if (bus_req_i.addr(7 downto 6) = dm_sreg_base_c(7 downto 6)) and (wren = '1') then
|
||||
if (bus_req_i.ben(sreg_halt_ack_c/8) = '1') then
|
||||
dci.halt_ack <= '1';
|
||||
end if;
|
||||
if (bus_req_i.ben(sreg_resume_ack_c/8) = '1') then
|
||||
dci.resume_ack <= '1';
|
||||
end if;
|
||||
if (bus_req_i.ben(sreg_execute_ack_c/8) = '1') then
|
||||
dci.execute_ack <= '1';
|
||||
end if;
|
||||
if (bus_req_i.ben(sreg_exception_ack_c/8) = '1') then
|
||||
dci.exception_ack <= '1';
|
||||
end if;
|
||||
dci.halt_ack <= bus_req_i.ben(sreg_halt_ack_c/8);
|
||||
dci.resume_ack <= bus_req_i.ben(sreg_resume_ack_c/8);
|
||||
dci.execute_ack <= bus_req_i.ben(sreg_execute_ack_c/8);
|
||||
dci.exception_ack <= bus_req_i.ben(sreg_exception_ack_c/8);
|
||||
end if;
|
||||
end if;
|
||||
end process write_access;
|
||||
|
||||
-- DM data buffer read access --
|
||||
dci.rdata <= data_buf;
|
||||
|
||||
|
||||
-- Read Access ----------------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
|
@ -746,7 +718,7 @@ begin
|
|||
when "01" => -- dm_pbuf_base_c: program buffer
|
||||
bus_rsp_o.data <= cpu_progbuf(to_integer(unsigned(bus_req_i.addr(3 downto 2))));
|
||||
when "10" => -- dm_data_base_c: data buffer
|
||||
bus_rsp_o.data <= data_buf;
|
||||
bus_rsp_o.data <= dci.data_reg;
|
||||
when others => -- dm_sreg_base_c: control and status register
|
||||
bus_rsp_o.data(sreg_resume_req_c) <= dci.resume_req;
|
||||
bus_rsp_o.data(sreg_execute_req_c) <= dci.execute_req;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue