2 * Copyright (c) 2016 RISC-V Foundation
3 * Copyright (c) 2016 The University of Virginia
4 * Copyright (c) 2020 Barkhausen Institut
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "arch/riscv/isa.hh"
37 #include "arch/riscv/interrupts.hh"
38 #include "arch/riscv/pagetable.hh"
39 #include "arch/riscv/registers.hh"
40 #include "base/bitfield.hh"
41 #include "cpu/base.hh"
42 #include "debug/Checkpoint.hh"
43 #include "debug/RiscvMisc.hh"
44 #include "params/RiscvISA.hh"
45 #include "sim/core.hh"
46 #include "sim/pseudo_inst.hh"
51 const std::array
<const char *, NumMiscRegs
> MiscRegNames
= {{
52 [MISCREG_PRV
] = "PRV",
53 [MISCREG_ISA
] = "ISA",
54 [MISCREG_VENDORID
] = "VENDORID",
55 [MISCREG_ARCHID
] = "ARCHID",
56 [MISCREG_IMPID
] = "IMPID",
57 [MISCREG_HARTID
] = "HARTID",
58 [MISCREG_STATUS
] = "STATUS",
61 [MISCREG_CYCLE
] = "CYCLE",
62 [MISCREG_TIME
] = "TIME",
63 [MISCREG_INSTRET
] = "INSTRET",
64 [MISCREG_HPMCOUNTER03
] = "HPMCOUNTER03",
65 [MISCREG_HPMCOUNTER04
] = "HPMCOUNTER04",
66 [MISCREG_HPMCOUNTER05
] = "HPMCOUNTER05",
67 [MISCREG_HPMCOUNTER06
] = "HPMCOUNTER06",
68 [MISCREG_HPMCOUNTER07
] = "HPMCOUNTER07",
69 [MISCREG_HPMCOUNTER08
] = "HPMCOUNTER08",
70 [MISCREG_HPMCOUNTER09
] = "HPMCOUNTER09",
71 [MISCREG_HPMCOUNTER10
] = "HPMCOUNTER10",
72 [MISCREG_HPMCOUNTER11
] = "HPMCOUNTER11",
73 [MISCREG_HPMCOUNTER12
] = "HPMCOUNTER12",
74 [MISCREG_HPMCOUNTER13
] = "HPMCOUNTER13",
75 [MISCREG_HPMCOUNTER14
] = "HPMCOUNTER14",
76 [MISCREG_HPMCOUNTER15
] = "HPMCOUNTER15",
77 [MISCREG_HPMCOUNTER16
] = "HPMCOUNTER16",
78 [MISCREG_HPMCOUNTER17
] = "HPMCOUNTER17",
79 [MISCREG_HPMCOUNTER18
] = "HPMCOUNTER18",
80 [MISCREG_HPMCOUNTER19
] = "HPMCOUNTER19",
81 [MISCREG_HPMCOUNTER20
] = "HPMCOUNTER20",
82 [MISCREG_HPMCOUNTER21
] = "HPMCOUNTER21",
83 [MISCREG_HPMCOUNTER22
] = "HPMCOUNTER22",
84 [MISCREG_HPMCOUNTER23
] = "HPMCOUNTER23",
85 [MISCREG_HPMCOUNTER24
] = "HPMCOUNTER24",
86 [MISCREG_HPMCOUNTER25
] = "HPMCOUNTER25",
87 [MISCREG_HPMCOUNTER26
] = "HPMCOUNTER26",
88 [MISCREG_HPMCOUNTER27
] = "HPMCOUNTER27",
89 [MISCREG_HPMCOUNTER28
] = "HPMCOUNTER28",
90 [MISCREG_HPMCOUNTER29
] = "HPMCOUNTER29",
91 [MISCREG_HPMCOUNTER30
] = "HPMCOUNTER30",
92 [MISCREG_HPMCOUNTER31
] = "HPMCOUNTER31",
93 [MISCREG_HPMEVENT03
] = "HPMEVENT03",
94 [MISCREG_HPMEVENT04
] = "HPMEVENT04",
95 [MISCREG_HPMEVENT05
] = "HPMEVENT05",
96 [MISCREG_HPMEVENT06
] = "HPMEVENT06",
97 [MISCREG_HPMEVENT07
] = "HPMEVENT07",
98 [MISCREG_HPMEVENT08
] = "HPMEVENT08",
99 [MISCREG_HPMEVENT09
] = "HPMEVENT09",
100 [MISCREG_HPMEVENT10
] = "HPMEVENT10",
101 [MISCREG_HPMEVENT11
] = "HPMEVENT11",
102 [MISCREG_HPMEVENT12
] = "HPMEVENT12",
103 [MISCREG_HPMEVENT13
] = "HPMEVENT13",
104 [MISCREG_HPMEVENT14
] = "HPMEVENT14",
105 [MISCREG_HPMEVENT15
] = "HPMEVENT15",
106 [MISCREG_HPMEVENT16
] = "HPMEVENT16",
107 [MISCREG_HPMEVENT17
] = "HPMEVENT17",
108 [MISCREG_HPMEVENT18
] = "HPMEVENT18",
109 [MISCREG_HPMEVENT19
] = "HPMEVENT19",
110 [MISCREG_HPMEVENT20
] = "HPMEVENT20",
111 [MISCREG_HPMEVENT21
] = "HPMEVENT21",
112 [MISCREG_HPMEVENT22
] = "HPMEVENT22",
113 [MISCREG_HPMEVENT23
] = "HPMEVENT23",
114 [MISCREG_HPMEVENT24
] = "HPMEVENT24",
115 [MISCREG_HPMEVENT25
] = "HPMEVENT25",
116 [MISCREG_HPMEVENT26
] = "HPMEVENT26",
117 [MISCREG_HPMEVENT27
] = "HPMEVENT27",
118 [MISCREG_HPMEVENT28
] = "HPMEVENT28",
119 [MISCREG_HPMEVENT29
] = "HPMEVENT29",
120 [MISCREG_HPMEVENT30
] = "HPMEVENT30",
121 [MISCREG_HPMEVENT31
] = "HPMEVENT31",
122 [MISCREG_TSELECT
] = "TSELECT",
123 [MISCREG_TDATA1
] = "TDATA1",
124 [MISCREG_TDATA2
] = "TDATA2",
125 [MISCREG_TDATA3
] = "TDATA3",
126 [MISCREG_DCSR
] = "DCSR",
127 [MISCREG_DPC
] = "DPC",
128 [MISCREG_DSCRATCH
] = "DSCRATCH",
130 [MISCREG_MEDELEG
] = "MEDELEG",
131 [MISCREG_MIDELEG
] = "MIDELEG",
132 [MISCREG_MTVEC
] = "MTVEC",
133 [MISCREG_MCOUNTEREN
] = "MCOUNTEREN",
134 [MISCREG_MSCRATCH
] = "MSCRATCH",
135 [MISCREG_MEPC
] = "MEPC",
136 [MISCREG_MCAUSE
] = "MCAUSE",
137 [MISCREG_MTVAL
] = "MTVAL",
138 [MISCREG_PMPCFG0
] = "PMPCFG0",
140 [MISCREG_PMPCFG2
] = "PMPCFG2",
142 [MISCREG_PMPADDR00
] = "PMPADDR00",
143 [MISCREG_PMPADDR01
] = "PMPADDR01",
144 [MISCREG_PMPADDR02
] = "PMPADDR02",
145 [MISCREG_PMPADDR03
] = "PMPADDR03",
146 [MISCREG_PMPADDR04
] = "PMPADDR04",
147 [MISCREG_PMPADDR05
] = "PMPADDR05",
148 [MISCREG_PMPADDR06
] = "PMPADDR06",
149 [MISCREG_PMPADDR07
] = "PMPADDR07",
150 [MISCREG_PMPADDR08
] = "PMPADDR08",
151 [MISCREG_PMPADDR09
] = "PMPADDR09",
152 [MISCREG_PMPADDR10
] = "PMPADDR10",
153 [MISCREG_PMPADDR11
] = "PMPADDR11",
154 [MISCREG_PMPADDR12
] = "PMPADDR12",
155 [MISCREG_PMPADDR13
] = "PMPADDR13",
156 [MISCREG_PMPADDR14
] = "PMPADDR14",
157 [MISCREG_PMPADDR15
] = "PMPADDR15",
159 [MISCREG_SEDELEG
] = "SEDELEG",
160 [MISCREG_SIDELEG
] = "SIDELEG",
161 [MISCREG_STVEC
] = "STVEC",
162 [MISCREG_SCOUNTEREN
] = "SCOUNTEREN",
163 [MISCREG_SSCRATCH
] = "SSCRATCH",
164 [MISCREG_SEPC
] = "SEPC",
165 [MISCREG_SCAUSE
] = "SCAUSE",
166 [MISCREG_STVAL
] = "STVAL",
167 [MISCREG_SATP
] = "SATP",
169 [MISCREG_UTVEC
] = "UTVEC",
170 [MISCREG_USCRATCH
] = "USCRATCH",
171 [MISCREG_UEPC
] = "UEPC",
172 [MISCREG_UCAUSE
] = "UCAUSE",
173 [MISCREG_UTVAL
] = "UTVAL",
174 [MISCREG_FFLAGS
] = "FFLAGS",
175 [MISCREG_FRM
] = "FRM",
178 ISA::ISA(Params
*p
) : BaseISA(p
)
180 miscRegFile
.resize(NumMiscRegs
);
184 const RiscvISAParams
*
187 return dynamic_cast<const Params
*>(_params
);
192 std::fill(miscRegFile
.begin(), miscRegFile
.end(), 0);
194 miscRegFile
[MISCREG_PRV
] = PRV_M
;
195 miscRegFile
[MISCREG_ISA
] = (2ULL << MXL_OFFSET
) | 0x14112D;
196 miscRegFile
[MISCREG_VENDORID
] = 0;
197 miscRegFile
[MISCREG_ARCHID
] = 0;
198 miscRegFile
[MISCREG_IMPID
] = 0;
199 miscRegFile
[MISCREG_STATUS
] = (2ULL << UXL_OFFSET
) | (2ULL << SXL_OFFSET
) |
201 miscRegFile
[MISCREG_MCOUNTEREN
] = 0x7;
202 miscRegFile
[MISCREG_SCOUNTEREN
] = 0x7;
203 // don't set it to zero; software may try to determine the supported
204 // triggers, starting at zero. simply set a different value here.
205 miscRegFile
[MISCREG_TSELECT
] = 1;
209 ISA::hpmCounterEnabled(int misc_reg
) const
211 int hpmcounter
= misc_reg
- MISCREG_CYCLE
;
212 if (hpmcounter
< 0 || hpmcounter
> 31)
213 panic("Illegal HPM counter %d\n", hpmcounter
);
215 switch (readMiscRegNoEffect(MISCREG_PRV
)) {
219 counteren
= MISCREG_MCOUNTEREN
;
222 counteren
= MISCREG_SCOUNTEREN
;
225 panic("Unknown privilege level %d\n", miscRegFile
[MISCREG_PRV
]);
228 return (miscRegFile
[counteren
] & (1ULL << (hpmcounter
))) > 0;
232 ISA::readMiscRegNoEffect(int misc_reg
) const
234 if (misc_reg
> NumMiscRegs
|| misc_reg
< 0) {
236 panic("Illegal CSR index %#x\n", misc_reg
);
239 DPRINTF(RiscvMisc
, "Reading MiscReg %s (%d): %#x.\n",
240 MiscRegNames
[misc_reg
], misc_reg
, miscRegFile
[misc_reg
]);
241 return miscRegFile
[misc_reg
];
245 ISA::readMiscReg(int misc_reg
, ThreadContext
*tc
)
249 return tc
->contextId();
251 if (hpmCounterEnabled(MISCREG_CYCLE
)) {
252 DPRINTF(RiscvMisc
, "Cycle counter at: %llu.\n",
253 tc
->getCpuPtr()->curCycle());
254 return tc
->getCpuPtr()->curCycle();
256 warn("Cycle counter disabled.\n");
260 if (hpmCounterEnabled(MISCREG_TIME
)) {
261 DPRINTF(RiscvMisc
, "Wall-clock counter at: %llu.\n",
263 return std::time(nullptr);
265 warn("Wall clock disabled.\n");
268 case MISCREG_INSTRET
:
269 if (hpmCounterEnabled(MISCREG_INSTRET
)) {
270 DPRINTF(RiscvMisc
, "Instruction counter at: %llu.\n",
271 tc
->getCpuPtr()->totalInsts());
272 return tc
->getCpuPtr()->totalInsts();
274 warn("Instruction counter disabled.\n");
279 auto ic
= dynamic_cast<RiscvISA::Interrupts
*>(
280 tc
->getCpuPtr()->getInterruptController(tc
->threadId()));
285 auto ic
= dynamic_cast<RiscvISA::Interrupts
*>(
286 tc
->getCpuPtr()->getInterruptController(tc
->threadId()));
292 auto misa
= readMiscRegNoEffect(MISCREG_ISA
);
293 auto val
= readMiscRegNoEffect(misc_reg
);
294 // if compressed instructions are disabled, epc[1] is set to 0
295 if ((misa
& ISA_EXT_C_MASK
) == 0)
296 return mbits(val
, 63, 2);
297 // epc[0] is always 0
299 return mbits(val
, 63, 1);
302 // Try reading HPM counters
303 // As a placeholder, all HPM counters are just cycle counters
304 if (misc_reg
>= MISCREG_HPMCOUNTER03
&&
305 misc_reg
<= MISCREG_HPMCOUNTER31
) {
306 if (hpmCounterEnabled(misc_reg
)) {
307 DPRINTF(RiscvMisc
, "HPM counter %d: %llu.\n",
308 misc_reg
- MISCREG_CYCLE
, tc
->getCpuPtr()->curCycle());
309 return tc
->getCpuPtr()->curCycle();
311 warn("HPM counter %d disabled.\n", misc_reg
- MISCREG_CYCLE
);
315 return readMiscRegNoEffect(misc_reg
);
320 ISA::setMiscRegNoEffect(int misc_reg
, RegVal val
)
322 if (misc_reg
> NumMiscRegs
|| misc_reg
< 0) {
324 panic("Illegal CSR index %#x\n", misc_reg
);
326 DPRINTF(RiscvMisc
, "Setting MiscReg %s (%d) to %#x.\n",
327 MiscRegNames
[misc_reg
], misc_reg
, val
);
328 miscRegFile
[misc_reg
] = val
;
332 ISA::setMiscReg(int misc_reg
, RegVal val
, ThreadContext
*tc
)
334 if (misc_reg
>= MISCREG_CYCLE
&& misc_reg
<= MISCREG_HPMCOUNTER31
) {
335 // Ignore writes to HPM counters for now
336 warn("Ignoring write to %s.\n", CSRData
.at(misc_reg
).name
);
341 auto ic
= dynamic_cast<RiscvISA::Interrupts
*>(
342 tc
->getCpuPtr()->getInterruptController(tc
->threadId()));
348 auto ic
= dynamic_cast<RiscvISA::Interrupts
*>(
349 tc
->getCpuPtr()->getInterruptController(tc
->threadId()));
355 // we only support bare and Sv39 mode; setting a different mode
356 // shall have no effect (see 4.1.12 in priv ISA manual)
357 SATP cur_val
= readMiscRegNoEffect(misc_reg
);
359 if (new_val
.mode
!= AddrXlateMode::BARE
&&
360 new_val
.mode
!= AddrXlateMode::SV39
)
361 new_val
.mode
= cur_val
.mode
;
362 setMiscRegNoEffect(misc_reg
, new_val
);
365 case MISCREG_TSELECT
:
367 // we don't support debugging, so always set a different value
369 setMiscRegNoEffect(misc_reg
, val
+ 1);
374 auto cur_val
= readMiscRegNoEffect(misc_reg
);
375 // only allow to disable compressed instructions
376 // if the following instruction is 4-byte aligned
377 if ((val
& ISA_EXT_C_MASK
) == 0 &&
378 bits(tc
->pcState().npc(), 2, 0) != 0)
379 val
|= cur_val
& ISA_EXT_C_MASK
;
380 setMiscRegNoEffect(misc_reg
, val
);
385 // SXL and UXL are hard-wired to 64 bit
386 auto cur
= readMiscRegNoEffect(misc_reg
);
387 val
&= ~(STATUS_SXL_MASK
| STATUS_UXL_MASK
);
388 val
|= cur
& (STATUS_SXL_MASK
| STATUS_UXL_MASK
);
389 setMiscRegNoEffect(misc_reg
, val
);
393 setMiscRegNoEffect(misc_reg
, val
);
399 ISA::serialize(CheckpointOut
&cp
) const
401 DPRINTF(Checkpoint
, "Serializing Riscv Misc Registers\n");
402 SERIALIZE_CONTAINER(miscRegFile
);
406 ISA::unserialize(CheckpointIn
&cp
)
408 DPRINTF(Checkpoint
, "Unserializing Riscv Misc Registers\n");
409 UNSERIALIZE_CONTAINER(miscRegFile
);
415 RiscvISAParams::create()
417 return new RiscvISA::ISA(this);