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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_fnc_plugin/] [cpu_riscv_func.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      CPU functional simulator class definition.
6
 */
7
 
8
#include "api_core.h"
9
#include "cpu_riscv_func.h"
10
#include "riscv-isa.h"
11
#if 1
12
#include "coreservices/iserial.h"
13
#endif
14
 
15
namespace debugger {
16
 
17
void addIsaUserRV64I(CpuContextType *data, AttributeType *out);
18
void addIsaPrivilegedRV64I(CpuContextType *data, AttributeType *out);
19
void addIsaExtensionA(CpuContextType *data, AttributeType *out);
20
void addIsaExtensionF(CpuContextType *data, AttributeType *out);
21
void addIsaExtensionM(CpuContextType *data, AttributeType *out);
22
 
23
void generateException(uint64_t code, CpuContextType *data);
24
void generateInterrupt(uint64_t code, CpuContextType *data);
25
 
26
uint64_t readCSR(uint32_t idx, CpuContextType *data);
27
void writeCSR(uint32_t idx, uint64_t val, CpuContextType *data);
28
 
29
 
30
CpuRiscV_Functional::CpuRiscV_Functional(const char *name)
31
    : IService(name), IHap(HAP_ConfigDone) {
32
    registerInterface(static_cast<IThread *>(this));
33
    registerInterface(static_cast<ICpuRiscV *>(this));
34
    registerInterface(static_cast<IClock *>(this));
35
    registerInterface(static_cast<IHap *>(this));
36
    registerAttribute("Enable", &isEnable_);
37
    registerAttribute("Bus", &bus_);
38
    registerAttribute("ListExtISA", &listExtISA_);
39
    registerAttribute("FreqHz", &freqHz_);
40
    registerAttribute("GenerateRegTraceFile", &generateRegTraceFile_);
41
    registerAttribute("GenerateMemTraceFile", &generateMemTraceFile_);
42
    registerAttribute("ResetVector", &resetVector_);
43
 
44
    isEnable_.make_boolean(true);
45
    bus_.make_string("");
46
    listExtISA_.make_list(0);
47
    freqHz_.make_uint64(1);
48
    generateRegTraceFile_.make_boolean(false);
49
    generateMemTraceFile_.make_boolean(false);
50
    resetVector_.make_uint64(0x1000);
51
 
52
    cpu_context_.step_cnt = 0;
53
    cpu_context_.stack_trace_cnt = 0;
54
 
55
    RISCV_event_create(&config_done_, "riscv_func_config_done");
56
    RISCV_register_hap(static_cast<IHap *>(this));
57
    cpu_context_.reset   = true;
58
    dbg_state_ = STATE_Normal;
59
    last_hit_breakpoint_ = ~0;
60
    reset();
61
 
62
    trans_.source_idx = CFG_NASTI_MASTER_CACHED;
63
    cpu_context_.reg_trace_file = 0;
64
    cpu_context_.mem_trace_file = 0;
65
    dport.valid = 0;
66
}
67
 
68
CpuRiscV_Functional::~CpuRiscV_Functional() {
69
    CpuContextType *pContext = getpContext();
70
    if (pContext->reg_trace_file) {
71
        pContext->reg_trace_file->close();
72
        delete pContext->reg_trace_file;
73
    }
74
    if (pContext->mem_trace_file) {
75
        pContext->mem_trace_file->close();
76
        delete pContext->mem_trace_file;
77
    }
78
    RISCV_event_close(&config_done_);
79
}
80
 
81
void CpuRiscV_Functional::postinitService() {
82
    CpuContextType *pContext = getpContext();
83
 
84
    pContext->ibus = static_cast<IBus *>(
85
       RISCV_get_service_iface(bus_.to_string(), IFACE_BUS));
86
 
87
    if (!pContext->ibus) {
88
        RISCV_error("Bus interface '%s' not found",
89
                    bus_.to_string());
90
        return;
91
    }
92
 
93
    // Supported instruction sets:
94
    for (int i = 0; i < INSTR_HASH_TABLE_SIZE; i++) {
95
        listInstr_[i].make_list(0);
96
    }
97
    addIsaUserRV64I(pContext, listInstr_);
98
    addIsaPrivilegedRV64I(pContext, listInstr_);
99
    for (unsigned i = 0; i < listExtISA_.size(); i++) {
100
        if (listExtISA_[i].to_string()[0] == 'A') {
101
            addIsaExtensionA(pContext, listInstr_);
102
        } else if (listExtISA_[i].to_string()[0] == 'F') {
103
            addIsaExtensionF(pContext, listInstr_);
104
        } else if (listExtISA_[i].to_string()[0] == 'M') {
105
            addIsaExtensionM(pContext, listInstr_);
106
        }
107
    }
108
 
109
    // Get global settings:
110
    const AttributeType *glb = RISCV_get_global_settings();
111
    if ((*glb)["SimEnable"].to_bool() && isEnable_.to_bool()) {
112
        if (!run()) {
113
            RISCV_error("Can't create thread.", NULL);
114
            return;
115
        }
116
 
117
        if (generateRegTraceFile_.to_bool()) {
118
            pContext->reg_trace_file = new std::ofstream("river_func_regs.log");
119
        }
120
        if (generateMemTraceFile_.to_bool()) {
121
            pContext->mem_trace_file = new std::ofstream("river_func_mem.log");
122
        }
123
    }
124
}
125
 
126
void CpuRiscV_Functional::hapTriggered(IFace *isrc, EHapType type,
127
                                       const char *descr) {
128
    RISCV_event_set(&config_done_);
129
}
130
 
131
void CpuRiscV_Functional::busyLoop() {
132
    RISCV_event_wait(&config_done_);
133
 
134
    while (isEnabled()) {
135
        updatePipeline();
136
    }
137
}
138
 
139
void CpuRiscV_Functional::updatePipeline() {
140
    IInstruction *instr;
141
    CpuContextType *pContext = getpContext();
142
 
143
    if (dport.valid) {
144
        dport.valid = 0;
145
        updateDebugPort();
146
    }
147
 
148
    pContext->pc = pContext->npc;
149
    if (isRunning()) {
150
        fetchInstruction();
151
    }
152
 
153
    updateState();
154
    if (pContext->reset) {
155
        updateQueue();
156
        reset();
157
        return;
158
    }
159
 
160
    instr = decodeInstruction(cacheline_);
161
    if (isRunning()) {
162
        last_hit_breakpoint_ = ~0;
163
        if (instr) {
164
            executeInstruction(instr, cacheline_);
165
        } else {
166
            pContext->npc += 4;
167
            generateException(EXCEPTION_InstrIllegal, pContext);
168
 
169
            RISCV_info("[%" RV_PRI64 "d] pc:%08x: %08x \t illegal instruction",
170
                        getStepCounter(),
171
                        static_cast<uint32_t>(pContext->pc), cacheline_[0]);
172
        }
173
    }
174
 
175
    updateQueue();
176
 
177
    handleTrap();
178
}
179
 
180
void CpuRiscV_Functional::updateState() {
181
    CpuContextType *pContext = getpContext();
182
    bool upd = true;
183
    switch (dbg_state_) {
184
    case STATE_Halted:
185
        upd = false;
186
        break;
187
    case STATE_Stepping:
188
        if (dbg_step_cnt_ <= pContext->step_cnt) {
189
            halt("Stepping breakpoint");
190
            upd = false;
191
        }
192
        break;
193
    default:;
194
    }
195
    if (upd) {
196
        pContext->step_cnt++;
197
   }
198
}
199
 
200
void CpuRiscV_Functional::updateQueue() {
201
    IFace *cb;
202
    CpuContextType *pContext = getpContext();
203
 
204
    queue_.initProc();
205
    queue_.pushPreQueued();
206
 
207
    while ((cb = queue_.getNext(pContext->step_cnt)) != 0) {
208
        static_cast<IClockListener *>(cb)->stepCallback(pContext->step_cnt);
209
    }
210
}
211
 
212
void CpuRiscV_Functional::handleTrap() {
213
    CpuContextType *pContext = getpContext();
214
    csr_mstatus_type mstatus;
215
    csr_mcause_type mcause;
216
    mstatus.value = pContext->csr[CSR_mstatus];
217
    mcause.value =  pContext->csr[CSR_mcause];
218
 
219
    if (pContext->exception == 0 && pContext->interrupt == 0) {
220
        return;
221
    }
222
    if (pContext->interrupt &&
223
        mstatus.bits.MIE == 0 && pContext->cur_prv_level == PRV_M) {
224
        return;
225
    }
226
    if (mcause.value == EXCEPTION_Breakpoint
227
        && pContext->br_ctrl.bits.trap_on_break == 0) {
228
        pContext->exception = 0;
229
        pContext->npc = pContext->pc;
230
        halt("EBREAK Breakpoint");
231
        return;
232
    }
233
 
234
    pContext->interrupt = 0;
235
    pContext->exception = 0;
236
 
237
    // All traps handle via machine mode while CSR mdelegate
238
    // doesn't setup other.
239
    // @todo delegating
240
    mstatus.bits.MPP = pContext->cur_prv_level;
241
    mstatus.bits.MPIE = (mstatus.value >> pContext->cur_prv_level) & 0x1;
242
    mstatus.bits.MIE = 0;
243
    pContext->cur_prv_level = PRV_M;
244
    pContext->csr[CSR_mstatus] = mstatus.value;
245
 
246
    uint64_t xepc = (pContext->cur_prv_level << 8) + 0x41;
247
    if (pContext->exception) {
248
        pContext->csr[xepc]    = pContext->pc;
249
    } else {
250
        // Software interrupt handled after instruction was executed
251
        pContext->csr[xepc]    = pContext->npc;
252
    }
253
    pContext->npc = pContext->csr[CSR_mtvec];
254
 
255
    pContext->exception = 0;
256
}
257
 
258
bool CpuRiscV_Functional::isRunning() {
259
    return  (dbg_state_ != STATE_Halted);
260
}
261
 
262
void CpuRiscV_Functional::reset() {
263
    CpuContextType *pContext = getpContext();
264
    pContext->regs[0] = 0;
265
    pContext->pc = resetVector_.to_uint64();
266
    pContext->npc = resetVector_.to_uint64();
267
    pContext->exception = 0;
268
    pContext->interrupt = 0;
269
    pContext->interrupt_pending = 0;
270
    pContext->csr[CSR_mvendorid] = 0x0001;   // UC Berkeley Rocket repo
271
    pContext->csr[CSR_mhartid] = 0;
272
    pContext->csr[CSR_marchid] = 0;
273
    pContext->csr[CSR_mimplementationid] = 0;
274
    pContext->csr[CSR_mtvec]   = 0x100;     // Hardwired RO value
275
    pContext->csr[CSR_mip] = 0;             // clear pending interrupts
276
    pContext->csr[CSR_mie] = 0;             // disabling interrupts
277
    pContext->csr[CSR_mepc] = 0;
278
    pContext->csr[CSR_mcause] = 0;
279
    pContext->csr[CSR_medeleg] = 0;
280
    pContext->csr[CSR_mideleg] = 0;
281
    pContext->csr[CSR_mtime] = 0;
282
    pContext->csr[CSR_mtimecmp] = 0;
283
    pContext->csr[CSR_uepc] = 0;
284
    pContext->csr[CSR_sepc] = 0;
285
    pContext->csr[CSR_hepc] = 0;
286
    csr_mstatus_type mstat;
287
    mstat.value = 0;
288
    pContext->csr[CSR_mstatus] = mstat.value;
289
    pContext->cur_prv_level = PRV_M;           // Current privilege level
290
    pContext->step_cnt = 0;
291
    pContext->br_ctrl.val = 0;
292
    pContext->br_inject_fetch = false;
293
    pContext->br_status_ena = false;
294
    pContext->stack_trace_cnt = 0;
295
}
296
 
297
void CpuRiscV_Functional::fetchInstruction() {
298
    CpuContextType *pContext = getpContext();
299
    if (pContext->br_inject_fetch
300
        && pContext->pc == pContext->br_address_fetch) {
301
        pContext->br_inject_fetch = false;
302
        cacheline_[0] = pContext->br_instr_fetch;
303
        return;
304
    }
305
    trans_.action = MemAction_Read;
306
    trans_.addr = pContext->pc;
307
    trans_.xsize = 4;
308
    trans_.wstrb = 0;
309
    pContext->ibus->b_transport(&trans_);
310
    cacheline_[0] = trans_.rpayload.b32[0];
311
}
312
 
313
IInstruction *CpuRiscV_Functional::decodeInstruction(uint32_t *rpayload) {
314
    IInstruction *instr = NULL;
315
    int hash_idx = hash32(rpayload[0]);
316
    for (unsigned i = 0; i < listInstr_[hash_idx].size(); i++) {
317
        instr = static_cast<IInstruction *>(
318
                        listInstr_[hash_idx][i].to_iface());
319
        if (instr->parse(rpayload)) {
320
            break;
321
        }
322
        instr = NULL;
323
    }
324
 
325
    return instr;
326
}
327
 
328
void CpuRiscV_Functional::debugRegOutput(const char *marker,
329
                                         CpuContextType *pContext) {
330
        RISCV_debug("%s[%" RV_PRI64 "d] %d %08x: "
331
                    "1:%016" RV_PRI64 "x; 2:%016" RV_PRI64 "x; 3:%016" RV_PRI64 "x; 4:%016" RV_PRI64 "x "
332
                    "5:%016" RV_PRI64 "x; 6:%016" RV_PRI64 "x; 7:%016" RV_PRI64 "x; 8:%016" RV_PRI64 "x "
333
                    "9:%016" RV_PRI64 "x; 10:%016" RV_PRI64 "x; 11:%016" RV_PRI64 "x; 12:%016" RV_PRI64 "x "
334
                    "13:%016" RV_PRI64 "x; 14:%016" RV_PRI64 "x; 15:%016" RV_PRI64 "x; 16:%016" RV_PRI64 "x "
335
                    "17:%016" RV_PRI64 "x; 18:%016" RV_PRI64 "x; 19:%016" RV_PRI64 "x; 20:%016" RV_PRI64 "x "
336
                    "21:%016" RV_PRI64 "x; 22:%016" RV_PRI64 "x; 24:%016" RV_PRI64 "x; 25:%016" RV_PRI64 "x "
337
                    "25:%016" RV_PRI64 "x; 26:%016" RV_PRI64 "x; 27:%016" RV_PRI64 "x; 28:%016" RV_PRI64 "x "
338
                    "29:%016" RV_PRI64 "x; 30:%016" RV_PRI64 "x; 31:%016" RV_PRI64 "x",
339
            marker,
340
            getStepCounter(),
341
            (int)pContext->cur_prv_level,
342
            (uint32_t)pContext->csr[CSR_mepc],
343
            pContext->regs[1], pContext->regs[2], pContext->regs[3], pContext->regs[4],
344
            pContext->regs[5], pContext->regs[6], pContext->regs[7], pContext->regs[8],
345
            pContext->regs[9], pContext->regs[10], pContext->regs[11], pContext->regs[12],
346
            pContext->regs[13], pContext->regs[14], pContext->regs[15], pContext->regs[16],
347
            pContext->regs[17], pContext->regs[18], pContext->regs[19], pContext->regs[20],
348
            pContext->regs[21], pContext->regs[22], pContext->regs[23], pContext->regs[24],
349
            pContext->regs[25], pContext->regs[26], pContext->regs[27], pContext->regs[28],
350
            pContext->regs[29], pContext->regs[30], pContext->regs[31]);
351
}
352
 
353
void CpuRiscV_Functional::executeInstruction(IInstruction *instr,
354
                                             uint32_t *rpayload) {
355
 
356
    CpuContextType *pContext = getpContext();
357
    if (pContext->reg_trace_file) {
358
        /** Save previous reg values to find modification after exec() */
359
        for (int i = 0; i < Reg_Total; i++) {
360
            iregs_prev[i] = pContext->regs[i];
361
        }
362
    }
363
 
364
    instr->exec(cacheline_, pContext);
365
#if 0
366
    if (pContext->pc == 0x10000148 && pContext->regs[Reg_a0] != 3) {
367
        RISCV_debug("IstWrapper [%" RV_PRI64 "d]: idx=%" RV_PRI64 "d",
368
            getStepCounter(), pContext->regs[Reg_a0]);
369
    }
370
    if (pContext->pc == 0x1000246c) {
371
        RISCV_debug("new_thread [%" RV_PRI64 "d]: "
372
                    "Stack:%016" RV_PRI64 "x; StackSize:%" RV_PRI64 "d; Entry:%08" RV_PRI64 "x "
373
                    "tp:%016" RV_PRI64 "x => %016" RV_PRI64 "x; prio=%" RV_PRI64 "d",
374
            getStepCounter(),
375
            pContext->regs[Reg_a0], pContext->regs[Reg_a1], pContext->regs[Reg_a2],
376
            pContext->regs[Reg_tp], pContext->regs[Reg_a0]+96,
377
            pContext->regs[Reg_a6]);
378
    }
379
#endif
380
    if (pContext->reg_trace_file) {
381
        int sz;
382
        sz = RISCV_sprintf(tstr, sizeof(tstr),"%8I64d [%08x] %08x: ",
383
            pContext->step_cnt, static_cast<uint32_t>(pContext->pc), rpayload[0]);
384
 
385
        bool reg_changed = false;
386
        for (int i = 0; i < 32; i++) {
387
            if (iregs_prev[i] != pContext->regs[i]) {
388
                reg_changed = true;
389
                sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz,
390
                        "%3s <= %016I64x\n", IREGS_NAMES[i], pContext->regs[i]);
391
            }
392
        }
393
        if (!reg_changed) {
394
            sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz, "%s", "-\n");
395
        }
396
        (*pContext->reg_trace_file) << tstr;
397
        pContext->reg_trace_file->flush();
398
    }
399
 
400
    if (generateRegTraceFile_.to_bool()) {
401
        char msg[16];
402
        int msg_len = 0;
403
        IService *uart = NULL;
404
        switch (pContext->step_cnt) {
405
        case 22080:
406
            uart = static_cast<IService *>(RISCV_get_service("uart0"));
407
            msg[0] = 'h';
408
            msg_len = 1;
409
            break;
410
        case 22500:
411
            uart = static_cast<IService *>(RISCV_get_service("uart0"));
412
            msg[0] = 'e';
413
            msg[1] = 'l';
414
            msg_len = 2;
415
            break;
416
        case 24350:
417
            uart = static_cast<IService *>(RISCV_get_service("uart0"));
418
            msg[0] = 'p';
419
            msg[1] = '\r';
420
            msg[2] = '\n';
421
            msg_len = 3;
422
            break;
423
        default:;
424
        }
425
 
426
        if (uart) {
427
            ISerial *iserial = static_cast<ISerial *>(
428
                        uart->getInterface(IFACE_SERIAL));
429
            //iserial->writeData("pnp\r\n", 6);
430
            //iserial->writeData("highticks\r\n", 11);
431
            iserial->writeData(msg, msg_len);
432
        }
433
    }
434
 
435
 
436
    if (pContext->regs[0] != 0) {
437
        RISCV_error("Register x0 was modificated (not equal to zero)", NULL);
438
    }
439
}
440
 
441
void CpuRiscV_Functional::registerStepCallback(IClockListener *cb,
442
                                               uint64_t t) {
443
    if (!isEnabled()) {
444
        if (t <= getpContext()->step_cnt) {
445
            cb->stepCallback(t);
446
        }
447
        return;
448
    }
449
    queue_.put(t, cb);
450
}
451
 
452
 
453
/**
454
 * prv-1.9.1 page 29
455
 *
456
 * An interrupt i will be taken if bit i is set in both mip and mie,
457
 * and if interrupts are globally enabled.  By default, M-mode interrupts
458
 * are globally enabled if the hart’s current privilege mode is less than M,
459
 * or if the current privilege mode is M and the MIE bit in the mstatus
460
 * register is set.
461
 * If bit i in mideleg is set, however, interrupts are considered to be
462
 * globally enabled if the hart’s current privilege mode equals the delegated
463
 * privilege mode (H, S, or U) and that mode’s interrupt enable bit
464
 * (HIE, SIE or UIE in mstatus) is set, or if the current privilege mode is
465
 * less than the delegated privilege mode.
466
 */
467
void CpuRiscV_Functional::raiseSignal(int idx) {
468
    CpuContextType *pContext = getpContext();
469
    csr_mstatus_type mstatus;
470
    mstatus.value = pContext->csr[CSR_mstatus];
471
 
472
    switch (idx) {
473
    case CPU_SIGNAL_RESET:
474
        pContext->reset = true; // Active HIGH
475
        break;
476
    case CPU_SIGNAL_EXT_IRQ:
477
        if (pContext->reset) {
478
            break;
479
        }
480
        // External Interrupt controller pending bit
481
        pContext->interrupt_pending |= (1ull << idx);
482
        if (mstatus.bits.MIE == 0 && pContext->cur_prv_level == PRV_M) {
483
            break;
484
        }
485
        /// @todo delegate interrupt to non-machine privilege level.
486
        generateInterrupt(INTERRUPT_MExternal, pContext);
487
        break;
488
    default:
489
        RISCV_error("Unsupported signalRaise(%d)", idx);
490
    }
491
}
492
 
493
void CpuRiscV_Functional::lowerSignal(int idx) {
494
    CpuContextType *pContext = getpContext();
495
    switch (idx) {
496
    case CPU_SIGNAL_RESET:
497
        pContext->reset = false; // Active HIGH
498
        break;
499
    case CPU_SIGNAL_EXT_IRQ:
500
        pContext->interrupt_pending &= ~(1 << idx);
501
        break;
502
    default:
503
        RISCV_error("Unsupported lowerSignal(%d)", idx);
504
    }
505
}
506
 
507
void CpuRiscV_Functional::updateDebugPort() {
508
    CpuContextType *pContext = getpContext();
509
    DsuMapType::udbg_type::debug_region_type::control_reg ctrl;
510
    DebugPortTransactionType *trans = dport.trans;
511
    trans->rdata = 0;
512
    switch (trans->region) {
513
    case 0:     // CSR
514
        trans->rdata = pContext->csr[trans->addr];
515
        if (trans->write) {
516
            pContext->csr[trans->addr] = trans->wdata;
517
        }
518
        break;
519
    case 1:     // IRegs
520
        if (trans->addr < Reg_Total) {
521
            trans->rdata = pContext->regs[trans->addr];
522
            if (trans->write) {
523
                pContext->regs[trans->addr] = trans->wdata;
524
            }
525
        } else if (trans->addr == Reg_Total) {
526
            /** Read only register */
527
            trans->rdata = pContext->pc;
528
        } else if (trans->addr == (Reg_Total + 1)) {
529
            trans->rdata = pContext->npc;
530
            if (trans->write) {
531
                pContext->npc = trans->wdata;
532
            }
533
        } else if (trans->addr == (Reg_Total + 2)) {
534
            trans->rdata = pContext->stack_trace_cnt;
535
            if (trans->write) {
536
                pContext->stack_trace_cnt = static_cast<int>(trans->wdata);
537
            }
538
        } else if (trans->addr >= 128 &&
539
                    trans->addr < (128 + STACK_TRACE_BUF_SIZE)) {
540
            trans->rdata = pContext->stack_trace_buf[trans->addr - 128];
541
        }
542
        break;
543
    case 2:     // Control
544
        switch (trans->addr) {
545
        case 0:
546
            ctrl.val = trans->wdata;
547
            if (trans->write) {
548
                if (ctrl.bits.halt) {
549
                    halt();
550
                } else if (ctrl.bits.stepping) {
551
                    step(dport.stepping_mode_steps);
552
                } else {
553
                    go();
554
                }
555
            } else {
556
                ctrl.val = 0;
557
                ctrl.bits.halt = isHalt() ? 1: 0;
558
                if (pContext->br_status_ena) {
559
                    ctrl.bits.breakpoint = 1;
560
                }
561
                ctrl.bits.core_id = 0;
562
            }
563
            trans->rdata = ctrl.val;
564
            break;
565
        case 1:
566
            trans->rdata = dport.stepping_mode_steps;
567
            if (trans->write) {
568
                dport.stepping_mode_steps = trans->wdata;
569
            }
570
            break;
571
        case 2:
572
            trans->rdata = pContext->step_cnt;
573
            break;
574
        case 3:
575
            trans->rdata = pContext->step_cnt;
576
            break;
577
        case 4:
578
            trans->rdata = pContext->br_ctrl.val;
579
            if (trans->write) {
580
                pContext->br_ctrl.val = trans->wdata;
581
            }
582
            break;
583
        case 5:
584
            if (trans->write) {
585
                addBreakpoint(trans->wdata);
586
            }
587
            break;
588
        case 6:
589
            if (trans->write) {
590
                removeBreakpoint(trans->wdata);
591
            }
592
            break;
593
        case 7:
594
            trans->rdata = pContext->br_address_fetch;
595
            if (trans->write) {
596
                pContext->br_address_fetch = trans->wdata;
597
            }
598
            break;
599
        case 8:
600
            trans->rdata = pContext->br_instr_fetch;
601
            if (trans->write) {
602
                pContext->br_inject_fetch = true;
603
                pContext->br_status_ena = false;
604
                pContext->br_instr_fetch = static_cast<uint32_t>(trans->wdata);
605
            }
606
            break;
607
        default:;
608
        }
609
        break;
610
    default:;
611
    }
612
    dport.cb->nb_response_debug_port(dport.trans);
613
}
614
 
615
void
616
CpuRiscV_Functional::nb_transport_debug_port(DebugPortTransactionType *trans,
617
                                             IDbgNbResponse *cb) {
618
    dport.trans = trans;
619
    dport.cb = cb;
620
    dport.valid = true;
621
}
622
 
623
void CpuRiscV_Functional::halt(const char *descr) {
624
    CpuContextType *pContext = getpContext();
625
    dbg_state_ = STATE_Halted;
626
 
627
    if (descr == NULL) {
628
        RISCV_printf0(
629
            "[%" RV_PRI64 "d] pc:%016" RV_PRI64 "x: %08x \t CPU halted",
630
            getStepCounter(), pContext->pc, cacheline_[0]);
631
    } else {
632
        RISCV_printf0("[%" RV_PRI64 "d] pc:%016" RV_PRI64 "x: %08x \t %s",
633
            getStepCounter(), pContext->pc, cacheline_[0], descr);
634
    }
635
}
636
 
637
void CpuRiscV_Functional::go() {
638
    dbg_state_ = STATE_Normal;
639
}
640
 
641
void CpuRiscV_Functional::step(uint64_t cnt) {
642
    CpuContextType *pContext = getpContext();
643
    dbg_step_cnt_ = pContext->step_cnt + cnt;
644
    dbg_state_ = STATE_Stepping;
645
}
646
 
647
uint64_t CpuRiscV_Functional::getReg(uint64_t idx) {
648
    CpuContextType *pContext = getpContext();
649
    if (idx >= 0 && idx < 32) {
650
        return pContext->regs[idx];
651
    }
652
    return REG_INVALID;
653
}
654
 
655
void CpuRiscV_Functional::setReg(uint64_t idx, uint64_t val) {
656
    CpuContextType *pContext = getpContext();
657
    if (idx >= 0 && idx < 32) {
658
        pContext->regs[idx] = val;
659
    }
660
}
661
 
662
uint64_t CpuRiscV_Functional::getPC() {
663
    CpuContextType *pContext = getpContext();
664
    return pContext->pc;
665
}
666
 
667
void CpuRiscV_Functional::setPC(uint64_t val) {
668
    CpuContextType *pContext = getpContext();
669
    pContext->pc = val;
670
}
671
 
672
uint64_t CpuRiscV_Functional::getNPC() {
673
    CpuContextType *pContext = getpContext();
674
    return pContext->npc;
675
}
676
 
677
void CpuRiscV_Functional::setNPC(uint64_t val) {
678
    CpuContextType *pContext = getpContext();
679
    pContext->npc = val;
680
}
681
 
682
void CpuRiscV_Functional::addBreakpoint(uint64_t addr) {
683
    //CpuContextType *pContext = getpContext();
684
}
685
 
686
void CpuRiscV_Functional::removeBreakpoint(uint64_t addr) {
687
    //CpuContextType *pContext = getpContext();
688
}
689
 
690
void CpuRiscV_Functional::hitBreakpoint(uint64_t addr) {
691
    CpuContextType *pContext = getpContext();
692
    if (addr == last_hit_breakpoint_) {
693
        return;
694
    }
695
    dbg_state_ = STATE_Halted;
696
    last_hit_breakpoint_ = addr;
697
 
698
    RISCV_printf0("[%" RV_PRI64 "d] pc:%016" RV_PRI64 "x: %08x \t stop on breakpoint",
699
        getStepCounter(), pContext->pc, cacheline_[0]);
700
}
701
 
702
}  // namespace debugger
703
 

powered by: WebSVN 2.1.0

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