Merge pull request #174 from antonblanchard/yosys-fixes
[microwatt.git] / core_debug.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.common.all;
7
8 entity core_debug is
9 port (
10 clk : in std_logic;
11 rst : in std_logic;
12
13 dmi_addr : in std_ulogic_vector(3 downto 0);
14 dmi_din : in std_ulogic_vector(63 downto 0);
15 dmi_dout : out std_ulogic_vector(63 downto 0);
16 dmi_req : in std_ulogic;
17 dmi_wr : in std_ulogic;
18 dmi_ack : out std_ulogic;
19
20 -- Debug actions
21 core_stop : out std_ulogic;
22 core_rst : out std_ulogic;
23 icache_rst : out std_ulogic;
24
25 -- Core status inputs
26 terminate : in std_ulogic;
27 core_stopped : in std_ulogic;
28 nia : in std_ulogic_vector(63 downto 0);
29 msr : in std_ulogic_vector(63 downto 0);
30
31 -- GSPR register read port
32 dbg_gpr_req : out std_ulogic;
33 dbg_gpr_ack : in std_ulogic;
34 dbg_gpr_addr : out gspr_index_t;
35 dbg_gpr_data : in std_ulogic_vector(63 downto 0);
36
37 -- Misc
38 terminated_out : out std_ulogic
39 );
40 end core_debug;
41
42 architecture behave of core_debug is
43 -- DMI needs fixing... make a one clock pulse
44 signal dmi_req_1: std_ulogic;
45
46 -- CTRL register (direct actions, write 1 to act, read back 0)
47 -- bit 0 : Core stop
48 -- bit 1 : Core reset (doesn't clear stop)
49 -- bit 2 : Icache reset
50 -- bit 3 : Single step
51 -- bit 4 : Core start
52 constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000";
53 constant DBG_CORE_CTRL_STOP : integer := 0;
54 constant DBG_CORE_CTRL_RESET : integer := 1;
55 constant DBG_CORE_CTRL_ICRESET : integer := 2;
56 constant DBG_CORE_CTRL_STEP : integer := 3;
57 constant DBG_CORE_CTRL_START : integer := 4;
58
59 -- STAT register (read only)
60 -- bit 0 : Core stopping (wait til bit 1 set)
61 -- bit 1 : Core stopped
62 -- bit 2 : Core terminated (clears with start or reset)
63 constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001";
64 constant DBG_CORE_STAT_STOPPING : integer := 0;
65 constant DBG_CORE_STAT_STOPPED : integer := 1;
66 constant DBG_CORE_STAT_TERM : integer := 2;
67
68 -- NIA register (read only for now)
69 constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010";
70
71 -- MSR (read only)
72 constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
73
74 -- GSPR register index
75 constant DBG_CORE_GSPR_INDEX : std_ulogic_vector(3 downto 0) := "0100";
76
77 -- GSPR register data
78 constant DBG_CORE_GSPR_DATA : std_ulogic_vector(3 downto 0) := "0101";
79
80 -- Some internal wires
81 signal stat_reg : std_ulogic_vector(63 downto 0);
82
83 -- Some internal latches
84 signal stopping : std_ulogic;
85 signal do_step : std_ulogic;
86 signal do_reset : std_ulogic;
87 signal do_icreset : std_ulogic;
88 signal terminated : std_ulogic;
89 signal do_gspr_rd : std_ulogic;
90 signal gspr_index : gspr_index_t;
91
92 begin
93 -- Single cycle register accesses on DMI except for GSPR data
94 dmi_ack <= dmi_req when dmi_addr /= DBG_CORE_GSPR_DATA
95 else dbg_gpr_ack;
96 dbg_gpr_req <= dmi_req when dmi_addr = DBG_CORE_GSPR_DATA
97 else '0';
98
99 -- Status register read composition
100 stat_reg <= (2 => terminated,
101 1 => core_stopped,
102 0 => stopping,
103 others => '0');
104
105 -- DMI read data mux
106 with dmi_addr select dmi_dout <=
107 stat_reg when DBG_CORE_STAT,
108 nia when DBG_CORE_NIA,
109 msr when DBG_CORE_MSR,
110 dbg_gpr_data when DBG_CORE_GSPR_DATA,
111 (others => '0') when others;
112
113 -- DMI writes
114 reg_write: process(clk)
115 begin
116 if rising_edge(clk) then
117 -- Reset the 1-cycle "do" signals
118 do_step <= '0';
119 do_reset <= '0';
120 do_icreset <= '0';
121
122 if (rst) then
123 stopping <= '0';
124 terminated <= '0';
125 else
126 -- Edge detect on dmi_req for 1-shot pulses
127 dmi_req_1 <= dmi_req;
128 if dmi_req = '1' and dmi_req_1 = '0' then
129 if dmi_wr = '1' then
130 report("DMI write to " & to_hstring(dmi_addr));
131
132 -- Control register actions
133 if dmi_addr = DBG_CORE_CTRL then
134 if dmi_din(DBG_CORE_CTRL_RESET) = '1' then
135 do_reset <= '1';
136 terminated <= '0';
137 end if;
138 if dmi_din(DBG_CORE_CTRL_STOP) = '1' then
139 stopping <= '1';
140 end if;
141 if dmi_din(DBG_CORE_CTRL_STEP) = '1' then
142 do_step <= '1';
143 terminated <= '0';
144 end if;
145 if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then
146 do_icreset <= '1';
147 end if;
148 if dmi_din(DBG_CORE_CTRL_START) = '1' then
149 stopping <= '0';
150 terminated <= '0';
151 end if;
152 elsif dmi_addr = DBG_CORE_GSPR_INDEX then
153 gspr_index <= dmi_din(gspr_index_t'left downto 0);
154 end if;
155 else
156 report("DMI read from " & to_string(dmi_addr));
157 end if;
158 end if;
159
160 -- Set core stop on terminate. We'll be stopping some time *after*
161 -- the offending instruction, at least until we can do back flushes
162 -- that preserve NIA which we can't just yet.
163 if terminate = '1' then
164 stopping <= '1';
165 terminated <= '1';
166 end if;
167 end if;
168 end if;
169 end process;
170
171 dbg_gpr_addr <= gspr_index;
172
173 -- Core control signals generated by the debug module
174 core_stop <= stopping and not do_step;
175 core_rst <= do_reset;
176 icache_rst <= do_icreset;
177 terminated_out <= terminated;
178 end behave;
179