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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_fnc_plugin/] [riscv-rv64i-priv.cpp] - Blame information for rev 4

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      Base ISA implementation (extension I, privileged level).
6
 */
7
 
8
#include "api_utils.h"
9
#include "riscv-isa.h"
10 4 sergeykhbr
#include "cpu_riscv_func.h"
11 2 sergeykhbr
 
12
namespace debugger {
13
 
14
/**
15
 * @brief The CSRRC (Atomic Read and Clear Bit in CSR).
16
 *
17
 * Instruction reads the value of the CSR, zeroextends the value to XLEN bits,
18
 * and writes it to integer register rd. The initial value in integer
19
 * register rs1 specifies bit positions to be cleared in the CSR. Any bit that
20
 * is high in rs1 will cause the corresponding bit to be cleared in the CSR,
21
 * if that CSR bit is writable. Other bits in the CSR are unaffected.
22
 */
23 4 sergeykhbr
class CSRRC : public RiscvInstruction {
24 2 sergeykhbr
public:
25 4 sergeykhbr
    CSRRC(CpuRiver_Functional *icpu) :
26
        RiscvInstruction(icpu, "CSRRC", "?????????????????011?????1110011") {}
27 2 sergeykhbr
 
28 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
29 2 sergeykhbr
        ISA_I_type u;
30 4 sergeykhbr
        u.value = payload->buf32[0];
31 2 sergeykhbr
 
32 4 sergeykhbr
        uint64_t clr_mask = ~R[u.bits.rs1];
33
        uint64_t csr = icpu_->readCSR(u.bits.imm);
34 2 sergeykhbr
        if (u.bits.rd) {
35 4 sergeykhbr
            R[u.bits.rd] = csr;
36 2 sergeykhbr
        }
37 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, (csr & clr_mask));
38
        return 4;
39 2 sergeykhbr
    }
40
};
41
 
42
/**
43
 * @brief The CSRRCI (Atomic Read and Clear Bit in CSR immediate).
44
 *
45
 * Similar to CSRRC except it updates the CSR using a 5-bit zero-extended
46
 * immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
47
 * an integer register.
48
 */
49 4 sergeykhbr
class CSRRCI : public RiscvInstruction {
50 2 sergeykhbr
public:
51 4 sergeykhbr
    CSRRCI(CpuRiver_Functional *icpu) :
52
        RiscvInstruction(icpu, "CSRRCI", "?????????????????111?????1110011") {}
53 2 sergeykhbr
 
54 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
55 2 sergeykhbr
        ISA_I_type u;
56 4 sergeykhbr
        u.value = payload->buf32[0];
57 2 sergeykhbr
 
58
        uint64_t clr_mask = ~static_cast<uint64_t>((u.bits.rs1));
59 4 sergeykhbr
        uint64_t csr = icpu_->readCSR(u.bits.imm);
60 2 sergeykhbr
        if (u.bits.rd) {
61 4 sergeykhbr
            R[u.bits.rd] = csr;
62 2 sergeykhbr
        }
63 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, (csr & clr_mask));
64
        return 4;
65 2 sergeykhbr
    }
66
};
67
 
68
/**
69
 * @brief The CSRRS (Atomic Read and Set Bit in CSR).
70
 *
71
 *   Instruction reads the value of the CSR, zero-extends the value to XLEN
72
 * bits, and writes it to integer register rd. The initial value in integer
73
 * register rs1 specifies bit positions to be set in the CSR. Any bit that is
74
 * high in rs1 will cause the corresponding bit to be set in the CSR, if that
75
 * CSR bit is writable. Other bits in the CSR are unaffected (though CSRs
76
 * might have side effects when written).
77
 *   The CSRR pseudo instruction (read CSR), when rs1 = 0.
78
 */
79 4 sergeykhbr
class CSRRS : public RiscvInstruction {
80 2 sergeykhbr
public:
81 4 sergeykhbr
    CSRRS(CpuRiver_Functional *icpu) :
82
        RiscvInstruction(icpu, "CSRRS", "?????????????????010?????1110011") {}
83 2 sergeykhbr
 
84 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
85 2 sergeykhbr
        ISA_I_type u;
86 4 sergeykhbr
        u.value = payload->buf32[0];
87 2 sergeykhbr
 
88 4 sergeykhbr
        uint64_t set_mask = R[u.bits.rs1];
89
        uint64_t csr = icpu_->readCSR(u.bits.imm);
90 2 sergeykhbr
        if (u.bits.rd) {
91 4 sergeykhbr
            R[u.bits.rd] = csr;
92 2 sergeykhbr
        }
93 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, (csr | set_mask));
94
        return 4;
95 2 sergeykhbr
    }
96
};
97
 
98
/**
99
 * @brief The CSRRSI (Atomic Read and Set Bit in CSR immediate).
100
 *
101
 * Similar to CSRRS except it updates the CSR using a 5-bit zero-extended
102
 * immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
103
 * an integer register.
104
 */
105 4 sergeykhbr
class CSRRSI : public RiscvInstruction {
106 2 sergeykhbr
public:
107 4 sergeykhbr
    CSRRSI(CpuRiver_Functional *icpu) :
108
        RiscvInstruction(icpu, "CSRRSI", "?????????????????110?????1110011") {}
109 2 sergeykhbr
 
110 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
111 2 sergeykhbr
        ISA_I_type u;
112 4 sergeykhbr
        u.value = payload->buf32[0];
113 2 sergeykhbr
 
114
        uint64_t set_mask = u.bits.rs1;
115 4 sergeykhbr
        uint64_t csr = icpu_->readCSR(u.bits.imm);
116 2 sergeykhbr
        if (u.bits.rd) {
117 4 sergeykhbr
            R[u.bits.rd] = csr;
118 2 sergeykhbr
        }
119 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, (csr | set_mask));
120
        return 4;
121 2 sergeykhbr
    }
122
};
123
 
124
/**
125
 * @brief The CSRRW (Atomic Read/Write CSR).
126
 *
127
 *   Instruction atomically swaps values in the CSRs and integer registers.
128
 * CSRRW reads the old value of the CSR, zero-extends the value to XLEN bits,
129
 * then writes it to integer register rd. The initial value in rs1 is written
130
 * to the CSR.
131
 *   The CSRW pseudo instruction (write CSR), when rs1 = 0.
132
 */
133 4 sergeykhbr
class CSRRW : public RiscvInstruction {
134 2 sergeykhbr
public:
135 4 sergeykhbr
    CSRRW(CpuRiver_Functional *icpu) :
136
        RiscvInstruction(icpu, "CSRRW", "?????????????????001?????1110011") {}
137 2 sergeykhbr
 
138 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
139 2 sergeykhbr
        ISA_I_type u;
140 4 sergeykhbr
        u.value = payload->buf32[0];
141 2 sergeykhbr
 
142 4 sergeykhbr
        uint64_t wr_value = R[u.bits.rs1];
143 2 sergeykhbr
        if (u.bits.rd) {
144 4 sergeykhbr
            R[u.bits.rd] = icpu_->readCSR(u.bits.imm);
145 2 sergeykhbr
        }
146 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, wr_value);
147
        return 4;
148 2 sergeykhbr
    }
149
};
150
 
151
/**
152
 * @brief The CSRRWI (Atomic Read/Write CSR immediate).
153
 *
154
 * Similar to CSRRW except it updates the CSR using a 5-bit zero-extended
155
 * immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
156
 * an integer register.
157
 */
158 4 sergeykhbr
class CSRRWI : public RiscvInstruction {
159 2 sergeykhbr
public:
160 4 sergeykhbr
    CSRRWI(CpuRiver_Functional *icpu) :
161
        RiscvInstruction(icpu, "CSRRWI", "?????????????????101?????1110011") {}
162 2 sergeykhbr
 
163 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
164 2 sergeykhbr
        ISA_I_type u;
165 4 sergeykhbr
        u.value = payload->buf32[0];
166 2 sergeykhbr
 
167
        uint64_t wr_value = u.bits.rs1;
168
        if (u.bits.rd) {
169 4 sergeykhbr
            R[u.bits.rd] = icpu_->readCSR(u.bits.imm);
170 2 sergeykhbr
        }
171 4 sergeykhbr
        icpu_->writeCSR(u.bits.imm, wr_value);
172
        return 4;
173 2 sergeykhbr
    }
174
};
175
 
176
/**
177
 * @brief MRET, HRET, SRET, or URET
178
 *
179
 * These instructions are used to return from traps in M-mode, Hmode,
180
 * S-mode, or U-mode respectively. When executing an xRET instruction,
181
 * supposing x PP holds the value y, y IE is set to x PIE; the privilege
182
 * mode is changed to y; x PIE is set to 1; and x PP is set to U
183
 * (or M if user-mode is not supported).
184
 *
185
 * User-level interrupts are an optional extension and have been allocated
186
 * the ISA extension letter N. If user-level interrupts are omitted, the UIE
187
 * and UPIE bits are hardwired to zero. For all other supported privilege
188
 * modes x, the x IE, x PIE, and x PP fields are required to be implemented.
189
 */
190 4 sergeykhbr
class URET : public RiscvInstruction {
191 2 sergeykhbr
public:
192 4 sergeykhbr
    URET(CpuRiver_Functional *icpu) :
193
        RiscvInstruction(icpu, "URET", "00000000001000000000000001110011") {}
194 2 sergeykhbr
 
195 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
196
        if (icpu_->getPrvLevel() != PRV_U) {
197
            icpu_->raiseSignal(EXCEPTION_InstrIllegal);
198
            return 4;
199 2 sergeykhbr
        }
200
        csr_mstatus_type mstatus;
201 4 sergeykhbr
        mstatus.value = icpu_->readCSR(CSR_mstatus);
202 2 sergeykhbr
 
203
        uint64_t xepc = (PRV_U << 8) + 0x41;
204 4 sergeykhbr
        icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
205 2 sergeykhbr
 
206
        bool is_N_extension = false;
207
        if (is_N_extension) {
208
            mstatus.bits.UIE = mstatus.bits.UPIE;
209
            mstatus.bits.UPIE = 1;
210
            // User mode not changed.
211
        } else {
212
            mstatus.bits.UIE = 0;
213
            mstatus.bits.UPIE = 0;
214
        }
215 4 sergeykhbr
        icpu_->setPrvLevel(PRV_U);
216
        icpu_->writeCSR(CSR_mstatus, mstatus.value);
217
        return 4;
218 2 sergeykhbr
    }
219
};
220
 
221
/**
222
 * @brief SRET return from super-user mode
223
 */
224 4 sergeykhbr
class SRET : public RiscvInstruction {
225 2 sergeykhbr
public:
226 4 sergeykhbr
    SRET(CpuRiver_Functional *icpu) :
227
        RiscvInstruction(icpu, "SRET", "00010000001000000000000001110011") {}
228 2 sergeykhbr
 
229 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
230
        if (icpu_->getPrvLevel() != PRV_S) {
231
            icpu_->raiseSignal(EXCEPTION_InstrIllegal);
232
            return 4;
233 2 sergeykhbr
        }
234
        csr_mstatus_type mstatus;
235 4 sergeykhbr
        mstatus.value = icpu_->readCSR(CSR_mstatus);
236 2 sergeykhbr
 
237
        uint64_t xepc = (PRV_S << 8) + 0x41;
238 4 sergeykhbr
        icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
239 2 sergeykhbr
 
240
        mstatus.bits.SIE = mstatus.bits.SPIE;
241
        mstatus.bits.SPIE = 1;
242 4 sergeykhbr
        icpu_->setPrvLevel(mstatus.bits.SPP);
243 2 sergeykhbr
        mstatus.bits.SPP = PRV_U;
244
 
245 4 sergeykhbr
        icpu_->writeCSR(CSR_mstatus, mstatus.value);
246
        return 4;
247 2 sergeykhbr
    }
248
};
249
 
250
/**
251
 * @brief HRET return from hypervisor mode
252
 */
253 4 sergeykhbr
class HRET : public RiscvInstruction {
254 2 sergeykhbr
public:
255 4 sergeykhbr
    HRET(CpuRiver_Functional *icpu) :
256
        RiscvInstruction(icpu, "HRET", "00100000001000000000000001110011") {}
257 2 sergeykhbr
 
258 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
259
        if (icpu_->getPrvLevel() != PRV_H) {
260
            icpu_->raiseSignal(EXCEPTION_InstrIllegal);
261
            return 4;
262 2 sergeykhbr
        }
263
        csr_mstatus_type mstatus;
264 4 sergeykhbr
        mstatus.value = icpu_->readCSR(CSR_mstatus);
265 2 sergeykhbr
 
266
        uint64_t xepc = (PRV_H << 8) + 0x41;
267 4 sergeykhbr
        icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
268 2 sergeykhbr
 
269
        mstatus.bits.HIE = mstatus.bits.HPIE;
270
        mstatus.bits.HPIE = 1;
271 4 sergeykhbr
        icpu_->setPrvLevel(mstatus.bits.HPP);
272 2 sergeykhbr
        mstatus.bits.HPP = PRV_U;
273
 
274 4 sergeykhbr
        icpu_->writeCSR(CSR_mstatus, mstatus.value);
275
        return 4;
276 2 sergeykhbr
    }
277
};
278
 
279
/**
280
 * @brief MRET return from machine mode
281
 */
282 4 sergeykhbr
class MRET : public RiscvInstruction {
283 2 sergeykhbr
public:
284 4 sergeykhbr
    MRET(CpuRiver_Functional *icpu) :
285
        RiscvInstruction(icpu, "MRET", "00110000001000000000000001110011") {}
286 2 sergeykhbr
 
287 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
288
        if (icpu_->getPrvLevel() != PRV_M) {
289
            icpu_->raiseSignal(EXCEPTION_InstrIllegal);
290
            return 4;
291 2 sergeykhbr
        }
292
        csr_mstatus_type mstatus;
293 4 sergeykhbr
        mstatus.value = icpu_->readCSR(CSR_mstatus);
294 2 sergeykhbr
 
295
        uint64_t xepc = (PRV_M << 8) + 0x41;
296 4 sergeykhbr
        icpu_->setBranch(icpu_->readCSR(static_cast<uint32_t>(xepc)));
297 2 sergeykhbr
 
298
        mstatus.bits.MIE = mstatus.bits.MPIE;
299
        mstatus.bits.MPIE = 1;
300 4 sergeykhbr
        icpu_->setPrvLevel(mstatus.bits.MPP);
301 2 sergeykhbr
        mstatus.bits.MPP = PRV_U;
302
 
303 4 sergeykhbr
        icpu_->writeCSR(CSR_mstatus, mstatus.value);
304
        return 4;
305 2 sergeykhbr
    }
306
};
307
 
308
 
309
/**
310
 * @brief FENCE (memory barrier)
311
 *
312
 * Not used in functional model so that cache is not modeling.
313
 */
314 4 sergeykhbr
class FENCE : public RiscvInstruction {
315 2 sergeykhbr
public:
316 4 sergeykhbr
    FENCE(CpuRiver_Functional *icpu) :
317
        RiscvInstruction(icpu, "FENCE", "?????????????????000?????0001111") {}
318 2 sergeykhbr
 
319 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
320
        return 4;
321 2 sergeykhbr
    }
322
};
323
 
324
/**
325
 * @brief FENCE_I (memory barrier)
326
 *
327
 * Not used in functional model so that cache is not modeling.
328
 */
329 4 sergeykhbr
class FENCE_I : public RiscvInstruction {
330 2 sergeykhbr
public:
331 4 sergeykhbr
    FENCE_I(CpuRiver_Functional *icpu) :
332
        RiscvInstruction(icpu, "FENCE_I", "?????????????????001?????0001111") {}
333 2 sergeykhbr
 
334 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
335
        return 4;
336 2 sergeykhbr
    }
337
};
338
 
339
/**
340
 * @brief EBREAK (breakpoint instruction)
341
 *
342
 * The EBREAK instruction is used by debuggers to cause control to be
343
 * transferred back to a debug-ging environment.
344
 */
345 4 sergeykhbr
class EBREAK : public RiscvInstruction {
346 2 sergeykhbr
public:
347 4 sergeykhbr
    EBREAK(CpuRiver_Functional *icpu) :
348
        RiscvInstruction(icpu, "EBREAK", "00000000000100000000000001110011") {}
349 2 sergeykhbr
 
350 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
351
        icpu_->raiseSignal(EXCEPTION_Breakpoint);
352
        return 4;
353 2 sergeykhbr
    }
354
};
355
 
356
/**
357
 * @brief ECALL (environment call instruction)
358
 *
359
 * The ECALL instruction is used to make a request to the supporting execution
360
 * environment, which isusually an operating system. The ABI for the system
361
 * will define how parameters for the environment request are passed, but usually
362
 * these will be in defined locations in the integer register file.
363
 */
364 4 sergeykhbr
class ECALL : public RiscvInstruction {
365 2 sergeykhbr
public:
366 4 sergeykhbr
    ECALL(CpuRiver_Functional *icpu) :
367
        RiscvInstruction(icpu, "ECALL", "00000000000000000000000001110011") {}
368 2 sergeykhbr
 
369 4 sergeykhbr
    virtual int exec(Reg64Type *payload) {
370
        switch (icpu_->getPrvLevel()) {
371 2 sergeykhbr
        case PRV_M:
372 4 sergeykhbr
            icpu_->raiseSignal(EXCEPTION_CallFromMmode);
373 2 sergeykhbr
            break;
374
        case PRV_U:
375 4 sergeykhbr
            icpu_->raiseSignal(EXCEPTION_CallFromUmode);
376 2 sergeykhbr
            break;
377
        default:;
378
        }
379 4 sergeykhbr
        return 4;
380 2 sergeykhbr
    }
381
};
382
 
383
 
384 4 sergeykhbr
void CpuRiver_Functional::addIsaPrivilegedRV64I() {
385
    addSupportedInstruction(new CSRRC(this));
386
    addSupportedInstruction(new CSRRCI(this));
387
    addSupportedInstruction(new CSRRS(this));
388
    addSupportedInstruction(new CSRRSI(this));
389
    addSupportedInstruction(new CSRRW(this));
390
    addSupportedInstruction(new CSRRWI(this));
391
    addSupportedInstruction(new URET(this));
392
    addSupportedInstruction(new SRET(this));
393
    addSupportedInstruction(new HRET(this));
394
    addSupportedInstruction(new MRET(this));
395
    addSupportedInstruction(new FENCE(this));
396
    addSupportedInstruction(new FENCE_I(this));
397
    addSupportedInstruction(new ECALL(this));
398
    addSupportedInstruction(new EBREAK(this));
399
 
400 2 sergeykhbr
    // TODO:
401
    /*
402
  def DRET               = BitPat("b01111011001000000000000001110011")
403 4 sergeykhbr
  def SFENCE_VMA         = BitPat("b0001001??????????000000001110011")
404 2 sergeykhbr
  def WFI                = BitPat("b00010000010100000000000001110011")  // wait for interrupt
405
 
406
    def RDCYCLE            = BitPat("b11000000000000000010?????1110011")
407
    def RDTIME             = BitPat("b11000000000100000010?????1110011")
408
    def RDINSTRET          = BitPat("b11000000001000000010?????1110011")
409
    def RDCYCLEH           = BitPat("b11001000000000000010?????1110011")
410
    def RDTIMEH            = BitPat("b11001000000100000010?????1110011")
411
    def RDINSTRETH         = BitPat("b11001000001000000010?????1110011")
412
    */
413
 
414
    /**
415
     * The 'U', 'S', and 'H' bits will be set if there is support for
416
     * user, supervisor, and hypervisor privilege modes respectively.
417
     */
418 4 sergeykhbr
    uint64_t isa = portCSR_.read(CSR_misa).val;
419
    isa |= (1LL << ('U' - 'A'));
420
    isa |= (1LL << ('S' - 'A'));
421
    isa |= (1LL << ('H' - 'A'));
422
    portCSR_.write(CSR_misa, isa);
423 2 sergeykhbr
}
424
 
425
}  // namespace debugger

powered by: WebSVN 2.1.0

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