Add Tercel PHY reset synchronization
[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.utils.all;
7 use work.common.all;
8
9 entity core_debug is
10 generic (
11 -- Length of log buffer
12 LOG_LENGTH : natural := 512
13 );
14 port (
15 clk : in std_logic;
16 rst : in std_logic;
17
18 dmi_addr : in std_ulogic_vector(3 downto 0);
19 dmi_din : in std_ulogic_vector(63 downto 0);
20 dmi_dout : out std_ulogic_vector(63 downto 0);
21 dmi_req : in std_ulogic;
22 dmi_wr : in std_ulogic;
23 dmi_ack : out std_ulogic;
24
25 -- Debug actions
26 core_stop : out std_ulogic;
27 core_rst : out std_ulogic;
28 icache_rst : out std_ulogic;
29
30 -- Core status inputs
31 terminate : in std_ulogic;
32 core_stopped : in std_ulogic;
33 nia : in std_ulogic_vector(63 downto 0);
34 msr : in std_ulogic_vector(63 downto 0);
35
36 -- GSPR register read port
37 dbg_gpr_req : out std_ulogic;
38 dbg_gpr_ack : in std_ulogic;
39 dbg_gpr_addr : out gspr_index_t;
40 dbg_gpr_data : in std_ulogic_vector(63 downto 0);
41
42 -- Core logging data
43 log_data : in std_ulogic_vector(255 downto 0);
44 log_read_addr : in std_ulogic_vector(31 downto 0);
45 log_read_data : out std_ulogic_vector(63 downto 0);
46 log_write_addr : out std_ulogic_vector(31 downto 0);
47
48 -- Misc
49 terminated_out : out std_ulogic
50 );
51 end core_debug;
52
53 architecture behave of core_debug is
54 -- DMI needs fixing... make a one clock pulse
55 signal dmi_req_1: std_ulogic;
56
57 -- CTRL register (direct actions, write 1 to act, read back 0)
58 -- bit 0 : Core stop
59 -- bit 1 : Core reset (doesn't clear stop)
60 -- bit 2 : Icache reset
61 -- bit 3 : Single step
62 -- bit 4 : Core start
63 constant DBG_CORE_CTRL : std_ulogic_vector(3 downto 0) := "0000";
64 constant DBG_CORE_CTRL_STOP : integer := 0;
65 constant DBG_CORE_CTRL_RESET : integer := 1;
66 constant DBG_CORE_CTRL_ICRESET : integer := 2;
67 constant DBG_CORE_CTRL_STEP : integer := 3;
68 constant DBG_CORE_CTRL_START : integer := 4;
69
70 -- STAT register (read only)
71 -- bit 0 : Core stopping (wait til bit 1 set)
72 -- bit 1 : Core stopped
73 -- bit 2 : Core terminated (clears with start or reset)
74 constant DBG_CORE_STAT : std_ulogic_vector(3 downto 0) := "0001";
75 constant DBG_CORE_STAT_STOPPING : integer := 0;
76 constant DBG_CORE_STAT_STOPPED : integer := 1;
77 constant DBG_CORE_STAT_TERM : integer := 2;
78
79 -- NIA register (read only for now)
80 constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010";
81
82 -- MSR (read only)
83 constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
84
85 -- GSPR register index
86 constant DBG_CORE_GSPR_INDEX : std_ulogic_vector(3 downto 0) := "0100";
87
88 -- GSPR register data
89 constant DBG_CORE_GSPR_DATA : std_ulogic_vector(3 downto 0) := "0101";
90
91 -- Log buffer address and data registers
92 constant DBG_CORE_LOG_ADDR : std_ulogic_vector(3 downto 0) := "0110";
93 constant DBG_CORE_LOG_DATA : std_ulogic_vector(3 downto 0) := "0111";
94 constant DBG_CORE_LOG_TRIGGER : std_ulogic_vector(3 downto 0) := "1000";
95
96 constant LOG_INDEX_BITS : natural := log2(LOG_LENGTH);
97
98 -- Some internal wires
99 signal stat_reg : std_ulogic_vector(63 downto 0);
100
101 -- Some internal latches
102 signal stopping : std_ulogic;
103 signal do_step : std_ulogic;
104 signal do_reset : std_ulogic;
105 signal do_icreset : std_ulogic;
106 signal terminated : std_ulogic;
107 signal do_gspr_rd : std_ulogic;
108 signal gspr_index : gspr_index_t;
109
110 signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
111 signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0');
112 signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0');
113 signal do_log_trigger : std_ulogic := '0';
114 signal do_dmi_log_rd : std_ulogic;
115 signal dmi_read_log_data : std_ulogic;
116 signal dmi_read_log_data_1 : std_ulogic;
117 signal log_trigger_delay : integer range 0 to 255 := 0;
118
119 begin
120 -- Single cycle register accesses on DMI except for GSPR data
121 dmi_ack <= dmi_req when dmi_addr /= DBG_CORE_GSPR_DATA
122 else dbg_gpr_ack;
123 dbg_gpr_req <= dmi_req when dmi_addr = DBG_CORE_GSPR_DATA
124 else '0';
125
126 -- Status register read composition
127 stat_reg <= (2 => terminated,
128 1 => core_stopped,
129 0 => stopping,
130 others => '0');
131
132 -- DMI read data mux
133 with dmi_addr select dmi_dout <=
134 stat_reg when DBG_CORE_STAT,
135 nia when DBG_CORE_NIA,
136 msr when DBG_CORE_MSR,
137 dbg_gpr_data when DBG_CORE_GSPR_DATA,
138 log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
139 log_dmi_data when DBG_CORE_LOG_DATA,
140 log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
141 (others => '0') when others;
142
143 -- DMI writes
144 reg_write: process(clk)
145 begin
146 if rising_edge(clk) then
147 -- Reset the 1-cycle "do" signals
148 do_step <= '0';
149 do_reset <= '0';
150 do_icreset <= '0';
151 do_dmi_log_rd <= '0';
152
153 if (rst) then
154 stopping <= '0';
155 terminated <= '0';
156 log_trigger_delay <= 0;
157 else
158 if do_log_trigger = '1' or log_trigger_delay /= 0 then
159 if log_trigger_delay = 255 then
160 log_dmi_trigger(1) <= '1';
161 log_trigger_delay <= 0;
162 else
163 log_trigger_delay <= log_trigger_delay + 1;
164 end if;
165 end if;
166 -- Edge detect on dmi_req for 1-shot pulses
167 dmi_req_1 <= dmi_req;
168 if dmi_req = '1' and dmi_req_1 = '0' then
169 if dmi_wr = '1' then
170 report("DMI write to " & to_hstring(dmi_addr));
171
172 -- Control register actions
173 if dmi_addr = DBG_CORE_CTRL then
174 if dmi_din(DBG_CORE_CTRL_RESET) = '1' then
175 do_reset <= '1';
176 terminated <= '0';
177 end if;
178 if dmi_din(DBG_CORE_CTRL_STOP) = '1' then
179 stopping <= '1';
180 end if;
181 if dmi_din(DBG_CORE_CTRL_STEP) = '1' then
182 do_step <= '1';
183 terminated <= '0';
184 end if;
185 if dmi_din(DBG_CORE_CTRL_ICRESET) = '1' then
186 do_icreset <= '1';
187 end if;
188 if dmi_din(DBG_CORE_CTRL_START) = '1' then
189 stopping <= '0';
190 terminated <= '0';
191 end if;
192 elsif dmi_addr = DBG_CORE_GSPR_INDEX then
193 gspr_index <= dmi_din(gspr_index_t'left downto 0);
194 elsif dmi_addr = DBG_CORE_LOG_ADDR then
195 log_dmi_addr <= dmi_din(31 downto 0);
196 do_dmi_log_rd <= '1';
197 elsif dmi_addr = DBG_CORE_LOG_TRIGGER then
198 log_dmi_trigger <= dmi_din;
199 end if;
200 else
201 report("DMI read from " & to_string(dmi_addr));
202 end if;
203
204 elsif dmi_read_log_data = '0' and dmi_read_log_data_1 = '1' then
205 -- Increment log_dmi_addr after the end of a read from DBG_CORE_LOG_DATA
206 log_dmi_addr(LOG_INDEX_BITS + 1 downto 0) <=
207 std_ulogic_vector(unsigned(log_dmi_addr(LOG_INDEX_BITS+1 downto 0)) + 1);
208 do_dmi_log_rd <= '1';
209 end if;
210 dmi_read_log_data_1 <= dmi_read_log_data;
211 if dmi_req = '1' and dmi_addr = DBG_CORE_LOG_DATA then
212 dmi_read_log_data <= '1';
213 else
214 dmi_read_log_data <= '0';
215 end if;
216
217 -- Set core stop on terminate. We'll be stopping some time *after*
218 -- the offending instruction, at least until we can do back flushes
219 -- that preserve NIA which we can't just yet.
220 if terminate = '1' then
221 stopping <= '1';
222 terminated <= '1';
223 end if;
224 end if;
225 end if;
226 end process;
227
228 dbg_gpr_addr <= gspr_index;
229
230 -- Core control signals generated by the debug module
231 core_stop <= stopping and not do_step;
232 core_rst <= do_reset;
233 icache_rst <= do_icreset;
234 terminated_out <= terminated;
235
236 -- Logging RAM
237 maybe_log: if LOG_LENGTH > 0 generate
238 subtype log_ptr_t is unsigned(LOG_INDEX_BITS - 1 downto 0);
239 type log_array_t is array(0 to LOG_LENGTH - 1) of std_ulogic_vector(255 downto 0);
240 signal log_array : log_array_t;
241 signal log_rd_ptr : log_ptr_t;
242 signal log_wr_ptr : log_ptr_t;
243 signal log_toggle : std_ulogic;
244 signal log_wr_enable : std_ulogic;
245 signal log_rd_ptr_latched : log_ptr_t;
246 signal log_rd : std_ulogic_vector(255 downto 0);
247 signal log_dmi_reading : std_ulogic;
248 signal log_dmi_read_done : std_ulogic;
249
250 function select_dword(data : std_ulogic_vector(255 downto 0);
251 addr : std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
252 variable firstbit : integer;
253 begin
254 firstbit := to_integer(unsigned(addr(1 downto 0))) * 64;
255 return data(firstbit + 63 downto firstbit);
256 end;
257
258 attribute ram_style : string;
259 attribute ram_style of log_array : signal is "block";
260 attribute ram_decomp : string;
261 attribute ram_decomp of log_array : signal is "power";
262
263 begin
264 -- Use MSB of read addresses to stop the logging
265 log_wr_enable <= not (log_read_addr(31) or log_dmi_addr(31) or log_dmi_trigger(1));
266
267 log_ram: process(clk)
268 begin
269 if rising_edge(clk) then
270 if log_wr_enable = '1' then
271 log_array(to_integer(log_wr_ptr)) <= log_data;
272 end if;
273 log_rd <= log_array(to_integer(log_rd_ptr_latched));
274 end if;
275 end process;
276
277
278 log_buffer: process(clk)
279 variable b : integer;
280 variable data : std_ulogic_vector(255 downto 0);
281 begin
282 if rising_edge(clk) then
283 if rst = '1' then
284 log_wr_ptr <= (others => '0');
285 log_toggle <= '0';
286 elsif log_wr_enable = '1' then
287 if log_wr_ptr = to_unsigned(LOG_LENGTH - 1, LOG_INDEX_BITS) then
288 log_toggle <= not log_toggle;
289 end if;
290 log_wr_ptr <= log_wr_ptr + 1;
291 end if;
292 if do_dmi_log_rd = '1' then
293 log_rd_ptr_latched <= unsigned(log_dmi_addr(LOG_INDEX_BITS + 1 downto 2));
294 else
295 log_rd_ptr_latched <= unsigned(log_read_addr(LOG_INDEX_BITS + 1 downto 2));
296 end if;
297 if log_dmi_read_done = '1' then
298 log_dmi_data <= select_dword(log_rd, log_dmi_addr);
299 else
300 log_read_data <= select_dword(log_rd, log_read_addr);
301 end if;
302 log_dmi_read_done <= log_dmi_reading;
303 log_dmi_reading <= do_dmi_log_rd;
304 do_log_trigger <= '0';
305 if log_data(42) = log_dmi_trigger(63) and
306 log_data(41 downto 0) = log_dmi_trigger(43 downto 2) and
307 log_dmi_trigger(0) = '1' then
308 do_log_trigger <= '1';
309 end if;
310 end if;
311 end process;
312 log_write_addr(LOG_INDEX_BITS - 1 downto 0) <= std_ulogic_vector(log_wr_ptr);
313 log_write_addr(LOG_INDEX_BITS) <= '1';
314 log_write_addr(31 downto LOG_INDEX_BITS + 1) <= (others => '0');
315 end generate;
316
317 no_log: if LOG_LENGTH = 0 generate
318 begin
319 log_read_data <= (others => '0');
320 log_write_addr <= x"00000001";
321 end generate;
322
323 end behave;
324