isa.cc revision 11963
1/*
2 * Copyright (c) 2016 RISC-V Foundation
3 * Copyright (c) 2016 The University of Virginia
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Alec Roelke
30 */
31#include "arch/riscv/isa.hh"
32
33#include <ctime>
34#include <set>
35#include <sstream>
36
37#include "arch/riscv/registers.hh"
38#include "base/bitfield.hh"
39#include "cpu/base.hh"
40#include "debug/RiscvMisc.hh"
41#include "params/RiscvISA.hh"
42#include "sim/core.hh"
43#include "sim/pseudo_inst.hh"
44
45namespace RiscvISA
46{
47
48ISA::ISA(Params *p) : SimObject(p)
49{
50    miscRegNames = {
51        {MISCREG_USTATUS, "ustatus"},
52        {MISCREG_UIE, "uie"},
53        {MISCREG_UTVEC, "utvec"},
54        {MISCREG_USCRATCH, "uscratch"},
55        {MISCREG_UEPC, "uepc"},
56        {MISCREG_UCAUSE, "ucause"},
57        {MISCREG_UBADADDR, "ubadaddr"},
58        {MISCREG_UIP, "uip"},
59        {MISCREG_FFLAGS, "fflags"},
60        {MISCREG_FRM, "frm"},
61        {MISCREG_FCSR, "fcsr"},
62        {MISCREG_CYCLE, "cycle"},
63        {MISCREG_TIME, "time"},
64        {MISCREG_INSTRET, "instret"},
65        {MISCREG_CYCLEH, "cycleh"},
66        {MISCREG_TIMEH, "timeh"},
67        {MISCREG_INSTRETH, "instreth"},
68
69        {MISCREG_SSTATUS, "sstatus"},
70        {MISCREG_SEDELEG, "sedeleg"},
71        {MISCREG_SIDELEG, "sideleg"},
72        {MISCREG_SIE, "sie"},
73        {MISCREG_STVEC, "stvec"},
74        {MISCREG_SSCRATCH, "sscratch"},
75        {MISCREG_SEPC, "sepc"},
76        {MISCREG_SCAUSE, "scause"},
77        {MISCREG_SBADADDR, "sbadaddr"},
78        {MISCREG_SIP, "sip"},
79        {MISCREG_SPTBR, "sptbr"},
80
81        {MISCREG_HSTATUS, "hstatus"},
82        {MISCREG_HEDELEG, "hedeleg"},
83        {MISCREG_HIDELEG, "hideleg"},
84        {MISCREG_HIE, "hie"},
85        {MISCREG_HTVEC, "htvec"},
86        {MISCREG_HSCRATCH, "hscratch"},
87        {MISCREG_HEPC, "hepc"},
88        {MISCREG_HCAUSE, "hcause"},
89        {MISCREG_HBADADDR, "hbadaddr"},
90        {MISCREG_HIP, "hip"},
91
92        {MISCREG_MVENDORID, "mvendorid"},
93        {MISCREG_MARCHID, "marchid"},
94        {MISCREG_MIMPID, "mimpid"},
95        {MISCREG_MHARTID, "mhartid"},
96        {MISCREG_MSTATUS, "mstatus"},
97        {MISCREG_MISA, "misa"},
98        {MISCREG_MEDELEG, "medeleg"},
99        {MISCREG_MIDELEG, "mideleg"},
100        {MISCREG_MIE, "mie"},
101        {MISCREG_MTVEC, "mtvec"},
102        {MISCREG_MSCRATCH, "mscratch"},
103        {MISCREG_MEPC, "mepc"},
104        {MISCREG_MCAUSE, "mcause"},
105        {MISCREG_MBADADDR, "mbadaddr"},
106        {MISCREG_MIP, "mip"},
107        {MISCREG_MBASE, "mbase"},
108        {MISCREG_MBOUND, "mbound"},
109        {MISCREG_MIBASE, "mibase"},
110        {MISCREG_MIBOUND, "mibound"},
111        {MISCREG_MDBASE, "mdbase"},
112        {MISCREG_MDBOUND, "mdbound"},
113        {MISCREG_MCYCLE, "mcycle"},
114        {MISCREG_MINSTRET, "minstret"},
115        {MISCREG_MUCOUNTEREN, "mucounteren"},
116        {MISCREG_MSCOUNTEREN, "mscounteren"},
117        {MISCREG_MHCOUNTEREN, "mhcounteren"},
118
119        {MISCREG_TSELECT, "tselect"},
120        {MISCREG_TDATA1, "tdata1"},
121        {MISCREG_TDATA2, "tdata2"},
122        {MISCREG_TDATA3, "tdata3"},
123        {MISCREG_DCSR, "dcsr"},
124        {MISCREG_DPC, "dpc"},
125        {MISCREG_DSCRATCH, "dscratch"}
126    };
127    for (int i = 0; i < NumHpmcounter; i++)
128    {
129        int hpmcounter = MISCREG_HPMCOUNTER_BASE + i;
130        std::stringstream ss;
131        ss << "hpmcounter" << hpmcounter;
132        miscRegNames[hpmcounter] = ss.str();
133    }
134    for (int i = 0; i < NumHpmcounterh; i++)
135    {
136        int hpmcounterh = MISCREG_HPMCOUNTERH_BASE + i;
137        std::stringstream ss;
138        ss << "hpmcounterh" << hpmcounterh;
139        miscRegNames[hpmcounterh] = ss.str();
140    }
141    for (int i = 0; i < NumMhpmcounter; i++)
142    {
143        int mhpmcounter = MISCREG_MHPMCOUNTER_BASE + i;
144        std::stringstream ss;
145        ss << "mhpmcounter" << mhpmcounter;
146        miscRegNames[mhpmcounter] = ss.str();
147    }
148    for (int i = 0; i < NumMhpmevent; i++)
149    {
150        int mhpmevent = MISCREG_MHPMEVENT_BASE + i;
151        std::stringstream ss;
152        ss << "mhpmcounterh" << mhpmevent;
153        miscRegNames[mhpmevent] = ss.str();
154    }
155
156    miscRegFile.resize(NumMiscRegs);
157    clear();
158}
159
160const RiscvISAParams *
161ISA::params() const
162{
163    return dynamic_cast<const Params *>(_params);
164}
165
166void ISA::clear()
167{
168    std::fill(miscRegFile.begin(), miscRegFile.end(), 0);
169
170    miscRegFile[MISCREG_MVENDORID] = 0;
171    miscRegFile[MISCREG_MARCHID] = 0;
172    miscRegFile[MISCREG_MIMPID] = 0;
173    miscRegFile[MISCREG_MISA] = 0x8000000000101129ULL;
174}
175
176
177MiscReg
178ISA::readMiscRegNoEffect(int misc_reg) const
179{
180    DPRINTF(RiscvMisc, "Reading CSR %s (0x%016llx).\n",
181        miscRegNames.at(misc_reg), miscRegFile[misc_reg]);
182    switch (misc_reg) {
183      case MISCREG_FFLAGS:
184        return bits(miscRegFile[MISCREG_FCSR], 4, 0);
185      case MISCREG_FRM:
186        return bits(miscRegFile[MISCREG_FCSR], 7, 5);
187      case MISCREG_FCSR:
188        return bits(miscRegFile[MISCREG_FCSR], 31, 0);
189      case MISCREG_CYCLE:
190        warn("Use readMiscReg to read the cycle CSR.");
191        return 0;
192      case MISCREG_TIME:
193        return std::time(nullptr);
194      case MISCREG_INSTRET:
195        warn("Use readMiscReg to read the instret CSR.");
196        return 0;
197      case MISCREG_CYCLEH:
198        warn("Use readMiscReg to read the cycleh CSR.");
199        return 0;
200      case MISCREG_TIMEH:
201        return std::time(nullptr) >> 32;
202      case MISCREG_INSTRETH:
203        warn("Use readMiscReg to read the instreth CSR.");
204        return 0;
205      case MISCREG_MHARTID:
206        warn("Use readMiscReg to read the mhartid CSR.");
207        return 0;
208      default:
209        return miscRegFile[misc_reg];
210    }
211}
212
213MiscReg
214ISA::readMiscReg(int misc_reg, ThreadContext *tc)
215{
216    switch (misc_reg) {
217      case MISCREG_INSTRET:
218        DPRINTF(RiscvMisc, "Reading CSR %s (0x%016llx).\n",
219            miscRegNames[misc_reg], miscRegFile[misc_reg]);
220        return tc->getCpuPtr()->totalInsts();
221      case MISCREG_CYCLE:
222        DPRINTF(RiscvMisc, "Reading CSR %s (0x%016llx).\n",
223            miscRegNames[misc_reg], miscRegFile[misc_reg]);
224        return tc->getCpuPtr()->curCycle();
225      case MISCREG_INSTRETH:
226        DPRINTF(RiscvMisc, "Reading CSR %s (0x%016llx).\n",
227            miscRegNames[misc_reg], miscRegFile[misc_reg]);
228        return tc->getCpuPtr()->totalInsts() >> 32;
229      case MISCREG_CYCLEH:
230        DPRINTF(RiscvMisc, "Reading CSR %s (0x%016llx).\n",
231            miscRegNames[misc_reg], miscRegFile[misc_reg]);
232        return tc->getCpuPtr()->curCycle() >> 32;
233      case MISCREG_MHARTID:
234        return 0; // TODO: make this the hardware thread or cpu id
235      default:
236        return readMiscRegNoEffect(misc_reg);
237    }
238}
239
240void
241ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
242{
243    DPRINTF(RiscvMisc, "Setting CSR %s to 0x%016llx.\n",
244        miscRegNames[misc_reg], val);
245    switch (misc_reg) {
246      case MISCREG_FFLAGS:
247        miscRegFile[MISCREG_FCSR] &= ~0x1F;
248        miscRegFile[MISCREG_FCSR] |= bits(val, 4, 0);
249        break;
250      case MISCREG_FRM:
251        miscRegFile[MISCREG_FCSR] &= ~0x70;
252        miscRegFile[MISCREG_FCSR] |= bits(val, 2, 0) << 5;
253        break;
254      case MISCREG_FCSR:
255        miscRegFile[MISCREG_FCSR] = bits(val, 7, 0);
256        break;
257      default:
258        miscRegFile[misc_reg] = val;
259        break;
260    }
261}
262
263void
264ISA::setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc)
265{
266    if (bits((unsigned)misc_reg, 11, 10) == 0x3) {
267        warn("Ignoring write to read-only CSR.");
268        return;
269    }
270    setMiscRegNoEffect(misc_reg, val);
271}
272
273}
274
275RiscvISA::ISA *
276RiscvISAParams::create()
277{
278    return new RiscvISA::ISA(this);
279}
280