1/* 2 * Copyright (c) 2017-2018 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 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Giacomo Travaglini 38 */ 39 40#include "arch/arm/tracers/tarmac_record_v8.hh" 41 42#include "arch/arm/insts/static_inst.hh" 43#include "arch/arm/tlb.hh" 44#include "arch/arm/tracers/tarmac_tracer.hh" 45 46namespace Trace { 47 48TarmacTracerRecordV8::TraceInstEntryV8::TraceInstEntryV8( 49 const TarmacContext& tarmCtx, 50 bool predicate) 51 : TraceInstEntry(tarmCtx, predicate), 52 TraceEntryV8(tarmCtx.tarmacCpuName()), 53 paddr(0), 54 paddrValid(false) 55{ 56 const auto thread = tarmCtx.thread; 57 58 // Evaluate physical address 59 ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr()); 60 paddrValid = dtb->translateFunctional(thread, addr, paddr); 61} 62 63TarmacTracerRecordV8::TraceMemEntryV8::TraceMemEntryV8( 64 const TarmacContext& tarmCtx, 65 uint8_t _size, Addr _addr, uint64_t _data) 66 : TraceMemEntry(tarmCtx, _size, _addr, _data), 67 TraceEntryV8(tarmCtx.tarmacCpuName()), 68 paddr(_addr) 69{ 70 const auto thread = tarmCtx.thread; 71 72 // Evaluate physical address 73 ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr()); 74 dtb->translateFunctional(thread, addr, paddr); 75} 76 77TarmacTracerRecordV8::TraceRegEntryV8::TraceRegEntryV8( 78 const TarmacContext& tarmCtx, 79 const RegId& reg) 80 : TraceRegEntry(tarmCtx, reg), 81 TraceEntryV8(tarmCtx.tarmacCpuName()), 82 regWidth(64) 83{ 84} 85 86void 87TarmacTracerRecordV8::TraceRegEntryV8::updateInt( 88 const TarmacContext& tarmCtx, 89 RegIndex regRelIdx 90) 91{ 92 // Do not trace pseudo register accesses: invalid 93 // register entry. 94 if (regRelIdx > NUM_ARCH_INTREGS) { 95 regValid = false; 96 return; 97 } 98 99 TraceRegEntry::updateInt(tarmCtx, regRelIdx); 100 101 if ((regRelIdx != PCReg) || (regRelIdx != StackPointerReg) || 102 (regRelIdx != FramePointerReg) || (regRelIdx != ReturnAddressReg)) { 103 104 const auto* arm_inst = static_cast<const ArmStaticInst*>( 105 tarmCtx.staticInst.get() 106 ); 107 108 regWidth = (arm_inst->getIntWidth()); 109 if (regWidth == 32) { 110 regName = "W" + std::to_string(regRelIdx); 111 } else { 112 regName = "X" + std::to_string(regRelIdx); 113 } 114 } 115} 116 117void 118TarmacTracerRecordV8::TraceRegEntryV8::updateMisc( 119 const TarmacContext& tarmCtx, 120 RegIndex regRelIdx 121) 122{ 123 TraceRegEntry::updateMisc(tarmCtx, regRelIdx); 124 // System registers are 32bit wide 125 regWidth = 32; 126} 127 128void 129TarmacTracerRecordV8::addInstEntry(std::vector<InstPtr>& queue, 130 const TarmacContext& tarmCtx) 131{ 132 // Generate an instruction entry in the record and 133 // add it to the Instruction Queue 134 queue.push_back( 135 m5::make_unique<TraceInstEntryV8>(tarmCtx, predicate) 136 ); 137} 138 139void 140TarmacTracerRecordV8::addMemEntry(std::vector<MemPtr>& queue, 141 const TarmacContext& tarmCtx) 142{ 143 // Generate a memory entry in the record if the record 144 // implies a valid memory access, and add it to the 145 // Memory Queue 146 if (getMemValid()) { 147 queue.push_back( 148 m5::make_unique<TraceMemEntryV8>(tarmCtx, 149 static_cast<uint8_t>(getSize()), 150 getAddr(), getIntData()) 151 ); 152 } 153} 154 155void 156TarmacTracerRecordV8::addRegEntry(std::vector<RegPtr>& queue, 157 const TarmacContext& tarmCtx) 158{ 159 // Generate an entry for every ARM register being 160 // written by the current instruction 161 for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) { 162 163 RegId reg_id = staticInst->destRegIdx(reg); 164 165 // Creating a single register change entry 166 auto single_reg = genRegister<TraceRegEntryV8>(tarmCtx, reg_id); 167 168 // Copying the entry and adding it to the "list" 169 // of entries to be dumped to trace. 170 queue.push_back( 171 m5::make_unique<TraceRegEntryV8>(single_reg) 172 ); 173 } 174 175 // Gem5 is treating CPSR flags as separate registers (CC registers), 176 // in contrast with Tarmac specification: we need to merge the gem5 CC 177 // entries altogether with the CPSR register and produce a single entry. 178 mergeCCEntry<TraceRegEntryV8>(queue, tarmCtx); 179} 180 181void 182TarmacTracerRecordV8::TraceInstEntryV8::print( 183 std::ostream& outs, 184 int verbosity, 185 const std::string &prefix) const 186{ 187 // If there is a valid vaddr->paddr translation, print the 188 // physical address, otherwise print the virtual address only. 189 std::string paddr_str = paddrValid? csprintf(":%012x",paddr) : 190 std::string(); 191 192 // Pad the opcode. 193 std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode); 194 195 // Print the instruction record formatted according 196 // to the Tarmac specification 197 ccprintf(outs, "%s clk %s %s (%u) %08x%s %s %s %s_%s : %s\n", 198 curTick(), /* Tick time */ 199 cpuName, /* Cpu name */ 200 taken? "IT" : "IS", /* Instruction taken/skipped */ 201 instCount, /* Instruction count */ 202 addr, /* Instruction virt address */ 203 paddr_str, /* Instruction phys address */ 204 opcode_str, /* Instruction opcode */ 205 iSetStateToStr(isetstate), /* Instruction Set */ 206 opModeToStr(mode), /* Exception level */ 207 secureMode? "s" : "ns", /* Security */ 208 disassemble); /* Instruction disass */ 209} 210 211void 212TarmacTracerRecordV8::TraceMemEntryV8::print( 213 std::ostream& outs, 214 int verbosity, 215 const std::string &prefix) const 216{ 217 // Print the memory record formatted according 218 // to the Tarmac specification 219 ccprintf(outs, "%s clk %s M%s%d %08x:%012x %0*x\n", 220 curTick(), /* Tick time */ 221 cpuName, /* Cpu name */ 222 loadAccess? "R" : "W", /* Access type */ 223 size, /* Access size */ 224 addr, /* Virt Memory address */ 225 paddr, /* Phys Memory address */ 226 size*2, /* Padding with access size */ 227 data); /* Memory data */ 228} 229 230void 231TarmacTracerRecordV8::TraceRegEntryV8::print( 232 std::ostream& outs, 233 int verbosity, 234 const std::string &prefix) const 235{ 236 // Print the register record formatted according 237 // to the Tarmac specification 238 if (regValid) { 239 ccprintf(outs, "%s clk %s R %s %0*x\n", 240 curTick(), /* Tick time */ 241 cpuName, /* Cpu name */ 242 regName, /* Register name */ 243 regWidth >> 2, /* Register value padding */ 244 valueLo); /* Register value */ 245 } 246} 247 248} // namespace Trace 249