1/* 2 * Copyright (c) 2017 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2001-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Steve Reinhardt 41 * Lisa Hsu 42 * Nathan Binkert 43 * Steve Raasch 44 */ 45 46#include "cpu/exetrace.hh" 47 48#include <iomanip> 49 50#include "arch/isa_traits.hh" 51#include "arch/utility.hh" 52#include "base/loader/symtab.hh" 53#include "config/the_isa.hh" 54#include "cpu/base.hh" 55#include "cpu/static_inst.hh" 56#include "cpu/thread_context.hh" 57#include "debug/ExecAll.hh" 58#include "enums/OpClass.hh" 59 60using namespace std; 61using namespace TheISA; 62 63namespace Trace { 64 65void 66ExeTracerRecord::dumpTicks(ostream &outs) 67{ 68 ccprintf(outs, "%7d: ", when); 69} 70 71void 72Trace::ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran) 73{ 74 ostream &outs = Trace::output(); 75 76 if (!Debug::ExecUser || !Debug::ExecKernel) { 77 bool in_user_mode = TheISA::inUserMode(thread); 78 if (in_user_mode && !Debug::ExecUser) return; 79 if (!in_user_mode && !Debug::ExecKernel) return; 80 } 81 82 if (Debug::ExecTicks) 83 dumpTicks(outs); 84 85 outs << thread->getCpuPtr()->name() << " "; 86 87 if (Debug::ExecAsid) 88 outs << "A" << dec << TheISA::getExecutingAsid(thread) << " "; 89 90 if (Debug::ExecThread) 91 outs << "T" << thread->threadId() << " : "; 92 93 std::string sym_str; 94 Addr sym_addr; 95 Addr cur_pc = pc.instAddr(); 96 if (debugSymbolTable && Debug::ExecSymbol && 97 (!FullSystem || !inUserMode(thread)) && 98 debugSymbolTable->findNearestSymbol(cur_pc, sym_str, sym_addr)) { 99 if (cur_pc != sym_addr) 100 sym_str += csprintf("+%d",cur_pc - sym_addr); 101 outs << "@" << sym_str; 102 } else { 103 outs << "0x" << hex << cur_pc; 104 } 105 106 if (inst->isMicroop()) { 107 outs << "." << setw(2) << dec << pc.microPC(); 108 } else { 109 outs << " "; 110 } 111 112 outs << " : "; 113 114 // 115 // Print decoded instruction 116 // 117 118 outs << setw(26) << left; 119 outs << inst->disassemble(cur_pc, debugSymbolTable); 120 121 if (ran) { 122 outs << " : "; 123 124 if (Debug::ExecOpClass) { 125 outs << Enums::OpClassStrings[inst->opClass()] << " : "; 126 } 127 128 if (Debug::ExecResult && !predicate) { 129 outs << "Predicated False"; 130 } 131 132 if (Debug::ExecResult && data_status != DataInvalid) { 133 switch (data_status) { 134 case DataVec: 135 { 136 ccprintf(outs, " D=0x["); 137 auto dv = data.as_vec->as<uint32_t>(); 138 for (int i = TheISA::VecRegSizeBytes / 4 - 1; i >= 0; 139 i--) { 140 ccprintf(outs, "%08x", dv[i]); 141 if (i != 0) { 142 ccprintf(outs, "_"); 143 } 144 } 145 ccprintf(outs, "]"); 146 } 147 break; 148 case DataVecPred: 149 { 150 ccprintf(outs, " D=0b["); 151 auto pv = data.as_pred->as<uint8_t>(); 152 for (int i = TheISA::VecPredRegSizeBits - 1; i >= 0; i--) { 153 ccprintf(outs, pv[i] ? "1" : "0"); 154 if (i != 0 && i % 4 == 0) { 155 ccprintf(outs, "_"); 156 } 157 } 158 ccprintf(outs, "]"); 159 } 160 break; 161 default: 162 ccprintf(outs, " D=%#018x", data.as_int); 163 break; 164 } 165 } 166 167 if (Debug::ExecEffAddr && getMemValid()) 168 outs << " A=0x" << hex << addr; 169 170 if (Debug::ExecFetchSeq && fetch_seq_valid) 171 outs << " FetchSeq=" << dec << fetch_seq; 172 173 if (Debug::ExecCPSeq && cp_seq_valid) 174 outs << " CPSeq=" << dec << cp_seq; 175 176 if (Debug::ExecFlags) { 177 outs << " flags=("; 178 inst->printFlags(outs, "|"); 179 outs << ")"; 180 } 181 } 182 183 // 184 // End of line... 185 // 186 outs << endl; 187} 188 189void 190Trace::ExeTracerRecord::dump() 191{ 192 /* 193 * The behavior this check tries to achieve is that if ExecMacro is on, 194 * the macroop will be printed. If it's on and microops are also on, it's 195 * printed before the microops start printing to give context. If the 196 * microops aren't printed, then it's printed only when the final microop 197 * finishes. Macroops then behave like regular instructions and don't 198 * complete/print when they fault. 199 */ 200 if (Debug::ExecMacro && staticInst->isMicroop() && 201 ((Debug::ExecMicro && 202 macroStaticInst && staticInst->isFirstMicroop()) || 203 (!Debug::ExecMicro && 204 macroStaticInst && staticInst->isLastMicroop()))) { 205 traceInst(macroStaticInst, false); 206 } 207 if (Debug::ExecMicro || !staticInst->isMicroop()) { 208 traceInst(staticInst, true); 209 } 210} 211 212} // namespace Trace 213 214//////////////////////////////////////////////////////////////////////// 215// 216// ExeTracer Simulation Object 217// 218Trace::ExeTracer * 219ExeTracerParams::create() 220{ 221 return new Trace::ExeTracer(this); 222} 223