isa.cc revision 13612
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_CYCLE: 116 if (hpmCounterEnabled(MISCREG_CYCLE)) { 117 DPRINTF(RiscvMisc, "Cycle counter at: %llu.\n", 118 tc->getCpuPtr()->curCycle()); 119 return tc->getCpuPtr()->curCycle(); 120 } else { 121 warn("Cycle counter disabled.\n"); 122 return 0; 123 } 124 case MISCREG_TIME: 125 if (hpmCounterEnabled(MISCREG_TIME)) { 126 DPRINTF(RiscvMisc, "Wall-clock counter at: %llu.\n", 127 std::time(nullptr)); 128 return std::time(nullptr); 129 } else { 130 warn("Wall clock disabled.\n"); 131 return 0; 132 } 133 case MISCREG_INSTRET: 134 if (hpmCounterEnabled(MISCREG_INSTRET)) { 135 DPRINTF(RiscvMisc, "Instruction counter at: %llu.\n", 136 tc->getCpuPtr()->totalInsts()); 137 return tc->getCpuPtr()->totalInsts(); 138 } else { 139 warn("Instruction counter disabled.\n"); 140 return 0; 141 } 142 case MISCREG_IP: 143 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 144 ->readIP(); 145 case MISCREG_IE: 146 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 147 ->readIE(); 148 default: 149 // Try reading HPM counters 150 // As a placeholder, all HPM counters are just cycle counters 151 if (misc_reg >= MISCREG_HPMCOUNTER03 && 152 misc_reg <= MISCREG_HPMCOUNTER31) { 153 if (hpmCounterEnabled(misc_reg)) { 154 DPRINTF(RiscvMisc, "HPM counter %d: %llu.\n", 155 misc_reg - MISCREG_CYCLE, tc->getCpuPtr()->curCycle()); 156 return tc->getCpuPtr()->curCycle(); 157 } else { 158 warn("HPM counter %d disabled.\n", misc_reg - MISCREG_CYCLE); 159 return 0; 160 } 161 } 162 return readMiscRegNoEffect(misc_reg); 163 } 164} 165 166void 167ISA::setMiscRegNoEffect(int misc_reg, RegVal val) 168{ 169 if (misc_reg > NumMiscRegs || misc_reg < 0) { 170 // Illegal CSR 171 panic("Illegal CSR index %#x\n", misc_reg); 172 } 173 DPRINTF(RiscvMisc, "Setting MiscReg %d to %#x.\n", misc_reg, val); 174 miscRegFile[misc_reg] = val; 175} 176 177void 178ISA::setMiscReg(int misc_reg, RegVal val, ThreadContext *tc) 179{ 180 if (misc_reg >= MISCREG_CYCLE && misc_reg <= MISCREG_HPMCOUNTER31) { 181 // Ignore writes to HPM counters for now 182 warn("Ignoring write to %s.\n", CSRData.at(misc_reg).name); 183 } else { 184 switch (misc_reg) { 185 case MISCREG_IP: 186 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 187 ->setIP(val); 188 case MISCREG_IE: 189 return tc->getCpuPtr()->getInterruptController(tc->threadId()) 190 ->setIE(val); 191 default: 192 setMiscRegNoEffect(misc_reg, val); 193 } 194 } 195} 196 197} 198 199RiscvISA::ISA * 200RiscvISAParams::create() 201{ 202 return new RiscvISA::ISA(this); 203} 204