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 miscRegFile.resize(NumMiscRegs); 51 clear(); 52} 53 54const RiscvISAParams * 55ISA::params() const 56{ 57 return dynamic_cast<const Params *>(_params); 58} 59 60void ISA::clear() 61{ 62 std::fill(miscRegFile.begin(), miscRegFile.end(), 0); 63 64 miscRegFile[MISCREG_PRV] = PRV_M; 65 miscRegFile[MISCREG_ISA] = (2ULL << MXL_OFFSET) | 0x14112D; 66 miscRegFile[MISCREG_VENDORID] = 0; 67 miscRegFile[MISCREG_ARCHID] = 0; 68 miscRegFile[MISCREG_IMPID] = 0; 69 miscRegFile[MISCREG_STATUS] = (2ULL << UXL_OFFSET) | (2ULL << SXL_OFFSET) | 70 (1ULL << FS_OFFSET); 71 miscRegFile[MISCREG_MCOUNTEREN] = 0x7; 72 miscRegFile[MISCREG_SCOUNTEREN] = 0x7; 73} 74 75bool 76ISA::hpmCounterEnabled(int misc_reg) const 77{ 78 int hpmcounter = misc_reg - MISCREG_CYCLE; 79 if (hpmcounter < 0 || hpmcounter > 31) 80 panic("Illegal HPM counter %d\n", hpmcounter); 81 int counteren; 82 switch (readMiscRegNoEffect(MISCREG_PRV)) { 83 case PRV_M: 84 return true; 85 case PRV_S: 86 counteren = MISCREG_MCOUNTEREN; 87 break; 88 case PRV_U: 89 counteren = MISCREG_SCOUNTEREN; 90 break; 91 default: 92 panic("Unknown privilege level %d\n", miscRegFile[MISCREG_PRV]); 93 return false; 94 } 95 return (miscRegFile[counteren] & (1ULL << (hpmcounter))) > 0; 96} 97 98RegVal 99ISA::readMiscRegNoEffect(int misc_reg) const 100{ 101 if (misc_reg > NumMiscRegs || misc_reg < 0) { 102 // Illegal CSR 103 panic("Illegal CSR index %#x\n", misc_reg); 104 return -1; 105 } 106 DPRINTF(RiscvMisc, "Reading MiscReg %d: %#llx.\n", misc_reg, 107 miscRegFile[misc_reg]); 108 return miscRegFile[misc_reg]; 109} 110 111RegVal 112ISA::readMiscReg(int misc_reg, ThreadContext *tc) 113{ 114 switch (misc_reg) { 115 case MISCREG_HARTID: 116 return tc->contextId(); 117 case MISCREG_CYCLE: 118 if (hpmCounterEnabled(MISCREG_CYCLE)) { 119 DPRINTF(RiscvMisc, "Cycle counter at: %llu.\n", 120 tc->getCpuPtr()->curCycle()); 121 return tc->getCpuPtr()->curCycle(); 122 } else { 123 warn("Cycle counter disabled.\n"); 124 return 0; 125 } 126 case MISCREG_TIME: 127 if (hpmCounterEnabled(MISCREG_TIME)) { 128 DPRINTF(RiscvMisc, "Wall-clock counter at: %llu.\n", 129 std::time(nullptr)); 130 return std::time(nullptr); 131 } else { 132 warn("Wall clock disabled.\n"); 133 return 0; 134 } 135 case MISCREG_INSTRET: 136 if (hpmCounterEnabled(MISCREG_INSTRET)) { 137 DPRINTF(RiscvMisc, "Instruction counter at: %llu.\n", 138 tc->getCpuPtr()->totalInsts()); 139 return tc->getCpuPtr()->totalInsts(); 140 } else { 141 warn("Instruction counter disabled.\n"); 142 return 0; 143 } 144 case MISCREG_IP: 145 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 146 ->readIP(); 147 case MISCREG_IE: 148 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 149 ->readIE(); 150 default: 151 // Try reading HPM counters 152 // As a placeholder, all HPM counters are just cycle counters 153 if (misc_reg >= MISCREG_HPMCOUNTER03 && 154 misc_reg <= MISCREG_HPMCOUNTER31) { 155 if (hpmCounterEnabled(misc_reg)) { 156 DPRINTF(RiscvMisc, "HPM counter %d: %llu.\n", 157 misc_reg - MISCREG_CYCLE, tc->getCpuPtr()->curCycle()); 158 return tc->getCpuPtr()->curCycle(); 159 } else { 160 warn("HPM counter %d disabled.\n", misc_reg - MISCREG_CYCLE); 161 return 0; 162 } 163 } 164 return readMiscRegNoEffect(misc_reg); 165 } 166} 167 168void 169ISA::setMiscRegNoEffect(int misc_reg, RegVal val) 170{ 171 if (misc_reg > NumMiscRegs || misc_reg < 0) { 172 // Illegal CSR 173 panic("Illegal CSR index %#x\n", misc_reg); 174 } 175 DPRINTF(RiscvMisc, "Setting MiscReg %d to %#x.\n", misc_reg, val); 176 miscRegFile[misc_reg] = val; 177} 178 179void 180ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc) 181{ 182 if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) { 183 // Ignore writes to HPM counters for now 184 warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name); 185 } else { 186 switch (misc_reg) { 187 case MISCREG_IP: 188 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 189 ->setIP(val); 190 case MISCREG_IE: 191 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 192 ->setIE(val); 193 default: 194 setMiscRegNoEffect(misc_reg, val); 195 } 196 } 197} 198 199} 200 201RiscvISA::ISA * 202RiscvISAParams::create() 203{ 204 return new RiscvISA::ISA(this); 205} 206