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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_sysc_plugin/] [riverlib/] [core/] [dbg_port.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Debug port.
6
 * @details    Must be connected to DSU.
7
 */
8
 
9
#include "dbg_port.h"
10
 
11
namespace debugger {
12
 
13
DbgPort::DbgPort(sc_module_name name_) : sc_module(name_) {
14
    SC_METHOD(comb);
15
    sensitive << i_nrst;
16
    sensitive << i_dport_valid;
17
    sensitive << i_dport_write;
18
    sensitive << i_dport_region;
19
    sensitive << i_dport_addr;
20
    sensitive << i_dport_wdata;
21
    sensitive << i_ireg_rdata;
22
    sensitive << i_csr_rdata;
23
    sensitive << i_pc;
24
    sensitive << i_npc;
25
    sensitive << i_e_call;
26
    sensitive << i_e_ret;
27
    sensitive << i_e_valid;
28
    sensitive << i_m_valid;
29
    sensitive << i_ebreak;
30
    sensitive << i_istate;
31
    sensitive << i_dstate;
32
    sensitive << i_cstate;
33
    sensitive << i_instr_buf;
34
    sensitive << r.ready;
35
    sensitive << r.rdata;
36
    sensitive << r.halt;
37
    sensitive << r.breakpoint;
38
    sensitive << r.stepping_mode;
39
    sensitive << r.clock_cnt;
40
    sensitive << r.executed_cnt;
41
    sensitive << r.stepping_mode_cnt;
42
    sensitive << r.trap_on_break;
43
    sensitive << wb_stack_rdata;
44
 
45
    SC_METHOD(registers);
46
    sensitive << i_clk.pos();
47
 
48
    if (CFG_STACK_TRACE_BUF_SIZE != 0) {
49
        trbuf0 = new StackTraceBuffer("trbuf0");
50
        trbuf0->i_clk(i_clk);
51
        trbuf0->i_raddr(wb_stack_raddr);
52
        trbuf0->o_rdata(wb_stack_rdata);
53
        trbuf0->i_we(w_stack_we);
54
        trbuf0->i_waddr(wb_stack_waddr);
55
        trbuf0->i_wdata(wb_stack_wdata);
56
    }
57
};
58
 
59
DbgPort::~DbgPort() {
60
    if (CFG_STACK_TRACE_BUF_SIZE != 0) {
61
        delete trbuf0;
62
    }
63
}
64
 
65
void DbgPort::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) {
66
    if (o_vcd) {
67
        sc_trace(o_vcd, i_dport_valid, "/top/proc0/dbg0/i_dport_valid");
68
        sc_trace(o_vcd, i_dport_write, "/top/proc0/dbg0/i_dport_write");
69
        sc_trace(o_vcd, i_dport_region, "/top/proc0/dbg0/i_dport_region");
70
        sc_trace(o_vcd, i_dport_addr, "/top/proc0/dbg0/i_dport_addr");
71
        sc_trace(o_vcd, i_dport_wdata, "/top/proc0/dbg0/i_dport_wdata");
72
        sc_trace(o_vcd, o_dport_ready, "/top/proc0/dbg0/o_dport_ready");
73
        sc_trace(o_vcd, o_dport_rdata, "/top/proc0/dbg0/o_dport_rdata");
74
        sc_trace(o_vcd, i_e_valid, "/top/proc0/dbg0/i_e_valid");
75
        sc_trace(o_vcd, i_m_valid, "/top/proc0/dbg0/i_m_valid");
76
        sc_trace(o_vcd, i_e_call, "/top/proc0/dbg0/i_e_call");
77
        sc_trace(o_vcd, i_e_ret, "/top/proc0/dbg0/i_e_ret");
78
        sc_trace(o_vcd, i_ebreak, "/top/proc0/dbg0/i_ebreak");
79
        sc_trace(o_vcd, i_istate, "/top/proc0/dbg0/i_istate");
80
        sc_trace(o_vcd, i_dstate, "/top/proc0/dbg0/i_dstate");
81
        sc_trace(o_vcd, i_cstate, "/top/proc0/dbg0/i_cstate");
82
        sc_trace(o_vcd, o_break_mode, "/top/proc0/dbg0/o_break_mode");
83
        sc_trace(o_vcd, o_br_fetch_valid, "/top/proc0/dbg0/o_br_fetch_valid");
84
        sc_trace(o_vcd, o_br_address_fetch, "/top/proc0/dbg0/o_br_address_fetch");
85
        sc_trace(o_vcd, o_br_instr_fetch, "/top/proc0/dbg0/o_br_instr_fetch");
86
 
87
        sc_trace(o_vcd, o_halt, "/top/proc0/dbg0/o_halt");
88
        sc_trace(o_vcd, o_core_addr, "/top/proc0/dbg0/o_core_addr");
89
        sc_trace(o_vcd, o_core_wdata, "/top/proc0/dbg0/o_core_wdata");
90
        sc_trace(o_vcd, o_ireg_ena, "/top/proc0/dbg0/o_ireg_ena");
91
        sc_trace(o_vcd, o_npc_write, "/top/proc0/dbg0/o_npc_write");
92
        sc_trace(o_vcd, o_ireg_write, "/top/proc0/dbg0/o_ireg_write");
93
        sc_trace(o_vcd, r.clock_cnt, "/top/proc0/dbg0/r_clock_cnt");
94
        sc_trace(o_vcd, r.stepping_mode_cnt, "/top/proc0/dbg0/r_stepping_mode_cnt");
95
        sc_trace(o_vcd, r.stepping_mode, "/top/proc0/dbg0/r_stepping_mode");
96
        sc_trace(o_vcd, r.breakpoint, "/top/proc0/dbg0/r_breakpoint");
97
    }
98
    if (CFG_STACK_TRACE_BUF_SIZE != 0) {
99
        trbuf0->generateVCD(i_vcd, o_vcd);
100
    }
101
}
102
 
103
void DbgPort::comb() {
104
    sc_uint<12> wb_o_core_addr;
105
    sc_uint<RISCV_ARCH> wb_o_core_wdata;
106
    sc_uint<64> wb_rdata;
107
    sc_uint<12> wb_idx;
108
    sc_uint<64> wb_o_rdata;
109
    bool w_o_csr_ena;
110
    bool w_o_csr_write;
111
    bool w_o_ireg_ena;
112
    bool w_o_ireg_write;
113
    bool w_o_npc_write;
114
    bool w_cur_halt;
115
 
116
    v = r;
117
 
118
    wb_o_core_addr = 0;
119
    wb_o_core_wdata = 0;
120
    wb_rdata = 0;
121
    wb_o_rdata = 0;
122
    wb_idx = i_dport_addr.read();
123
    w_o_csr_ena = 0;
124
    w_o_csr_write = 0;
125
    w_o_ireg_ena = 0;
126
    w_o_ireg_write = 0;
127
    w_o_npc_write = 0;
128
    v.br_fetch_valid = 0;
129
    v.rd_trbuf_ena = 0;
130
    wb_stack_raddr = 0;
131
    w_stack_we = 0;
132
    wb_stack_waddr = 0;
133
    wb_stack_wdata = 0;
134
 
135
    v.ready = i_dport_valid.read();
136
 
137
    w_cur_halt = 0;
138
    if (i_e_valid.read()) {
139
        if (r.stepping_mode_cnt.read() != 0) {
140
            v.stepping_mode_cnt = r.stepping_mode_cnt.read() - 1;
141
            if (r.stepping_mode_cnt.read() == 1) {
142
                v.halt = 1;
143
                w_cur_halt = 1;
144
                v.stepping_mode = 0;
145
            }
146
        }
147
    }
148
 
149
    if (r.halt == 0) {
150
        v.clock_cnt = r.clock_cnt.read() + 1;
151
    }
152
    if (i_m_valid.read()) {
153
        v.executed_cnt = r.executed_cnt.read() + 1;
154
    }
155
    if (i_ebreak.read()) {
156
        v.breakpoint = 1;
157
        if (!r.trap_on_break) {
158
            v.halt = 1;
159
        }
160
    }
161
 
162
    if (CFG_STACK_TRACE_BUF_SIZE != 0) {
163
        if (i_e_call.read() &&
164
            r.stack_trace_cnt.read() != (CFG_STACK_TRACE_BUF_SIZE - 1)) {
165
            w_stack_we = 1;
166
            wb_stack_waddr = r.stack_trace_cnt.read();
167
            wb_stack_wdata = (i_npc, i_pc);
168
            v.stack_trace_cnt = r.stack_trace_cnt.read() + 1;
169
        } else if (i_e_ret.read() && r.stack_trace_cnt.read() != 0) {
170
            v.stack_trace_cnt = r.stack_trace_cnt.read() - 1;
171
        }
172
    }
173
 
174
    if (i_dport_valid.read()) {
175
        switch (i_dport_region.read()) {
176
        case 0:
177
            w_o_csr_ena = 1;
178
            wb_o_core_addr = i_dport_addr;
179
            wb_rdata = i_csr_rdata;
180
            if (i_dport_write.read()) {
181
                w_o_csr_write = 1;
182
                wb_o_core_wdata = i_dport_wdata;
183
            }
184
            break;
185
        case 1:
186
            if (wb_idx < 32) {
187
                w_o_ireg_ena = 1;
188
                wb_o_core_addr = i_dport_addr;
189
                wb_rdata = i_ireg_rdata;
190
                if (i_dport_write.read()) {
191
                    w_o_ireg_write = 1;
192
                    wb_o_core_wdata = i_dport_wdata;
193
                }
194
            } else if (wb_idx == 32) {
195
                /** Read only register */
196
                wb_rdata = i_pc;
197
            } else if (wb_idx == 33) {
198
                wb_rdata = i_npc;
199
                if (i_dport_write.read()) {
200
                    w_o_npc_write = 1;
201
                    wb_o_core_wdata = i_dport_wdata;
202
                }
203
            } else if (wb_idx == 34) {
204
                wb_rdata = r.stack_trace_cnt;
205
                if (i_dport_write.read()) {
206
                    v.stack_trace_cnt = i_dport_wdata.read()(4, 0);
207
                }
208
            } else if (wb_idx >= 128
209
                && wb_idx < (128 + 2 * CFG_STACK_TRACE_BUF_SIZE)) {
210
                    v.rd_trbuf_ena = 1;
211
                    v.rd_trbuf_addr0 = wb_idx & 0x1;
212
                    wb_stack_raddr = (wb_idx - 128) / 2;
213
            } else if (wb_idx == 256) {
214
                wb_rdata = i_instr_buf.read()(63, 0);
215
            } else if (wb_idx == 257) {
216
                wb_rdata = i_instr_buf.read()(127, 64);
217
            } else if (wb_idx == 258) {
218
                wb_rdata = i_instr_buf.read()(191, 128);
219
            } else if (wb_idx == 259) {
220
                wb_rdata = i_instr_buf.read()(255, 192);
221
            }
222
            break;
223
        case 2:
224
            switch (wb_idx) {
225
            case 0:
226
                wb_rdata[0] = r.halt;
227
                wb_rdata[2] = r.breakpoint;
228
                wb_rdata(33, 32) = i_istate.read();
229
                wb_rdata(37, 36) = i_dstate.read();
230
                wb_rdata(41, 40) = i_cstate.read();
231
                if (i_dport_write.read()) {
232
                    v.halt = i_dport_wdata.read()[0];
233
                    v.stepping_mode = i_dport_wdata.read()[1];
234
                    if (i_dport_wdata.read()[1]) {
235
                        v.stepping_mode_cnt = r.stepping_mode_steps;
236
                    }
237
                }
238
                break;
239
            case 1:
240
                wb_rdata = r.stepping_mode_steps;
241
                if (i_dport_write.read()) {
242
                    v.stepping_mode_steps = i_dport_wdata.read();
243
                }
244
                break;
245
            case 2:
246
                wb_rdata = r.clock_cnt;
247
                break;
248
            case 3:
249
                wb_rdata = r.executed_cnt;
250
                break;
251
            case 4:
252
                /** Trap on instruction:
253
                    *      0 = Halt pipeline on ECALL instruction
254
                    *      1 = Generate trap on ECALL instruction
255
                    */
256
                wb_rdata[0] = r.trap_on_break;
257
                if (i_dport_write.read()) {
258
                    v.trap_on_break = i_dport_wdata.read()[0];
259
                }
260
                break;
261
            case 5:
262
                // todo: add hardware breakpoint
263
                break;
264
            case 6:
265
                // todo: remove hardware breakpoint
266
                break;
267
            case 7:
268
                wb_rdata(BUS_ADDR_WIDTH-1, 0) = r.br_address_fetch;
269
                if (i_dport_write.read()) {
270
                    v.br_address_fetch = i_dport_wdata.read()(BUS_ADDR_WIDTH-1, 0);
271
                }
272
                break;
273
            case 8:
274
                wb_rdata(31, 0) = r.br_instr_fetch;
275
                if (i_dport_write.read()) {
276
                    v.br_fetch_valid = 1;
277
                    v.breakpoint = 0;
278
                    v.br_instr_fetch = i_dport_wdata.read()(31, 0);
279
                }
280
                break;
281
            default:;
282
            }
283
            break;
284
        default:;
285
        }
286
    }
287
    v.rdata = wb_rdata;
288
    if (r.rd_trbuf_ena.read()) {
289
        if (r.rd_trbuf_addr0.read() == 0) {
290
            wb_o_rdata = wb_stack_rdata.read()(BUS_ADDR_WIDTH-1, 0);
291
        } else {
292
            wb_o_rdata = wb_stack_rdata.read()(2*BUS_ADDR_WIDTH-1,
293
                                               BUS_ADDR_WIDTH);
294
        }
295
    } else {
296
        wb_o_rdata = r.rdata;
297
    }
298
 
299
    if (!i_nrst.read()) {
300
        v.ready = 0;
301
        v.halt = 0;
302
        v.breakpoint = 0;
303
        v.stepping_mode = 0;
304
        v.rdata = 0;
305
        v.stepping_mode_cnt = 0;
306
        v.stepping_mode_steps = 0;
307
        v.clock_cnt = 0;
308
        v.executed_cnt = 0;
309
        v.trap_on_break = 0;
310
        v.br_address_fetch = 0;
311
        v.br_instr_fetch = 0;
312
        v.br_fetch_valid = 0;
313
        v.stack_trace_cnt = 0;
314
        v.rd_trbuf_ena = 0;
315
        v.rd_trbuf_addr0 = 0;
316
    }
317
 
318
    o_core_addr = wb_o_core_addr;
319
    o_core_wdata = wb_o_core_wdata;
320
    o_csr_ena = w_o_csr_ena;
321
    o_csr_write = w_o_csr_write;
322
    o_ireg_ena = w_o_ireg_ena;
323
    o_ireg_write = w_o_ireg_write;
324
    o_npc_write = w_o_npc_write;
325
    o_clock_cnt = r.clock_cnt;
326
    o_executed_cnt = r.executed_cnt;
327
    o_halt = r.halt | w_cur_halt;
328
    o_break_mode = r.trap_on_break;
329
    o_br_fetch_valid = r.br_fetch_valid;
330
    o_br_address_fetch = r.br_address_fetch;
331
    o_br_instr_fetch = r.br_instr_fetch;
332
 
333
    o_dport_ready = r.ready;
334
    o_dport_rdata = wb_o_rdata;
335
}
336
 
337
void DbgPort::registers() {
338
    r = v;
339
}
340
 
341
}  // namespace debugger
342
 

powered by: WebSVN 2.1.0

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