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 5

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

Line No. Rev Author Line
1 4 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
 
11
namespace debugger {
12
 
13
CpuRiver_Functional::CpuRiver_Functional(const char *name) :
14
    CpuGeneric(name),
15
    portRegs_(this, "regs", DSUREG(ureg.v.iregs), Reg_Total),
16
    portSavedRegs_(this, "savedregs", 0, Reg_Total),  // not mapped !!!
17
    portCSR_(this, "csr", DSUREG(csr), 1<<12) {
18
    registerInterface(static_cast<ICpuRiscV *>(this));
19
    registerAttribute("ListExtISA", &listExtISA_);
20
    registerAttribute("VendorID", &vendorID_);
21
    registerAttribute("VectorTable", &vectorTable_);
22
}
23
 
24
CpuRiver_Functional::~CpuRiver_Functional() {
25
}
26
 
27
void CpuRiver_Functional::postinitService() {
28
    // Supported instruction sets:
29
    for (int i = 0; i < INSTR_HASH_TABLE_SIZE; i++) {
30
        listInstr_[i].make_list(0);
31
    }
32
    addIsaUserRV64I();
33
    addIsaPrivilegedRV64I();
34
    for (unsigned i = 0; i < listExtISA_.size(); i++) {
35
        if (listExtISA_[i].to_string()[0] == 'A') {
36
            addIsaExtensionA();
37
        } else if (listExtISA_[i].to_string()[0] == 'C') {
38
            addIsaExtensionC();
39
        } else if (listExtISA_[i].to_string()[0] == 'F') {
40
            addIsaExtensionF();
41
        } else if (listExtISA_[i].to_string()[0] == 'M') {
42
            addIsaExtensionM();
43
        }
44
    }
45
 
46
    // Power-on
47
    reset(false);
48
 
49
    CpuGeneric::postinitService();
50
}
51
 
52
unsigned CpuRiver_Functional::addSupportedInstruction(
53
                                    RiscvInstruction *instr) {
54
    AttributeType tmp(instr);
55
    listInstr_[instr->hash()].add_to_list(&tmp);
56
    return 0;
57
}
58
 
59
void CpuRiver_Functional::handleTrap() {
60
    csr_mstatus_type mstatus;
61
    csr_mcause_type mcause;
62
    if (interrupt_pending_ == 0) {
63
        return;
64
    }
65
 
66
    mstatus.value = portCSR_.read(CSR_mstatus).val;
67
    mcause.value =  portCSR_.read(CSR_mcause).val;
68
    uint64_t exception_mask = (1ull << INTERRUPT_USoftware) - 1;
69
    if ((interrupt_pending_ & exception_mask) == 0 &&
70
        mstatus.bits.MIE == 0 && cur_prv_level == PRV_M) {
71
        return;
72
    }
73
    if (mcause.value == EXCEPTION_Breakpoint) {
74
        DsuMapType::udbg_type::debug_region_type::breakpoint_control_reg t1;
75
        t1.val = br_control_.getValue().val;
76
        if (t1.bits.trap_on_break == 0) {
77
            sw_breakpoint_ = true;
78
            interrupt_pending_ &= ~(1ull << EXCEPTION_Breakpoint);
79
            npc_.setValue(pc_.getValue());
80
            halt("EBREAK Breakpoint");
81
            return;
82
        }
83
    }
84
 
85
    // All traps handle via machine mode while CSR mdelegate
86
    // doesn't setup other.
87
    // @todo delegating
88
    mstatus.bits.MPP = cur_prv_level;
89
    mstatus.bits.MPIE = (mstatus.value >> cur_prv_level) & 0x1;
90
    mstatus.bits.MIE = 0;
91
    cur_prv_level = PRV_M;
92
    portCSR_.write(CSR_mstatus, mstatus.value);
93
 
94
    int xepc = static_cast<int>((cur_prv_level << 8) + 0x41);
95
    if (interrupt_pending_ & exception_mask) {
96
        // Exception
97
        portCSR_.write(xepc, pc_.getValue().val);
98
    } else {
99
        // Software interrupt handled after instruction was executed
100
        portCSR_.write(xepc,  npc_.getValue().val);
101
    }
102
    npc_.setValue(portCSR_.read(CSR_mtvec));
103
    interrupt_pending_ = 0;
104
}
105
 
106
void CpuRiver_Functional::reset(bool active) {
107
    CpuGeneric::reset(active);
108
    portRegs_.reset();
109
    portCSR_.reset();
110
    portCSR_.write(CSR_mvendorid, vendorID_.to_uint64());
111
    portCSR_.write(CSR_mtvec, vectorTable_.to_uint64());
112
 
113
    cur_prv_level = PRV_M;           // Current privilege level
114
}
115
 
116
GenericInstruction *CpuRiver_Functional::decodeInstruction(Reg64Type *cache) {
117
    RiscvInstruction *instr = NULL;
118
    int hash_idx = hash32(cacheline_[0].buf32[0]);
119
    for (unsigned i = 0; i < listInstr_[hash_idx].size(); i++) {
120
        instr = static_cast<RiscvInstruction *>(
121
                        listInstr_[hash_idx][i].to_iface());
122
        if (instr->parse(cacheline_[0].buf32)) {
123
            break;
124
        }
125
        instr = NULL;
126
    }
127
    // Check compressed instructions:
128
    if (instr == NULL) {
129
        hash_idx = hash16(cacheline_[0].buf16[0]);
130
        for (unsigned i = 0; i < listInstr_[hash_idx].size(); i++) {
131
            instr = static_cast<RiscvInstruction *>(
132
                            listInstr_[hash_idx][i].to_iface());
133
            if (instr->parse(cacheline_[0].buf32)) {
134
                break;
135
            }
136
            instr = NULL;
137
        }
138
    }
139
    return instr;
140
}
141
 
142
void CpuRiver_Functional::generateIllegalOpcode() {
143
    raiseSignal(EXCEPTION_InstrIllegal);
144
    RISCV_error("Illegal instruction at 0x%08" RV_PRI64 "x", getPC());
145
}
146
 
147
void CpuRiver_Functional::trackContextStart() {
148
    if (reg_trace_file == 0) {
149
        return;
150
    }
151
    /** Save previous reg values to find modification after exec() */
152
    uint64_t *dst = portSavedRegs_.getpR64();
153
    uint64_t *src = portRegs_.getpR64();
154
    memcpy(dst, src, Reg_Total*sizeof(uint64_t));
155
}
156
 
157
void CpuRiver_Functional::trackContextEnd() {
158
    if (reg_trace_file == 0) {
159
        return;
160
    }
161
    int sz;
162
    char tstr[1024];
163
    sz = RISCV_sprintf(tstr, sizeof(tstr),"%8I64d [%08x]: ",
164
        step_cnt_, pc_.getValue().buf32[0]);
165
 
166
    bool reg_changed = false;
167
    uint64_t *prev = portSavedRegs_.getpR64();
168
    uint64_t *cur = portRegs_.getpR64();
169
    for (int i = 0; i < Reg_Total; i++) {
170
        if (prev[i] != cur[i]) {
171
            reg_changed = true;
172
            sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz,
173
                    "%3s <= %016I64x",
174
                    IREGS_NAMES[i], cur[i]);//, instr_->name());
175
        }
176
    }
177
    if (instr_ && !reg_changed) {
178
        sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz, "-", NULL);
179
    }
180
    (*reg_trace_file) << tstr << "\n";
181
    reg_trace_file->flush();
182
}
183
 
184
void CpuRiver_Functional::raiseSignal(int idx) {
185
    if (idx < INTERRUPT_USoftware) {
186
        // Exception:
187
        csr_mcause_type cause;
188
        cause.value     = 0;
189
        cause.bits.irq  = 0;
190
        cause.bits.code = idx;
191
        portCSR_.write(CSR_mcause, cause.value);
192
        interrupt_pending_ |= 1LL << idx;
193
    } else if (idx < SIGNAL_HardReset) {
194
        csr_mcause_type cause;
195
        cause.value     = 0;
196
        cause.bits.irq  = 1;
197
        cause.bits.code = idx - INTERRUPT_USoftware;
198
        portCSR_.write(CSR_mcause, cause.value);
199
        interrupt_pending_ |= 1LL << idx;
200
    } else if (idx == SIGNAL_HardReset) {
201
    } else {
202
        RISCV_error("Raise unsupported signal %d", idx);
203
    }
204
}
205
 
206
void CpuRiver_Functional::lowerSignal(int idx) {
207
    if (idx == SIGNAL_HardReset) {
208
    } else if (idx < SIGNAL_HardReset) {
209
        interrupt_pending_ &= ~(1 << idx);
210
    } else {
211
        RISCV_error("Lower unsupported signal %d", idx);
212
    }
213
}
214
 
215
uint64_t CpuRiver_Functional::readCSR(int idx) {
216
    if (idx == CSR_mtime) {
217
        return step_cnt_;
218
    }
219
    return portCSR_.read(idx).val;
220
}
221
 
222
void CpuRiver_Functional::writeCSR(int idx, uint64_t val) {
223
    switch (idx) {
224
    // Read-Only registers
225
    case CSR_misa:
226
    case CSR_mvendorid:
227
    case CSR_marchid:
228
    case CSR_mimplementationid:
229
    case CSR_mhartid:
230
        break;
231
    case CSR_mtime:
232
        break;
233
    default:
234
        portCSR_.write(idx, val);
235
    }
236
}
237
 
238
}  // namespace debugger
239
 

powered by: WebSVN 2.1.0

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