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

powered by: WebSVN 2.1.0

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