misc: Merge branch 'release-staging-v20.0.0.0' into develop
[gem5.git] / src / arch / riscv / isa.cc
1 /*
2 * Copyright (c) 2016 RISC-V Foundation
3 * Copyright (c) 2016 The University of Virginia
4 * Copyright (c) 2020 Barkhausen Institut
5 * All rights reserved.
6 *
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.
17 *
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.
29 */
30
31 #include "arch/riscv/isa.hh"
32
33 #include <ctime>
34 #include <set>
35 #include <sstream>
36
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 "base/compiler.hh"
42 #include "cpu/base.hh"
43 #include "debug/Checkpoint.hh"
44 #include "debug/RiscvMisc.hh"
45 #include "params/RiscvISA.hh"
46 #include "sim/core.hh"
47 #include "sim/pseudo_inst.hh"
48
49 namespace RiscvISA
50 {
51
52 const std::array<const char *, NumMiscRegs> M5_VAR_USED MiscRegNames = {{
53 [MISCREG_PRV] = "PRV",
54 [MISCREG_ISA] = "ISA",
55 [MISCREG_VENDORID] = "VENDORID",
56 [MISCREG_ARCHID] = "ARCHID",
57 [MISCREG_IMPID] = "IMPID",
58 [MISCREG_HARTID] = "HARTID",
59 [MISCREG_STATUS] = "STATUS",
60 [MISCREG_IP] = "IP",
61 [MISCREG_IE] = "IE",
62 [MISCREG_CYCLE] = "CYCLE",
63 [MISCREG_TIME] = "TIME",
64 [MISCREG_INSTRET] = "INSTRET",
65 [MISCREG_HPMCOUNTER03] = "HPMCOUNTER03",
66 [MISCREG_HPMCOUNTER04] = "HPMCOUNTER04",
67 [MISCREG_HPMCOUNTER05] = "HPMCOUNTER05",
68 [MISCREG_HPMCOUNTER06] = "HPMCOUNTER06",
69 [MISCREG_HPMCOUNTER07] = "HPMCOUNTER07",
70 [MISCREG_HPMCOUNTER08] = "HPMCOUNTER08",
71 [MISCREG_HPMCOUNTER09] = "HPMCOUNTER09",
72 [MISCREG_HPMCOUNTER10] = "HPMCOUNTER10",
73 [MISCREG_HPMCOUNTER11] = "HPMCOUNTER11",
74 [MISCREG_HPMCOUNTER12] = "HPMCOUNTER12",
75 [MISCREG_HPMCOUNTER13] = "HPMCOUNTER13",
76 [MISCREG_HPMCOUNTER14] = "HPMCOUNTER14",
77 [MISCREG_HPMCOUNTER15] = "HPMCOUNTER15",
78 [MISCREG_HPMCOUNTER16] = "HPMCOUNTER16",
79 [MISCREG_HPMCOUNTER17] = "HPMCOUNTER17",
80 [MISCREG_HPMCOUNTER18] = "HPMCOUNTER18",
81 [MISCREG_HPMCOUNTER19] = "HPMCOUNTER19",
82 [MISCREG_HPMCOUNTER20] = "HPMCOUNTER20",
83 [MISCREG_HPMCOUNTER21] = "HPMCOUNTER21",
84 [MISCREG_HPMCOUNTER22] = "HPMCOUNTER22",
85 [MISCREG_HPMCOUNTER23] = "HPMCOUNTER23",
86 [MISCREG_HPMCOUNTER24] = "HPMCOUNTER24",
87 [MISCREG_HPMCOUNTER25] = "HPMCOUNTER25",
88 [MISCREG_HPMCOUNTER26] = "HPMCOUNTER26",
89 [MISCREG_HPMCOUNTER27] = "HPMCOUNTER27",
90 [MISCREG_HPMCOUNTER28] = "HPMCOUNTER28",
91 [MISCREG_HPMCOUNTER29] = "HPMCOUNTER29",
92 [MISCREG_HPMCOUNTER30] = "HPMCOUNTER30",
93 [MISCREG_HPMCOUNTER31] = "HPMCOUNTER31",
94 [MISCREG_HPMEVENT03] = "HPMEVENT03",
95 [MISCREG_HPMEVENT04] = "HPMEVENT04",
96 [MISCREG_HPMEVENT05] = "HPMEVENT05",
97 [MISCREG_HPMEVENT06] = "HPMEVENT06",
98 [MISCREG_HPMEVENT07] = "HPMEVENT07",
99 [MISCREG_HPMEVENT08] = "HPMEVENT08",
100 [MISCREG_HPMEVENT09] = "HPMEVENT09",
101 [MISCREG_HPMEVENT10] = "HPMEVENT10",
102 [MISCREG_HPMEVENT11] = "HPMEVENT11",
103 [MISCREG_HPMEVENT12] = "HPMEVENT12",
104 [MISCREG_HPMEVENT13] = "HPMEVENT13",
105 [MISCREG_HPMEVENT14] = "HPMEVENT14",
106 [MISCREG_HPMEVENT15] = "HPMEVENT15",
107 [MISCREG_HPMEVENT16] = "HPMEVENT16",
108 [MISCREG_HPMEVENT17] = "HPMEVENT17",
109 [MISCREG_HPMEVENT18] = "HPMEVENT18",
110 [MISCREG_HPMEVENT19] = "HPMEVENT19",
111 [MISCREG_HPMEVENT20] = "HPMEVENT20",
112 [MISCREG_HPMEVENT21] = "HPMEVENT21",
113 [MISCREG_HPMEVENT22] = "HPMEVENT22",
114 [MISCREG_HPMEVENT23] = "HPMEVENT23",
115 [MISCREG_HPMEVENT24] = "HPMEVENT24",
116 [MISCREG_HPMEVENT25] = "HPMEVENT25",
117 [MISCREG_HPMEVENT26] = "HPMEVENT26",
118 [MISCREG_HPMEVENT27] = "HPMEVENT27",
119 [MISCREG_HPMEVENT28] = "HPMEVENT28",
120 [MISCREG_HPMEVENT29] = "HPMEVENT29",
121 [MISCREG_HPMEVENT30] = "HPMEVENT30",
122 [MISCREG_HPMEVENT31] = "HPMEVENT31",
123 [MISCREG_TSELECT] = "TSELECT",
124 [MISCREG_TDATA1] = "TDATA1",
125 [MISCREG_TDATA2] = "TDATA2",
126 [MISCREG_TDATA3] = "TDATA3",
127 [MISCREG_DCSR] = "DCSR",
128 [MISCREG_DPC] = "DPC",
129 [MISCREG_DSCRATCH] = "DSCRATCH",
130
131 [MISCREG_MEDELEG] = "MEDELEG",
132 [MISCREG_MIDELEG] = "MIDELEG",
133 [MISCREG_MTVEC] = "MTVEC",
134 [MISCREG_MCOUNTEREN] = "MCOUNTEREN",
135 [MISCREG_MSCRATCH] = "MSCRATCH",
136 [MISCREG_MEPC] = "MEPC",
137 [MISCREG_MCAUSE] = "MCAUSE",
138 [MISCREG_MTVAL] = "MTVAL",
139 [MISCREG_PMPCFG0] = "PMPCFG0",
140 // pmpcfg1 rv32 only
141 [MISCREG_PMPCFG2] = "PMPCFG2",
142 // pmpcfg3 rv32 only
143 [MISCREG_PMPADDR00] = "PMPADDR00",
144 [MISCREG_PMPADDR01] = "PMPADDR01",
145 [MISCREG_PMPADDR02] = "PMPADDR02",
146 [MISCREG_PMPADDR03] = "PMPADDR03",
147 [MISCREG_PMPADDR04] = "PMPADDR04",
148 [MISCREG_PMPADDR05] = "PMPADDR05",
149 [MISCREG_PMPADDR06] = "PMPADDR06",
150 [MISCREG_PMPADDR07] = "PMPADDR07",
151 [MISCREG_PMPADDR08] = "PMPADDR08",
152 [MISCREG_PMPADDR09] = "PMPADDR09",
153 [MISCREG_PMPADDR10] = "PMPADDR10",
154 [MISCREG_PMPADDR11] = "PMPADDR11",
155 [MISCREG_PMPADDR12] = "PMPADDR12",
156 [MISCREG_PMPADDR13] = "PMPADDR13",
157 [MISCREG_PMPADDR14] = "PMPADDR14",
158 [MISCREG_PMPADDR15] = "PMPADDR15",
159
160 [MISCREG_SEDELEG] = "SEDELEG",
161 [MISCREG_SIDELEG] = "SIDELEG",
162 [MISCREG_STVEC] = "STVEC",
163 [MISCREG_SCOUNTEREN] = "SCOUNTEREN",
164 [MISCREG_SSCRATCH] = "SSCRATCH",
165 [MISCREG_SEPC] = "SEPC",
166 [MISCREG_SCAUSE] = "SCAUSE",
167 [MISCREG_STVAL] = "STVAL",
168 [MISCREG_SATP] = "SATP",
169
170 [MISCREG_UTVEC] = "UTVEC",
171 [MISCREG_USCRATCH] = "USCRATCH",
172 [MISCREG_UEPC] = "UEPC",
173 [MISCREG_UCAUSE] = "UCAUSE",
174 [MISCREG_UTVAL] = "UTVAL",
175 [MISCREG_FFLAGS] = "FFLAGS",
176 [MISCREG_FRM] = "FRM",
177 }};
178
179 ISA::ISA(Params *p) : BaseISA(p)
180 {
181 miscRegFile.resize(NumMiscRegs);
182 clear();
183 }
184
185 const RiscvISAParams *
186 ISA::params() const
187 {
188 return dynamic_cast<const Params *>(_params);
189 }
190
191 void ISA::clear()
192 {
193 std::fill(miscRegFile.begin(), miscRegFile.end(), 0);
194
195 miscRegFile[MISCREG_PRV] = PRV_M;
196 miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSET) | 0x14112D;
197 miscRegFile[MISCREG_VENDORID] = 0;
198 miscRegFile[MISCREG_ARCHID] = 0;
199 miscRegFile[MISCREG_IMPID] = 0;
200 miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) | (2ULL << SXL_OFFSET) |
201 (1ULL << FS_OFFSET);
202 miscRegFile[MISCREG_MCOUNTEREN] = 0x7;
203 miscRegFile[MISCREG_SCOUNTEREN] = 0x7;
204 // don't set it to zero; software may try to determine the supported
205 // triggers, starting at zero. simply set a different value here.
206 miscRegFile[MISCREG_TSELECT] = 1;
207 }
208
209 bool
210 ISA::hpmCounterEnabled(int misc_reg) const
211 {
212 int hpmcounter = misc_reg - MISCREG_CYCLE;
213 if (hpmcounter < 0 || hpmcounter > 31)
214 panic("Illegal HPM counter %d\n", hpmcounter);
215 int counteren;
216 switch (readMiscRegNoEffect(MISCREG_PRV)) {
217 case PRV_M:
218 return true;
219 case PRV_S:
220 counteren = MISCREG_MCOUNTEREN;
221 break;
222 case PRV_U:
223 counteren = MISCREG_SCOUNTEREN;
224 break;
225 default:
226 panic("Unknown privilege level %d\n", miscRegFile[MISCREG_PRV]);
227 return false;
228 }
229 return (miscRegFile[counteren] & (1ULL << (hpmcounter))) > 0;
230 }
231
232 RegVal
233 ISA::readMiscRegNoEffect(int misc_reg) const
234 {
235 if (misc_reg > NumMiscRegs || misc_reg < 0) {
236 // Illegal CSR
237 panic("Illegal CSR index %#x\n", misc_reg);
238 return -1;
239 }
240 DPRINTF(RiscvMisc, "Reading MiscReg %s (%d): %#x.\n",
241 MiscRegNames[misc_reg], misc_reg, miscRegFile[misc_reg]);
242 return miscRegFile[misc_reg];
243 }
244
245 RegVal
246 ISA::readMiscReg(int misc_reg, ThreadContext *tc)
247 {
248 switch (misc_reg) {
249 case MISCREG_HARTID:
250 return tc->contextId();
251 case MISCREG_CYCLE:
252 if (hpmCounterEnabled(MISCREG_CYCLE)) {
253 DPRINTF(RiscvMisc, "Cycle counter at: %llu.\n",
254 tc->getCpuPtr()->curCycle());
255 return tc->getCpuPtr()->curCycle();
256 } else {
257 warn("Cycle counter disabled.\n");
258 return 0;
259 }
260 case MISCREG_TIME:
261 if (hpmCounterEnabled(MISCREG_TIME)) {
262 DPRINTF(RiscvMisc, "Wall-clock counter at: %llu.\n",
263 std::time(nullptr));
264 return std::time(nullptr);
265 } else {
266 warn("Wall clock disabled.\n");
267 return 0;
268 }
269 case MISCREG_INSTRET:
270 if (hpmCounterEnabled(MISCREG_INSTRET)) {
271 DPRINTF(RiscvMisc, "Instruction counter at: %llu.\n",
272 tc->getCpuPtr()->totalInsts());
273 return tc->getCpuPtr()->totalInsts();
274 } else {
275 warn("Instruction counter disabled.\n");
276 return 0;
277 }
278 case MISCREG_IP:
279 {
280 auto ic = dynamic_cast<RiscvISA::Interrupts *>(
281 tc->getCpuPtr()->getInterruptController(tc->threadId()));
282 return ic->readIP();
283 }
284 case MISCREG_IE:
285 {
286 auto ic = dynamic_cast<RiscvISA::Interrupts *>(
287 tc->getCpuPtr()->getInterruptController(tc->threadId()));
288 return ic->readIE();
289 }
290 case MISCREG_SEPC:
291 case MISCREG_MEPC:
292 {
293 auto misa = readMiscRegNoEffect(MISCREG_ISA);
294 auto val = readMiscRegNoEffect(misc_reg);
295 // if compressed instructions are disabled, epc[1] is set to 0
296 if ((misa & ISA_EXT_C_MASK) == 0)
297 return mbits(val, 63, 2);
298 // epc[0] is always 0
299 else
300 return mbits(val, 63, 1);
301 }
302 default:
303 // Try reading HPM counters
304 // As a placeholder, all HPM counters are just cycle counters
305 if (misc_reg >= MISCREG_HPMCOUNTER03 &&
306 misc_reg <= MISCREG_HPMCOUNTER31) {
307 if (hpmCounterEnabled(misc_reg)) {
308 DPRINTF(RiscvMisc, "HPM counter %d: %llu.\n",
309 misc_reg - MISCREG_CYCLE, tc->getCpuPtr()->curCycle());
310 return tc->getCpuPtr()->curCycle();
311 } else {
312 warn("HPM counter %d disabled.\n", misc_reg - MISCREG_CYCLE);
313 return 0;
314 }
315 }
316 return readMiscRegNoEffect(misc_reg);
317 }
318 }
319
320 void
321 ISA::setMiscRegNoEffect(int misc_reg, RegVal val)
322 {
323 if (misc_reg > NumMiscRegs || misc_reg < 0) {
324 // Illegal CSR
325 panic("Illegal CSR index %#x\n", misc_reg);
326 }
327 DPRINTF(RiscvMisc, "Setting MiscReg %s (%d) to %#x.\n",
328 MiscRegNames[misc_reg], misc_reg, val);
329 miscRegFile[misc_reg] = val;
330 }
331
332 void
333 ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
334 {
335 if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) {
336 // Ignore writes to HPM counters for now
337 warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name);
338 } else {
339 switch (misc_reg) {
340 case MISCREG_IP:
341 {
342 auto ic = dynamic_cast<RiscvISA::Interrupts *>(
343 tc->getCpuPtr()->getInterruptController(tc->threadId()));
344 ic->setIP(val);
345 }
346 break;
347 case MISCREG_IE:
348 {
349 auto ic = dynamic_cast<RiscvISA::Interrupts *>(
350 tc->getCpuPtr()->getInterruptController(tc->threadId()));
351 ic->setIE(val);
352 }
353 break;
354 case MISCREG_SATP:
355 {
356 // we only support bare and Sv39 mode; setting a different mode
357 // shall have no effect (see 4.1.12 in priv ISA manual)
358 SATP cur_val = readMiscRegNoEffect(misc_reg);
359 SATP new_val = val;
360 if (new_val.mode != AddrXlateMode::BARE &&
361 new_val.mode != AddrXlateMode::SV39)
362 new_val.mode = cur_val.mode;
363 setMiscRegNoEffect(misc_reg, new_val);
364 }
365 break;
366 case MISCREG_TSELECT:
367 {
368 // we don't support debugging, so always set a different value
369 // than written
370 setMiscRegNoEffect(misc_reg, val + 1);
371 }
372 break;
373 case MISCREG_ISA:
374 {
375 auto cur_val = readMiscRegNoEffect(misc_reg);
376 // only allow to disable compressed instructions
377 // if the following instruction is 4-byte aligned
378 if ((val & ISA_EXT_C_MASK) == 0 &&
379 bits(tc->pcState().npc(), 2, 0) != 0)
380 val |= cur_val & ISA_EXT_C_MASK;
381 setMiscRegNoEffect(misc_reg, val);
382 }
383 break;
384 case MISCREG_STATUS:
385 {
386 // SXL and UXL are hard-wired to 64 bit
387 auto cur = readMiscRegNoEffect(misc_reg);
388 val &= ~(STATUS_SXL_MASK | STATUS_UXL_MASK);
389 val |= cur & (STATUS_SXL_MASK | STATUS_UXL_MASK);
390 setMiscRegNoEffect(misc_reg, val);
391 }
392 break;
393 default:
394 setMiscRegNoEffect(misc_reg, val);
395 }
396 }
397 }
398
399 void
400 ISA::serialize(CheckpointOut &cp) const
401 {
402 DPRINTF(Checkpoint, "Serializing Riscv Misc Registers\n");
403 SERIALIZE_CONTAINER(miscRegFile);
404 }
405
406 void
407 ISA::unserialize(CheckpointIn &cp)
408 {
409 DPRINTF(Checkpoint, "Unserializing Riscv Misc Registers\n");
410 UNSERIALIZE_CONTAINER(miscRegFile);
411 }
412
413 }
414
415 RiscvISA::ISA *
416 RiscvISAParams::create()
417 {
418 return new RiscvISA::ISA(this);
419 }