OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [core/] [dbg_port.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
5
--! @brief     Debug port must be connected to DSU.
6
------------------------------------------------------------------------------
7
 
8
library ieee;
9
use ieee.std_logic_1164.all;
10
library commonlib;
11
use commonlib.types_common.all;
12
--! RIVER CPU specific library.
13
library riverlib;
14
--! RIVER CPU configuration constants.
15
use riverlib.river_cfg.all;
16
 
17
 
18
entity DbgPort is
19
  port (
20
    i_clk : in std_logic;                                     -- CPU clock
21
    i_nrst : in std_logic;                                    -- Reset. Active LOW.
22
    -- "RIVER" Debug interface
23
    i_dport_valid : in std_logic;                             -- Debug access from DSU is valid
24
    i_dport_write : in std_logic;                             -- Write command flag
25
    i_dport_region : in std_logic_vector(1 downto 0);         -- Registers region ID: 0=CSR; 1=IREGS; 2=Control
26
    i_dport_addr : in std_logic_vector(11 downto 0);          -- Register idx
27
    i_dport_wdata : in std_logic_vector(RISCV_ARCH-1 downto 0);-- Write value
28
    o_dport_ready : out std_logic;                            -- Response is ready
29
    o_dport_rdata : out std_logic_vector(RISCV_ARCH-1 downto 0);-- Response value
30
    -- CPU debugging signals:
31
    o_core_addr : out std_logic_vector(11 downto 0);          -- Address of the sub-region register
32
    o_core_wdata : out std_logic_vector(RISCV_ARCH-1 downto 0);-- Write data
33
    o_csr_ena : out std_logic;                                -- Region 0: Access to CSR bank is enabled.
34
    o_csr_write : out std_logic;                              -- Region 0: CSR write enable
35
    i_csr_rdata : in std_logic_vector(RISCV_ARCH-1 downto 0); -- Region 0: CSR read value
36
    o_ireg_ena : out std_logic;                               -- Region 1: Access to integer register bank is enabled
37
    o_ireg_write : out std_logic;                             -- Region 1: Integer registers bank write pulse
38
    o_npc_write : out std_logic;                              -- Region 1: npc write enable
39
    i_ireg_rdata : in std_logic_vector(RISCV_ARCH-1 downto 0);-- Region 1: Integer register read value
40
    i_pc : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);    -- Region 1: Instruction pointer
41
    i_npc : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);   -- Region 1: Next Instruction pointer
42
    i_e_valid : in std_logic;                                 -- Stepping control signal
43
    i_e_call : in std_logic;                                  -- pseudo-instruction CALL
44
    i_e_ret : in std_logic;                                   -- pseudo-instruction RET
45
    i_m_valid : in std_logic;                                 -- To compute number of valid executed instruction
46
    o_clock_cnt : out std_logic_vector(63 downto 0);          -- Number of clocks excluding halt state
47
    o_executed_cnt : out std_logic_vector(63 downto 0);       -- Number of executed instructions
48
    o_halt : out std_logic;                                   -- Halt signal is equal to hold pipeline
49
    i_ebreak : in std_logic;                                  -- ebreak instruction decoded
50
    o_break_mode : out std_logic;                             -- Behaviour on EBREAK instruction: 0 = halt; 1 = generate trap
51
    o_br_fetch_valid : out std_logic;                         -- Fetch injection address/instr are valid
52
    o_br_address_fetch : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Fetch injection address to skip ebreak instruciton only once
53
    o_br_instr_fetch : out std_logic_vector(31 downto 0);     -- Real instruction value that was replaced by ebreak
54
    -- Debug signals:
55
    i_istate : in std_logic_vector(1 downto 0);               -- ICache state machine value
56
    i_dstate : in std_logic_vector(1 downto 0);               -- DCache state machine value
57
    i_cstate : in std_logic_vector(1 downto 0);               -- CacheTop state machine value
58
    i_instr_buf : in std_logic_vector(DBG_FETCH_TRACE_SIZE*64-1 downto 0) -- trace last fetched instructions
59
  );
60
end;
61
 
62
architecture arch_DbgPort of DbgPort is
63
 
64
  constant zero64 : std_logic_vector(63 downto 0) := (others => '0');
65
  constant one64 : std_logic_vector(63 downto 0) := X"0000000000000001";
66
  constant STACKTR_ADRSZ : integer := log2(CFG_STACK_TRACE_BUF_SIZE);
67
 
68
  type RegistersType is record
69
      ready : std_logic;
70
      halt : std_logic;
71
      breakpoint : std_logic;
72
      stepping_mode : std_logic;
73
      stepping_mode_cnt : std_logic_vector(RISCV_ARCH-1 downto 0);
74
      trap_on_break : std_logic;
75
      br_address_fetch : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
76
      br_instr_fetch : std_logic_vector(31 downto 0);
77
      br_fetch_valid : std_logic;
78
 
79
      rdata : std_logic_vector(RISCV_ARCH-1 downto 0);
80
      stepping_mode_steps : std_logic_vector(RISCV_ARCH-1 downto 0); -- Number of steps before halt in stepping mode
81
      clock_cnt : std_logic_vector(63 downto 0);               -- Timer in clocks.
82
      executed_cnt : std_logic_vector(63 downto 0);            -- Number of valid executed instructions
83
      stack_trace_cnt : integer range 0 to CFG_STACK_TRACE_BUF_SIZE-1; -- Stack trace buffer counter
84
      rd_trbuf_ena : std_logic;
85
      rd_trbuf_addr0 : std_logic;
86
  end record;
87
 
88
  signal r, rin : RegistersType;
89
  signal wb_stack_raddr : std_logic_vector(STACKTR_ADRSZ-1 downto 0);
90
  signal wb_stack_rdata : std_logic_vector(2*BUS_ADDR_WIDTH-1 downto 0);
91
  signal w_stack_we : std_logic;
92
  signal wb_stack_waddr : std_logic_vector(STACKTR_ADRSZ-1 downto 0);
93
  signal wb_stack_wdata : std_logic_vector(2*BUS_ADDR_WIDTH-1 downto 0);
94
 
95
  component StackTraceBuffer is
96
  generic (
97
    abits : integer := 5;
98
    dbits : integer := 64
99
  );
100
  port (
101
    i_clk   : in std_logic;
102
    i_raddr : in std_logic_vector(abits-1 downto 0);
103
    o_rdata : out std_logic_vector(dbits-1 downto 0);
104
    i_we    : in std_logic;
105
    i_waddr : in std_logic_vector(abits-1 downto 0);
106
    i_wdata : in std_logic_vector(dbits-1 downto 0)
107
  );
108
  end component;
109
 
110
begin
111
 
112
 
113
  stacktr_ena : if CFG_STACK_TRACE_BUF_SIZE /= 0 generate
114
    stacktr0 : StackTraceBuffer generic map (
115
      abits => STACKTR_ADRSZ,
116
      dbits => 2*BUS_ADDR_WIDTH
117
    ) port map (
118
      i_clk   => i_clk,
119
      i_raddr => wb_stack_raddr,
120
      o_rdata => wb_stack_rdata,
121
      i_we    => w_stack_we,
122
      i_waddr => wb_stack_waddr,
123
      i_wdata => wb_stack_wdata
124
    );
125
  end generate;
126
 
127
  comb : process(i_nrst, i_dport_valid, i_dport_write, i_dport_region,
128
                 i_dport_addr, i_dport_wdata, i_ireg_rdata, i_csr_rdata,
129
                 i_pc, i_npc, i_e_valid, i_m_valid, i_ebreak, r,
130
                 wb_stack_rdata, i_e_call, i_e_ret, i_istate, i_dstate,
131
                 i_cstate, i_instr_buf)
132
    variable v : RegistersType;
133
    variable wb_o_core_addr : std_logic_vector(11 downto 0);
134
    variable wb_o_core_wdata : std_logic_vector(RISCV_ARCH-1 downto 0);
135
    variable wb_rdata : std_logic_vector(63 downto 0);
136
    variable wb_o_rdata : std_logic_vector(63 downto 0);
137
    variable wb_idx : integer range 0 to 4095;
138
    variable w_o_csr_ena : std_logic;
139
    variable w_o_csr_write : std_logic;
140
    variable w_o_ireg_ena : std_logic;
141
    variable w_o_ireg_write : std_logic;
142
    variable w_o_npc_write : std_logic;
143
    variable w_cur_halt : std_logic;
144
  begin
145
 
146
    v := r;
147
 
148
    wb_o_core_addr := (others => '0');
149
    wb_o_core_wdata := (others => '0');
150
    wb_rdata := (others => '0');
151
    wb_o_rdata := (others => '0');
152
    wb_idx := conv_integer(i_dport_addr);
153
    w_o_csr_ena := '0';
154
    w_o_csr_write := '0';
155
    w_o_ireg_ena := '0';
156
    w_o_ireg_write := '0';
157
    w_o_npc_write := '0';
158
    v.br_fetch_valid := '0';
159
    v.rd_trbuf_ena := '0';
160
    wb_stack_raddr <= (others => '0');
161
    w_stack_we <= '0';
162
    wb_stack_waddr <= (others => '0');
163
    wb_stack_wdata <= (others => '0');
164
 
165
    v.ready := i_dport_valid;
166
 
167
    w_cur_halt := '0';
168
    if i_e_valid = '1' then
169
        if r.stepping_mode_cnt /= zero64(RISCV_ARCH-1 downto 0) then
170
            v.stepping_mode_cnt := r.stepping_mode_cnt - 1;
171
            if r.stepping_mode_cnt = one64 then
172
                v.halt := '1';
173
                w_cur_halt := '1';
174
                v.stepping_mode := '0';
175
            end if;
176
        end if;
177
    end if;
178
 
179
    if r.halt = '0' then
180
        v.clock_cnt := r.clock_cnt + 1;
181
    end if;
182
    if i_m_valid = '1' then
183
        v.executed_cnt := r.executed_cnt + 1;
184
    end if;
185
    if i_ebreak = '1' then
186
        v.breakpoint := '1';
187
        if r.trap_on_break = '0' then
188
            v.halt := '1';
189
        end if;
190
    end if;
191
 
192
    if CFG_STACK_TRACE_BUF_SIZE /= 0 then
193
        if i_e_call = '1' and r.stack_trace_cnt /= (CFG_STACK_TRACE_BUF_SIZE - 1) then
194
            w_stack_we <= '1';
195
            wb_stack_waddr <= conv_std_logic_vector(r.stack_trace_cnt, STACKTR_ADRSZ);
196
            wb_stack_wdata <= i_npc & i_pc;
197
            v.stack_trace_cnt := r.stack_trace_cnt + 1;
198
        elsif i_e_ret = '1' and r.stack_trace_cnt /= 0 then
199
            v.stack_trace_cnt := r.stack_trace_cnt - 1;
200
        end if;
201
    end if;
202
 
203
    if i_dport_valid = '1' then
204
        case i_dport_region is
205
        when "00" =>
206
            w_o_csr_ena := '1';
207
            wb_o_core_addr := i_dport_addr;
208
            wb_rdata := i_csr_rdata;
209
            if i_dport_write = '1' then
210
                w_o_csr_write := '1';
211
                wb_o_core_wdata := i_dport_wdata;
212
            end if;
213
        when "01" =>
214
            if wb_idx < 32 then
215
                w_o_ireg_ena := '1';
216
                wb_o_core_addr := i_dport_addr;
217
                wb_rdata := i_ireg_rdata;
218
                if i_dport_write = '1' then
219
                    w_o_ireg_write := '1';
220
                    wb_o_core_wdata := i_dport_wdata;
221
                end if;
222
            elsif wb_idx = 32 then
223
                --! Read only register
224
                wb_rdata(BUS_ADDR_WIDTH-1 downto 0) := i_pc;
225
            elsif wb_idx = 33 then
226
                wb_rdata(BUS_ADDR_WIDTH-1 downto 0) := i_npc;
227
                if i_dport_write = '1' then
228
                    w_o_npc_write := '1';
229
                    wb_o_core_wdata := i_dport_wdata;
230
                end if;
231
            elsif wb_idx = 34 then
232
                wb_rdata(STACKTR_ADRSZ-1 downto 0) :=
233
                                                        conv_std_logic_vector(r.stack_trace_cnt, STACKTR_ADRSZ);
234
                if i_dport_write = '1' then
235
                    v.stack_trace_cnt := conv_integer(i_dport_wdata);
236
                end if;
237
            elsif (wb_idx >= 128) and (wb_idx < (128 + 2 * CFG_STACK_TRACE_BUF_SIZE)) then
238
                    v.rd_trbuf_ena := '1';
239
                    v.rd_trbuf_addr0 := conv_std_logic_vector(wb_idx, 1)(0);
240
                    wb_stack_raddr <= conv_std_logic_vector((wb_idx - 128) / 2, STACKTR_ADRSZ);
241
            elsif wb_idx = 256 then
242
                wb_rdata := i_instr_buf(63 downto 0);
243
            elsif wb_idx = 257 then
244
                wb_rdata := i_instr_buf(127 downto 64);
245
            elsif wb_idx = 258 then
246
                wb_rdata := i_instr_buf(191 downto 128);
247
            elsif wb_idx = 259 then
248
                wb_rdata := i_instr_buf(255 downto 192);
249
            end if;
250
        when "10" =>
251
            case wb_idx is
252
            when 0 =>
253
                wb_rdata(0) := r.halt;
254
                wb_rdata(2) := r.breakpoint;
255
                wb_rdata(33 downto 32) := i_istate;
256
                wb_rdata(37 downto 36) := i_dstate;
257
                wb_rdata(41 downto 40) := i_cstate;
258
                if i_dport_write = '1' then
259
                    v.halt := i_dport_wdata(0);
260
                    v.stepping_mode := i_dport_wdata(1);
261
                    if i_dport_wdata(1) = '1' then
262
                        v.stepping_mode_cnt := r.stepping_mode_steps;
263
                    end if;
264
                end if;
265
            when 1 =>
266
                wb_rdata := r.stepping_mode_steps;
267
                if i_dport_write = '1' then
268
                    v.stepping_mode_steps := i_dport_wdata;
269
                end if;
270
            when 2 =>
271
                wb_rdata := r.clock_cnt;
272
            when 3 =>
273
                wb_rdata := r.executed_cnt;
274
            when 4 =>
275
                --! Trap on instruction:
276
                --!      0 = Halt pipeline on ECALL instruction
277
                --!      1 = Generate trap on ECALL instruction
278
                wb_rdata(0) := r.trap_on_break;
279
                if i_dport_write = '1' then
280
                    v.trap_on_break := i_dport_wdata(0);
281
                end if;
282
            when 5 =>
283
                -- todo: add hardware breakpoint
284
            when 6 =>
285
                -- todo: remove hardware breakpoint
286
            when 7 =>
287
                wb_rdata(BUS_ADDR_WIDTH-1 downto 0) := r.br_address_fetch;
288
                if i_dport_write = '1' then
289
                    v.br_address_fetch := i_dport_wdata(BUS_ADDR_WIDTH-1 downto 0);
290
                end if;
291
            when 8 =>
292
                wb_rdata(31 downto 0) := r.br_instr_fetch;
293
                if i_dport_write = '1' then
294
                    v.br_fetch_valid := '1';
295
                    v.breakpoint := '0';
296
                    v.br_instr_fetch := i_dport_wdata(31 downto 0);
297
                end if;
298
            when others =>
299
            end case;
300
        when others =>
301
        end case;
302
    end if;
303
    v.rdata := wb_rdata;
304
    if r.rd_trbuf_ena = '1' then
305
        if r.rd_trbuf_addr0 = '0' then
306
            wb_o_rdata(BUS_ADDR_WIDTH-1 downto 0) :=
307
                                        wb_stack_rdata(BUS_ADDR_WIDTH-1 downto 0);
308
        else
309
            wb_o_rdata(BUS_ADDR_WIDTH-1 downto 0) :=
310
                                        wb_stack_rdata(2*BUS_ADDR_WIDTH-1 downto BUS_ADDR_WIDTH);
311
        end if;
312
    else
313
        wb_o_rdata := r.rdata;
314
    end if;
315
 
316
 
317
    if i_nrst = '0' then
318
        v.ready := '0';
319
        v.halt := '0';
320
        v.breakpoint := '0';
321
        v.stepping_mode := '0';
322
        v.rdata := (others => '0');
323
        v.stepping_mode_cnt := (others => '0');
324
        v.stepping_mode_steps := (others => '0');
325
        v.clock_cnt := (others => '0');
326
        v.executed_cnt := (others => '0');
327
        v.trap_on_break := '0';
328
        v.br_address_fetch := (others => '0');
329
        v.br_instr_fetch := (others => '0');
330
        v.br_fetch_valid := '0';
331
        v.stack_trace_cnt := 0;
332
        v.rd_trbuf_ena := '0';
333
        v.rd_trbuf_addr0 := '0';
334
    end if;
335
 
336
    rin <= v;
337
 
338
    o_core_addr <= wb_o_core_addr;
339
    o_core_wdata <= wb_o_core_wdata;
340
    o_csr_ena <= w_o_csr_ena;
341
    o_csr_write <= w_o_csr_write;
342
    o_ireg_ena <= w_o_ireg_ena;
343
    o_ireg_write <= w_o_ireg_write;
344
    o_npc_write <= w_o_npc_write;
345
    o_clock_cnt <= r.clock_cnt;
346
    o_executed_cnt <= r.executed_cnt;
347
    o_halt <= r.halt or w_cur_halt;
348
    o_break_mode <= r.trap_on_break;
349
    o_br_fetch_valid <= r.br_fetch_valid;
350
    o_br_address_fetch <= r.br_address_fetch;
351
    o_br_instr_fetch <= r.br_instr_fetch;
352
 
353
    o_dport_ready <= r.ready;
354
    o_dport_rdata <= wb_o_rdata;
355
  end process;
356
 
357
 
358
  -- registers:
359
  regs : process(i_clk)
360
  begin
361
     if rising_edge(i_clk) then
362
        r <= rin;
363
     end if;
364
  end process;
365
 
366
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.