111723Sar4jc@virginia.edu/*
211723Sar4jc@virginia.edu * Copyright (c) 2016 RISC-V Foundation
311723Sar4jc@virginia.edu * Copyright (c) 2016 The University of Virginia
411723Sar4jc@virginia.edu * All rights reserved.
511723Sar4jc@virginia.edu *
611723Sar4jc@virginia.edu * Redistribution and use in source and binary forms, with or without
711723Sar4jc@virginia.edu * modification, are permitted provided that the following conditions are
811723Sar4jc@virginia.edu * met: redistributions of source code must retain the above copyright
911723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer;
1011723Sar4jc@virginia.edu * redistributions in binary form must reproduce the above copyright
1111723Sar4jc@virginia.edu * notice, this list of conditions and the following disclaimer in the
1211723Sar4jc@virginia.edu * documentation and/or other materials provided with the distribution;
1311723Sar4jc@virginia.edu * neither the name of the copyright holders nor the names of its
1411723Sar4jc@virginia.edu * contributors may be used to endorse or promote products derived from
1511723Sar4jc@virginia.edu * this software without specific prior written permission.
1611723Sar4jc@virginia.edu *
1711723Sar4jc@virginia.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1811723Sar4jc@virginia.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1911723Sar4jc@virginia.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2011723Sar4jc@virginia.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2111723Sar4jc@virginia.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2211723Sar4jc@virginia.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2311723Sar4jc@virginia.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2411723Sar4jc@virginia.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2511723Sar4jc@virginia.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2611723Sar4jc@virginia.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2711723Sar4jc@virginia.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811723Sar4jc@virginia.edu *
2911723Sar4jc@virginia.edu * Authors: Alec Roelke
3011723Sar4jc@virginia.edu */
3111723Sar4jc@virginia.edu#include "arch/riscv/isa.hh"
3211723Sar4jc@virginia.edu
3311723Sar4jc@virginia.edu#include <ctime>
3411723Sar4jc@virginia.edu#include <set>
3511963Sar4jc@virginia.edu#include <sstream>
3611723Sar4jc@virginia.edu
3711723Sar4jc@virginia.edu#include "arch/riscv/registers.hh"
3811723Sar4jc@virginia.edu#include "base/bitfield.hh"
3911723Sar4jc@virginia.edu#include "cpu/base.hh"
4011723Sar4jc@virginia.edu#include "debug/RiscvMisc.hh"
4111723Sar4jc@virginia.edu#include "params/RiscvISA.hh"
4211723Sar4jc@virginia.edu#include "sim/core.hh"
4311723Sar4jc@virginia.edu#include "sim/pseudo_inst.hh"
4411723Sar4jc@virginia.edu
4511723Sar4jc@virginia.edunamespace RiscvISA
4611723Sar4jc@virginia.edu{
4711723Sar4jc@virginia.edu
4811723Sar4jc@virginia.eduISA::ISA(Params *p) : SimObject(p)
4911723Sar4jc@virginia.edu{
5011723Sar4jc@virginia.edu    miscRegFile.resize(NumMiscRegs);
5111723Sar4jc@virginia.edu    clear();
5211723Sar4jc@virginia.edu}
5311723Sar4jc@virginia.edu
5411723Sar4jc@virginia.educonst RiscvISAParams *
5511723Sar4jc@virginia.eduISA::params() const
5611723Sar4jc@virginia.edu{
5711723Sar4jc@virginia.edu    return dynamic_cast<const Params *>(_params);
5811723Sar4jc@virginia.edu}
5911723Sar4jc@virginia.edu
6011723Sar4jc@virginia.eduvoid ISA::clear()
6111723Sar4jc@virginia.edu{
6211723Sar4jc@virginia.edu    std::fill(miscRegFile.begin(), miscRegFile.end(), 0);
6311963Sar4jc@virginia.edu
6412695Sar4jc@virginia.edu    miscRegFile[MISCREG_PRV] = PRV_M;
6512695Sar4jc@virginia.edu    miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSET) | 0x14112D;
6612695Sar4jc@virginia.edu    miscRegFile[MISCREG_VENDORID] = 0;
6712695Sar4jc@virginia.edu    miscRegFile[MISCREG_ARCHID] = 0;
6812695Sar4jc@virginia.edu    miscRegFile[MISCREG_IMPID] = 0;
6912695Sar4jc@virginia.edu    miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) | (2ULL << SXL_OFFSET) |
7012695Sar4jc@virginia.edu                                  (1ULL << FS_OFFSET);
7112695Sar4jc@virginia.edu    miscRegFile[MISCREG_MCOUNTEREN] = 0x7;
7212695Sar4jc@virginia.edu    miscRegFile[MISCREG_SCOUNTEREN] = 0x7;
7311723Sar4jc@virginia.edu}
7411723Sar4jc@virginia.edu
7512695Sar4jc@virginia.edubool
7612695Sar4jc@virginia.eduISA::hpmCounterEnabled(int misc_reg) const
7712695Sar4jc@virginia.edu{
7812695Sar4jc@virginia.edu    int hpmcounter = misc_reg - MISCREG_CYCLE;
7912695Sar4jc@virginia.edu    if (hpmcounter < 0 || hpmcounter > 31)
8012695Sar4jc@virginia.edu        panic("Illegal HPM counter %d\n", hpmcounter);
8112695Sar4jc@virginia.edu    int counteren;
8212695Sar4jc@virginia.edu    switch (readMiscRegNoEffect(MISCREG_PRV)) {
8312695Sar4jc@virginia.edu      case PRV_M:
8412695Sar4jc@virginia.edu        return true;
8512695Sar4jc@virginia.edu      case PRV_S:
8612695Sar4jc@virginia.edu        counteren = MISCREG_MCOUNTEREN;
8712695Sar4jc@virginia.edu        break;
8812695Sar4jc@virginia.edu      case PRV_U:
8912695Sar4jc@virginia.edu        counteren = MISCREG_SCOUNTEREN;
9012695Sar4jc@virginia.edu        break;
9112695Sar4jc@virginia.edu      default:
9212695Sar4jc@virginia.edu        panic("Unknown privilege level %d\n", miscRegFile[MISCREG_PRV]);
9312695Sar4jc@virginia.edu        return false;
9412695Sar4jc@virginia.edu    }
9512695Sar4jc@virginia.edu    return (miscRegFile[counteren] & (1ULL << (hpmcounter))) > 0;
9612695Sar4jc@virginia.edu}
9711723Sar4jc@virginia.edu
9813612Sgabeblack@google.comRegVal
9911723Sar4jc@virginia.eduISA::readMiscRegNoEffect(int misc_reg) const
10011723Sar4jc@virginia.edu{
10112695Sar4jc@virginia.edu    if (misc_reg > NumMiscRegs || misc_reg < 0) {
10212695Sar4jc@virginia.edu        // Illegal CSR
10312695Sar4jc@virginia.edu        panic("Illegal CSR index %#x\n", misc_reg);
10412695Sar4jc@virginia.edu        return -1;
10511723Sar4jc@virginia.edu    }
10612695Sar4jc@virginia.edu    DPRINTF(RiscvMisc, "Reading MiscReg %d: %#llx.\n", misc_reg,
10712695Sar4jc@virginia.edu            miscRegFile[misc_reg]);
10812695Sar4jc@virginia.edu    return miscRegFile[misc_reg];
10911723Sar4jc@virginia.edu}
11011723Sar4jc@virginia.edu
11113612Sgabeblack@google.comRegVal
11211723Sar4jc@virginia.eduISA::readMiscReg(int misc_reg, ThreadContext *tc)
11311723Sar4jc@virginia.edu{
11411723Sar4jc@virginia.edu    switch (misc_reg) {
11513935Salec.roelke@gmail.com      case MISCREG_HARTID:
11613935Salec.roelke@gmail.com        return tc->contextId();
11712695Sar4jc@virginia.edu      case MISCREG_CYCLE:
11812695Sar4jc@virginia.edu        if (hpmCounterEnabled(MISCREG_CYCLE)) {
11912695Sar4jc@virginia.edu            DPRINTF(RiscvMisc, "Cycle counter at: %llu.\n",
12012695Sar4jc@virginia.edu                    tc->getCpuPtr()->curCycle());
12112695Sar4jc@virginia.edu            return tc->getCpuPtr()->curCycle();
12212695Sar4jc@virginia.edu        } else {
12312695Sar4jc@virginia.edu            warn("Cycle counter disabled.\n");
12412695Sar4jc@virginia.edu            return 0;
12512695Sar4jc@virginia.edu        }
12612695Sar4jc@virginia.edu      case MISCREG_TIME:
12712695Sar4jc@virginia.edu        if (hpmCounterEnabled(MISCREG_TIME)) {
12812695Sar4jc@virginia.edu            DPRINTF(RiscvMisc, "Wall-clock counter at: %llu.\n",
12912695Sar4jc@virginia.edu                    std::time(nullptr));
13012695Sar4jc@virginia.edu            return std::time(nullptr);
13112695Sar4jc@virginia.edu        } else {
13212695Sar4jc@virginia.edu            warn("Wall clock disabled.\n");
13312695Sar4jc@virginia.edu            return 0;
13412695Sar4jc@virginia.edu        }
13511723Sar4jc@virginia.edu      case MISCREG_INSTRET:
13612695Sar4jc@virginia.edu        if (hpmCounterEnabled(MISCREG_INSTRET)) {
13712695Sar4jc@virginia.edu            DPRINTF(RiscvMisc, "Instruction counter at: %llu.\n",
13812695Sar4jc@virginia.edu                    tc->getCpuPtr()->totalInsts());
13912695Sar4jc@virginia.edu            return tc->getCpuPtr()->totalInsts();
14012695Sar4jc@virginia.edu        } else {
14112695Sar4jc@virginia.edu            warn("Instruction counter disabled.\n");
14212695Sar4jc@virginia.edu            return 0;
14312695Sar4jc@virginia.edu        }
14413548Salec.roelke@gmail.com      case MISCREG_IP:
14513548Salec.roelke@gmail.com        return tc->getCpuPtr()->getInterruptController(tc->threadId())
14613548Salec.roelke@gmail.com                              ->readIP();
14713548Salec.roelke@gmail.com      case MISCREG_IE:
14813548Salec.roelke@gmail.com        return tc->getCpuPtr()->getInterruptController(tc->threadId())
14913548Salec.roelke@gmail.com                              ->readIE();
15011723Sar4jc@virginia.edu      default:
15112695Sar4jc@virginia.edu        // Try reading HPM counters
15212695Sar4jc@virginia.edu        // As a placeholder, all HPM counters are just cycle counters
15312695Sar4jc@virginia.edu        if (misc_reg >= MISCREG_HPMCOUNTER03 &&
15412695Sar4jc@virginia.edu                misc_reg <= MISCREG_HPMCOUNTER31) {
15512695Sar4jc@virginia.edu            if (hpmCounterEnabled(misc_reg)) {
15612695Sar4jc@virginia.edu                DPRINTF(RiscvMisc, "HPM counter %d: %llu.\n",
15712695Sar4jc@virginia.edu                        misc_reg - MISCREG_CYCLE, tc->getCpuPtr()->curCycle());
15812695Sar4jc@virginia.edu                return tc->getCpuPtr()->curCycle();
15912695Sar4jc@virginia.edu            } else {
16012695Sar4jc@virginia.edu                warn("HPM counter %d disabled.\n", misc_reg - MISCREG_CYCLE);
16112695Sar4jc@virginia.edu                return 0;
16212695Sar4jc@virginia.edu            }
16312695Sar4jc@virginia.edu        }
16411723Sar4jc@virginia.edu        return readMiscRegNoEffect(misc_reg);
16511723Sar4jc@virginia.edu    }
16611723Sar4jc@virginia.edu}
16711723Sar4jc@virginia.edu
16811723Sar4jc@virginia.eduvoid
16913612Sgabeblack@google.comISA::setMiscRegNoEffect(int misc_reg, RegVal val)
17011723Sar4jc@virginia.edu{
17112695Sar4jc@virginia.edu    if (misc_reg > NumMiscRegs || misc_reg < 0) {
17212695Sar4jc@virginia.edu        // Illegal CSR
17312695Sar4jc@virginia.edu        panic("Illegal CSR index %#x\n", misc_reg);
17411723Sar4jc@virginia.edu    }
17512695Sar4jc@virginia.edu    DPRINTF(RiscvMisc, "Setting MiscReg %d to %#x.\n", misc_reg, val);
17612695Sar4jc@virginia.edu    miscRegFile[misc_reg] = val;
17711723Sar4jc@virginia.edu}
17811723Sar4jc@virginia.edu
17911723Sar4jc@virginia.eduvoid
18013612Sgabeblack@google.comISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc)
18111723Sar4jc@virginia.edu{
18212695Sar4jc@virginia.edu    if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) {
18312695Sar4jc@virginia.edu        // Ignore writes to HPM counters for now
18412695Sar4jc@virginia.edu        warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name);
18512695Sar4jc@virginia.edu    } else {
18613548Salec.roelke@gmail.com        switch (misc_reg) {
18713548Salec.roelke@gmail.com          case MISCREG_IP:
18813548Salec.roelke@gmail.com            return tc->getCpuPtr()->getInterruptController(tc->threadId())
18913548Salec.roelke@gmail.com                                  ->setIP(val);
19013548Salec.roelke@gmail.com          case MISCREG_IE:
19113548Salec.roelke@gmail.com            return tc->getCpuPtr()->getInterruptController(tc->threadId())
19213548Salec.roelke@gmail.com                                  ->setIE(val);
19313548Salec.roelke@gmail.com          default:
19413548Salec.roelke@gmail.com            setMiscRegNoEffect(misc_reg, val);
19513548Salec.roelke@gmail.com        }
19611723Sar4jc@virginia.edu    }
19711723Sar4jc@virginia.edu}
19811723Sar4jc@virginia.edu
19911723Sar4jc@virginia.edu}
20011723Sar4jc@virginia.edu
20111723Sar4jc@virginia.eduRiscvISA::ISA *
20211723Sar4jc@virginia.eduRiscvISAParams::create()
20311723Sar4jc@virginia.edu{
20411723Sar4jc@virginia.edu    return new RiscvISA::ISA(this);
20513582Sgabeblack@google.com}
206