112642Sgiacomo.travaglini@arm.com/* 212642Sgiacomo.travaglini@arm.com * Copyright (c) 2017-2018 ARM Limited 312642Sgiacomo.travaglini@arm.com * All rights reserved 412642Sgiacomo.travaglini@arm.com * 512642Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall 612642Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual 712642Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating 812642Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software 912642Sgiacomo.travaglini@arm.com * licensed hereunder. You may use the software subject to the license 1012642Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated 1112642Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software, 1212642Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form. 1312642Sgiacomo.travaglini@arm.com * 1412642Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 1512642Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are 1612642Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright 1712642Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer; 1812642Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright 1912642Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the 2012642Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution; 2112642Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its 2212642Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from 2312642Sgiacomo.travaglini@arm.com * this software without specific prior written permission. 2412642Sgiacomo.travaglini@arm.com * 2512642Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2612642Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2712642Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2812642Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2912642Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3012642Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3112642Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3212642Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3312642Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3412642Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3512642Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3612642Sgiacomo.travaglini@arm.com * 3712642Sgiacomo.travaglini@arm.com * Authors: Giacomo Travaglini 3812642Sgiacomo.travaglini@arm.com */ 3912642Sgiacomo.travaglini@arm.com 4012642Sgiacomo.travaglini@arm.com#include "arch/arm/tracers/tarmac_record.hh" 4112642Sgiacomo.travaglini@arm.com 4212642Sgiacomo.travaglini@arm.com#include "arch/arm/insts/static_inst.hh" 4312642Sgiacomo.travaglini@arm.com#include "tarmac_tracer.hh" 4412642Sgiacomo.travaglini@arm.com 4512642Sgiacomo.travaglini@arm.comnamespace Trace { 4612642Sgiacomo.travaglini@arm.com 4712642Sgiacomo.travaglini@arm.com// TARMAC Instruction Record static variables 4812642Sgiacomo.travaglini@arm.comuint64_t TarmacTracerRecord::TraceInstEntry::instCount = 0; 4912642Sgiacomo.travaglini@arm.com 5012642Sgiacomo.travaglini@arm.comstd::string 5112642Sgiacomo.travaglini@arm.comiSetStateToStr(TarmacBaseRecord::ISetState isetstate) 5212642Sgiacomo.travaglini@arm.com{ 5312642Sgiacomo.travaglini@arm.com switch (isetstate) { 5412642Sgiacomo.travaglini@arm.com case TarmacBaseRecord::ISET_ARM: 5512642Sgiacomo.travaglini@arm.com return "A"; 5612642Sgiacomo.travaglini@arm.com case TarmacBaseRecord::ISET_THUMB: 5712642Sgiacomo.travaglini@arm.com return "T"; 5812642Sgiacomo.travaglini@arm.com case TarmacBaseRecord::ISET_A64: 5912642Sgiacomo.travaglini@arm.com return "O"; 6012642Sgiacomo.travaglini@arm.com default: 6112642Sgiacomo.travaglini@arm.com return "Unsupported"; 6212642Sgiacomo.travaglini@arm.com } 6312642Sgiacomo.travaglini@arm.com} 6412642Sgiacomo.travaglini@arm.com 6512642Sgiacomo.travaglini@arm.comstd::string 6612642Sgiacomo.travaglini@arm.comopModeToStr(OperatingMode opMode) 6712642Sgiacomo.travaglini@arm.com{ 6812642Sgiacomo.travaglini@arm.com switch (opMode) { 6912642Sgiacomo.travaglini@arm.com case MODE_EL0T: 7012642Sgiacomo.travaglini@arm.com return "EL0t"; 7112642Sgiacomo.travaglini@arm.com case MODE_EL1T: 7212642Sgiacomo.travaglini@arm.com return "EL1t"; 7312642Sgiacomo.travaglini@arm.com case MODE_EL1H: 7412642Sgiacomo.travaglini@arm.com return "EL1h"; 7512642Sgiacomo.travaglini@arm.com case MODE_EL2T: 7612642Sgiacomo.travaglini@arm.com return "EL2t"; 7712642Sgiacomo.travaglini@arm.com case MODE_EL2H: 7812642Sgiacomo.travaglini@arm.com return "EL2h"; 7912642Sgiacomo.travaglini@arm.com case MODE_EL3T: 8012642Sgiacomo.travaglini@arm.com return "EL3t"; 8112642Sgiacomo.travaglini@arm.com case MODE_EL3H: 8212642Sgiacomo.travaglini@arm.com return "EL3h"; 8312642Sgiacomo.travaglini@arm.com case MODE_USER: 8412642Sgiacomo.travaglini@arm.com return "usr"; 8512642Sgiacomo.travaglini@arm.com case MODE_FIQ: 8612642Sgiacomo.travaglini@arm.com return "fiq"; 8712642Sgiacomo.travaglini@arm.com case MODE_IRQ: 8812642Sgiacomo.travaglini@arm.com return "irq"; 8912642Sgiacomo.travaglini@arm.com case MODE_SVC: 9012642Sgiacomo.travaglini@arm.com return "svc"; 9112642Sgiacomo.travaglini@arm.com case MODE_MON: 9212642Sgiacomo.travaglini@arm.com return "mon"; 9312642Sgiacomo.travaglini@arm.com case MODE_ABORT: 9412642Sgiacomo.travaglini@arm.com return "abt"; 9512642Sgiacomo.travaglini@arm.com case MODE_HYP: 9612642Sgiacomo.travaglini@arm.com return "hyp"; 9712642Sgiacomo.travaglini@arm.com case MODE_UNDEFINED: 9812642Sgiacomo.travaglini@arm.com return "und"; 9912642Sgiacomo.travaglini@arm.com case MODE_SYSTEM: 10012642Sgiacomo.travaglini@arm.com return "sys"; 10112642Sgiacomo.travaglini@arm.com default: 10212642Sgiacomo.travaglini@arm.com return "Unsupported"; 10312642Sgiacomo.travaglini@arm.com } 10412642Sgiacomo.travaglini@arm.com} 10512642Sgiacomo.travaglini@arm.com 10612642Sgiacomo.travaglini@arm.com// TarmacTracerRecord ctor 10712642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TarmacTracerRecord(Tick _when, ThreadContext *_thread, 10812642Sgiacomo.travaglini@arm.com const StaticInstPtr _staticInst, 10912642Sgiacomo.travaglini@arm.com PCState _pc, 11012642Sgiacomo.travaglini@arm.com TarmacTracer& _tracer, 11112642Sgiacomo.travaglini@arm.com const StaticInstPtr _macroStaticInst) 11212642Sgiacomo.travaglini@arm.com : TarmacBaseRecord(_when, _thread, _staticInst, 11312642Sgiacomo.travaglini@arm.com _pc, _macroStaticInst), 11412642Sgiacomo.travaglini@arm.com tracer(_tracer) 11512642Sgiacomo.travaglini@arm.com{ 11612642Sgiacomo.travaglini@arm.com} 11712642Sgiacomo.travaglini@arm.com 11812642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceInstEntry::TraceInstEntry( 11912642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 12012642Sgiacomo.travaglini@arm.com bool predicate) 12112642Sgiacomo.travaglini@arm.com : InstEntry(tarmCtx.thread, tarmCtx.pc, tarmCtx.staticInst, predicate) 12212642Sgiacomo.travaglini@arm.com{ 12312642Sgiacomo.travaglini@arm.com secureMode = inSecureState(tarmCtx.thread); 12412642Sgiacomo.travaglini@arm.com 12512642Sgiacomo.travaglini@arm.com auto arm_inst = static_cast<const ArmStaticInst*>( 12612642Sgiacomo.travaglini@arm.com tarmCtx.staticInst.get() 12712642Sgiacomo.travaglini@arm.com ); 12812642Sgiacomo.travaglini@arm.com 12912642Sgiacomo.travaglini@arm.com // Get the instruction size as a number of bits: 13012642Sgiacomo.travaglini@arm.com // (multiply byte size by 8) 13112642Sgiacomo.travaglini@arm.com instSize = (arm_inst->instSize() << 3); 13212642Sgiacomo.travaglini@arm.com 13312642Sgiacomo.travaglini@arm.com // Mask the opcode using the instruction size: the 13412642Sgiacomo.travaglini@arm.com // opcode field will otherwise be 32 bit wide even 13512642Sgiacomo.travaglini@arm.com // for 16bit (Thumb) instruction. 13612642Sgiacomo.travaglini@arm.com opcode = arm_inst->encoding(); 13712642Sgiacomo.travaglini@arm.com 13812642Sgiacomo.travaglini@arm.com // Update the instruction count: number of executed 13912642Sgiacomo.travaglini@arm.com // instructions. 14012642Sgiacomo.travaglini@arm.com instCount++; 14112642Sgiacomo.travaglini@arm.com} 14212642Sgiacomo.travaglini@arm.com 14312642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceMemEntry::TraceMemEntry( 14412642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 14512642Sgiacomo.travaglini@arm.com uint8_t _size, Addr _addr, uint64_t _data) 14612642Sgiacomo.travaglini@arm.com : MemEntry(_size, _addr, _data), 14712642Sgiacomo.travaglini@arm.com loadAccess(tarmCtx.staticInst->isLoad()) 14812642Sgiacomo.travaglini@arm.com{ 14912642Sgiacomo.travaglini@arm.com} 15012642Sgiacomo.travaglini@arm.com 15112642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::TraceRegEntry( 15212642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 15312642Sgiacomo.travaglini@arm.com const RegId& reg) 15412642Sgiacomo.travaglini@arm.com : RegEntry(tarmCtx.pc), 15512642Sgiacomo.travaglini@arm.com regValid(false), 15612642Sgiacomo.travaglini@arm.com regClass(reg.classValue()), 15712642Sgiacomo.travaglini@arm.com regRel(reg.index()) 15812642Sgiacomo.travaglini@arm.com{ 15912642Sgiacomo.travaglini@arm.com} 16012642Sgiacomo.travaglini@arm.com 16112642Sgiacomo.travaglini@arm.comvoid 16212642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::update( 16312642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx 16412642Sgiacomo.travaglini@arm.com) 16512642Sgiacomo.travaglini@arm.com{ 16612642Sgiacomo.travaglini@arm.com // Fill the register entry data, according to register 16712642Sgiacomo.travaglini@arm.com // class. 16812642Sgiacomo.travaglini@arm.com switch (regClass) { 16912642Sgiacomo.travaglini@arm.com case CCRegClass: 17012642Sgiacomo.travaglini@arm.com updateCC(tarmCtx, regRel); 17112642Sgiacomo.travaglini@arm.com break; 17212642Sgiacomo.travaglini@arm.com case FloatRegClass: 17312642Sgiacomo.travaglini@arm.com updateFloat(tarmCtx, regRel); 17412642Sgiacomo.travaglini@arm.com break; 17512642Sgiacomo.travaglini@arm.com case IntRegClass: 17612642Sgiacomo.travaglini@arm.com updateInt(tarmCtx, regRel); 17712642Sgiacomo.travaglini@arm.com break; 17812642Sgiacomo.travaglini@arm.com case MiscRegClass: 17912642Sgiacomo.travaglini@arm.com updateMisc(tarmCtx, regRel); 18012642Sgiacomo.travaglini@arm.com break; 18112642Sgiacomo.travaglini@arm.com default: 18212642Sgiacomo.travaglini@arm.com // If unsupported format, do nothing: non updating 18312642Sgiacomo.travaglini@arm.com // the register will prevent it to be printed. 18412642Sgiacomo.travaglini@arm.com break; 18512642Sgiacomo.travaglini@arm.com } 18612642Sgiacomo.travaglini@arm.com} 18712642Sgiacomo.travaglini@arm.com 18812642Sgiacomo.travaglini@arm.comvoid 18912642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::updateMisc( 19012642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 19112642Sgiacomo.travaglini@arm.com RegIndex regRelIdx 19212642Sgiacomo.travaglini@arm.com) 19312642Sgiacomo.travaglini@arm.com{ 19412642Sgiacomo.travaglini@arm.com auto thread = tarmCtx.thread; 19512642Sgiacomo.travaglini@arm.com 19612642Sgiacomo.travaglini@arm.com regValid = true; 19712642Sgiacomo.travaglini@arm.com regName = miscRegName[regRelIdx]; 19812642Sgiacomo.travaglini@arm.com valueLo = thread->readMiscRegNoEffect(regRelIdx); 19912642Sgiacomo.travaglini@arm.com 20012642Sgiacomo.travaglini@arm.com // If it is the CPSR: 20112642Sgiacomo.travaglini@arm.com // update the value of the CPSR register and add 20212642Sgiacomo.travaglini@arm.com // the CC flags on top of the value 20312642Sgiacomo.travaglini@arm.com if (regRelIdx == MISCREG_CPSR) { 20412642Sgiacomo.travaglini@arm.com CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR); 20512642Sgiacomo.travaglini@arm.com cpsr.nz = thread->readCCReg(CCREG_NZ); 20612642Sgiacomo.travaglini@arm.com cpsr.c = thread->readCCReg(CCREG_C); 20712642Sgiacomo.travaglini@arm.com cpsr.v = thread->readCCReg(CCREG_V); 20812642Sgiacomo.travaglini@arm.com cpsr.ge = thread->readCCReg(CCREG_GE); 20912642Sgiacomo.travaglini@arm.com 21012642Sgiacomo.travaglini@arm.com // update the entry value 21112642Sgiacomo.travaglini@arm.com valueLo = cpsr; 21212642Sgiacomo.travaglini@arm.com } 21312642Sgiacomo.travaglini@arm.com} 21412642Sgiacomo.travaglini@arm.com 21512642Sgiacomo.travaglini@arm.comvoid 21612642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::updateCC( 21712642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 21812642Sgiacomo.travaglini@arm.com RegIndex regRelIdx 21912642Sgiacomo.travaglini@arm.com) 22012642Sgiacomo.travaglini@arm.com{ 22112642Sgiacomo.travaglini@arm.com auto thread = tarmCtx.thread; 22212642Sgiacomo.travaglini@arm.com 22312642Sgiacomo.travaglini@arm.com regValid = true; 22412642Sgiacomo.travaglini@arm.com regName = ccRegName[regRelIdx]; 22512642Sgiacomo.travaglini@arm.com valueLo = thread->readCCReg(regRelIdx); 22612642Sgiacomo.travaglini@arm.com} 22712642Sgiacomo.travaglini@arm.com 22812642Sgiacomo.travaglini@arm.comvoid 22912642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::updateFloat( 23012642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 23112642Sgiacomo.travaglini@arm.com RegIndex regRelIdx 23212642Sgiacomo.travaglini@arm.com) 23312642Sgiacomo.travaglini@arm.com{ 23412642Sgiacomo.travaglini@arm.com auto thread = tarmCtx.thread; 23512642Sgiacomo.travaglini@arm.com 23612642Sgiacomo.travaglini@arm.com regValid = true; 23712642Sgiacomo.travaglini@arm.com regName = "f" + std::to_string(regRelIdx); 23813611Sgabeblack@google.com valueLo = bitsToFloat32(thread->readFloatReg(regRelIdx)); 23912642Sgiacomo.travaglini@arm.com} 24012642Sgiacomo.travaglini@arm.com 24112642Sgiacomo.travaglini@arm.comvoid 24212642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::updateInt( 24312642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx, 24412642Sgiacomo.travaglini@arm.com RegIndex regRelIdx 24512642Sgiacomo.travaglini@arm.com) 24612642Sgiacomo.travaglini@arm.com{ 24712642Sgiacomo.travaglini@arm.com auto thread = tarmCtx.thread; 24812642Sgiacomo.travaglini@arm.com 24912642Sgiacomo.travaglini@arm.com // Reading operating mode from CPSR. 25012642Sgiacomo.travaglini@arm.com // This is needed when printing the register name in case 25112642Sgiacomo.travaglini@arm.com // of banked register (e.g. lr_svc) 25212642Sgiacomo.travaglini@arm.com CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR); 25312642Sgiacomo.travaglini@arm.com OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode; 25412642Sgiacomo.travaglini@arm.com 25512642Sgiacomo.travaglini@arm.com std::string reg_suffix; 25612642Sgiacomo.travaglini@arm.com if (mode != MODE_USER) { 25712642Sgiacomo.travaglini@arm.com reg_suffix = "_" + opModeToStr(mode); 25812642Sgiacomo.travaglini@arm.com } 25912642Sgiacomo.travaglini@arm.com 26012642Sgiacomo.travaglini@arm.com regValid = true; 26112642Sgiacomo.travaglini@arm.com switch (regRelIdx) { 26212642Sgiacomo.travaglini@arm.com case PCReg: 26312642Sgiacomo.travaglini@arm.com regName = "pc"; 26412642Sgiacomo.travaglini@arm.com break; 26512642Sgiacomo.travaglini@arm.com case StackPointerReg: 26612642Sgiacomo.travaglini@arm.com regName = "sp" + reg_suffix ; 26712642Sgiacomo.travaglini@arm.com break; 26812642Sgiacomo.travaglini@arm.com case FramePointerReg: 26912642Sgiacomo.travaglini@arm.com regName = "fp" + reg_suffix; 27012642Sgiacomo.travaglini@arm.com break; 27112642Sgiacomo.travaglini@arm.com case ReturnAddressReg: 27212642Sgiacomo.travaglini@arm.com regName = "lr" + reg_suffix; 27312642Sgiacomo.travaglini@arm.com break; 27412642Sgiacomo.travaglini@arm.com default: 27512642Sgiacomo.travaglini@arm.com regName = "r" + std::to_string(regRelIdx); 27612642Sgiacomo.travaglini@arm.com break; 27712642Sgiacomo.travaglini@arm.com } 27812642Sgiacomo.travaglini@arm.com valueLo = thread->readIntReg(regRelIdx); 27912642Sgiacomo.travaglini@arm.com} 28012642Sgiacomo.travaglini@arm.com 28112642Sgiacomo.travaglini@arm.comvoid 28212642Sgiacomo.travaglini@arm.comTarmacTracerRecord::addInstEntry(std::vector<InstPtr>& queue, 28312642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx) 28412642Sgiacomo.travaglini@arm.com{ 28512642Sgiacomo.travaglini@arm.com // Generate an instruction entry in the record and 28612642Sgiacomo.travaglini@arm.com // add it to the Instruction Queue 28712642Sgiacomo.travaglini@arm.com queue.push_back( 28812642Sgiacomo.travaglini@arm.com m5::make_unique<TraceInstEntry>(tarmCtx, predicate) 28912642Sgiacomo.travaglini@arm.com ); 29012642Sgiacomo.travaglini@arm.com} 29112642Sgiacomo.travaglini@arm.com 29212642Sgiacomo.travaglini@arm.comvoid 29312642Sgiacomo.travaglini@arm.comTarmacTracerRecord::addMemEntry(std::vector<MemPtr>& queue, 29412642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx) 29512642Sgiacomo.travaglini@arm.com{ 29612642Sgiacomo.travaglini@arm.com // Generate a memory entry in the record if the record 29712642Sgiacomo.travaglini@arm.com // implies a valid memory access, and add it to the 29812642Sgiacomo.travaglini@arm.com // Memory Queue 29912642Sgiacomo.travaglini@arm.com if (getMemValid()) { 30012642Sgiacomo.travaglini@arm.com queue.push_back( 30112642Sgiacomo.travaglini@arm.com m5::make_unique<TraceMemEntry>(tarmCtx, 30212642Sgiacomo.travaglini@arm.com static_cast<uint8_t>(getSize()), 30312642Sgiacomo.travaglini@arm.com getAddr(), getIntData()) 30412642Sgiacomo.travaglini@arm.com ); 30512642Sgiacomo.travaglini@arm.com } 30612642Sgiacomo.travaglini@arm.com} 30712642Sgiacomo.travaglini@arm.com 30812642Sgiacomo.travaglini@arm.comvoid 30912642Sgiacomo.travaglini@arm.comTarmacTracerRecord::addRegEntry(std::vector<RegPtr>& queue, 31012642Sgiacomo.travaglini@arm.com const TarmacContext& tarmCtx) 31112642Sgiacomo.travaglini@arm.com{ 31212642Sgiacomo.travaglini@arm.com // Generate an entry for every ARM register being 31312642Sgiacomo.travaglini@arm.com // written by the current instruction 31412642Sgiacomo.travaglini@arm.com for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) { 31512642Sgiacomo.travaglini@arm.com 31612642Sgiacomo.travaglini@arm.com RegId reg_id = staticInst->destRegIdx(reg); 31712642Sgiacomo.travaglini@arm.com 31812642Sgiacomo.travaglini@arm.com // Creating a single register change entry 31912642Sgiacomo.travaglini@arm.com auto single_reg = genRegister<TraceRegEntry>(tarmCtx, reg_id); 32012642Sgiacomo.travaglini@arm.com 32112642Sgiacomo.travaglini@arm.com // Copying the entry and adding it to the "list" 32212642Sgiacomo.travaglini@arm.com // of entries to be dumped to trace. 32312642Sgiacomo.travaglini@arm.com queue.push_back( 32412642Sgiacomo.travaglini@arm.com m5::make_unique<TraceRegEntry>(single_reg) 32512642Sgiacomo.travaglini@arm.com ); 32612642Sgiacomo.travaglini@arm.com } 32712642Sgiacomo.travaglini@arm.com 32812642Sgiacomo.travaglini@arm.com // Gem5 is treating CPSR flags as separate registers (CC registers), 32912642Sgiacomo.travaglini@arm.com // in contrast with Tarmac specification: we need to merge the gem5 CC 33012642Sgiacomo.travaglini@arm.com // entries altogether with the CPSR register and produce a single entry. 33112642Sgiacomo.travaglini@arm.com mergeCCEntry<TraceRegEntry>(queue, tarmCtx); 33212642Sgiacomo.travaglini@arm.com} 33312642Sgiacomo.travaglini@arm.com 33412642Sgiacomo.travaglini@arm.comvoid 33512642Sgiacomo.travaglini@arm.comTarmacTracerRecord::dump() 33612642Sgiacomo.travaglini@arm.com{ 33712642Sgiacomo.travaglini@arm.com // Generate and print all the record's entries. 33812642Sgiacomo.travaglini@arm.com auto &instQueue = tracer.instQueue; 33912642Sgiacomo.travaglini@arm.com auto &memQueue = tracer.memQueue; 34012642Sgiacomo.travaglini@arm.com auto ®Queue = tracer.regQueue; 34112642Sgiacomo.travaglini@arm.com 34212642Sgiacomo.travaglini@arm.com const TarmacContext tarmCtx( 34312642Sgiacomo.travaglini@arm.com thread, 34412642Sgiacomo.travaglini@arm.com staticInst->isMicroop()? macroStaticInst : staticInst, 34512642Sgiacomo.travaglini@arm.com pc 34612642Sgiacomo.travaglini@arm.com ); 34712642Sgiacomo.travaglini@arm.com 34812642Sgiacomo.travaglini@arm.com if (!staticInst->isMicroop()) { 34912642Sgiacomo.travaglini@arm.com // Current instruction is NOT a micro-instruction: 35012642Sgiacomo.travaglini@arm.com // Generate Tarmac entries and dump them immediately 35112642Sgiacomo.travaglini@arm.com 35212642Sgiacomo.travaglini@arm.com // Generate Tarmac entries and add them to the respective 35312642Sgiacomo.travaglini@arm.com // queues. 35412642Sgiacomo.travaglini@arm.com addInstEntry(instQueue, tarmCtx); 35512642Sgiacomo.travaglini@arm.com addMemEntry(memQueue, tarmCtx); 35612642Sgiacomo.travaglini@arm.com addRegEntry(regQueue, tarmCtx); 35712642Sgiacomo.travaglini@arm.com 35812642Sgiacomo.travaglini@arm.com // Flush (print) any queued entry. 35912642Sgiacomo.travaglini@arm.com flushQueues(instQueue, memQueue, regQueue); 36012642Sgiacomo.travaglini@arm.com 36112642Sgiacomo.travaglini@arm.com } else { 36212642Sgiacomo.travaglini@arm.com // Current instruction is a micro-instruction: 36312642Sgiacomo.travaglini@arm.com // save micro entries into dedicated queues and flush them 36412642Sgiacomo.travaglini@arm.com // into the tracefile only when the MACRO-instruction 36512642Sgiacomo.travaglini@arm.com // has completed. 36612642Sgiacomo.travaglini@arm.com 36712642Sgiacomo.travaglini@arm.com if (staticInst->isFirstMicroop()) { 36812642Sgiacomo.travaglini@arm.com addInstEntry(instQueue, tarmCtx); 36912642Sgiacomo.travaglini@arm.com } 37012642Sgiacomo.travaglini@arm.com 37112642Sgiacomo.travaglini@arm.com addRegEntry(regQueue, tarmCtx); 37212642Sgiacomo.travaglini@arm.com addMemEntry(memQueue, tarmCtx); 37312642Sgiacomo.travaglini@arm.com 37412642Sgiacomo.travaglini@arm.com if (staticInst->isLastMicroop()) { 37512642Sgiacomo.travaglini@arm.com // Flush (print) any queued entry. 37612642Sgiacomo.travaglini@arm.com flushQueues(instQueue, memQueue, regQueue); 37712642Sgiacomo.travaglini@arm.com } 37812642Sgiacomo.travaglini@arm.com } 37912642Sgiacomo.travaglini@arm.com} 38012642Sgiacomo.travaglini@arm.com 38112642Sgiacomo.travaglini@arm.comtemplate<typename Queue> 38212642Sgiacomo.travaglini@arm.comvoid 38312642Sgiacomo.travaglini@arm.comTarmacTracerRecord::flushQueues(Queue& queue) 38412642Sgiacomo.travaglini@arm.com{ 38512642Sgiacomo.travaglini@arm.com std::ostream &outs = Trace::output(); 38612642Sgiacomo.travaglini@arm.com 38712642Sgiacomo.travaglini@arm.com for (const auto &single_entry : queue) { 38812642Sgiacomo.travaglini@arm.com single_entry->print(outs); 38912642Sgiacomo.travaglini@arm.com } 39012642Sgiacomo.travaglini@arm.com 39112642Sgiacomo.travaglini@arm.com queue.clear(); 39212642Sgiacomo.travaglini@arm.com} 39312642Sgiacomo.travaglini@arm.com 39412642Sgiacomo.travaglini@arm.comtemplate<typename Queue, typename... Args> 39512642Sgiacomo.travaglini@arm.comvoid 39612642Sgiacomo.travaglini@arm.comTarmacTracerRecord::flushQueues(Queue& queue, Args & ... args) 39712642Sgiacomo.travaglini@arm.com{ 39812642Sgiacomo.travaglini@arm.com flushQueues(queue); 39912642Sgiacomo.travaglini@arm.com flushQueues(args...); 40012642Sgiacomo.travaglini@arm.com} 40112642Sgiacomo.travaglini@arm.com 40212642Sgiacomo.travaglini@arm.comvoid 40312642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceInstEntry::print( 40412642Sgiacomo.travaglini@arm.com std::ostream& outs, 40512642Sgiacomo.travaglini@arm.com int verbosity, 40612642Sgiacomo.travaglini@arm.com const std::string &prefix) const 40712642Sgiacomo.travaglini@arm.com{ 40812642Sgiacomo.travaglini@arm.com // Pad the opcode 40912642Sgiacomo.travaglini@arm.com std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode); 41012642Sgiacomo.travaglini@arm.com 41112642Sgiacomo.travaglini@arm.com // Print the instruction record formatted according 41212642Sgiacomo.travaglini@arm.com // to the Tarmac specification 41312642Sgiacomo.travaglini@arm.com ccprintf(outs, "%s clk %s (%u) %08x %s %s %s_%s : %s\n", 41412642Sgiacomo.travaglini@arm.com curTick(), /* Tick time */ 41512642Sgiacomo.travaglini@arm.com taken? "IT" : "IS", /* Instruction taken/skipped */ 41612642Sgiacomo.travaglini@arm.com instCount, /* Instruction count */ 41712642Sgiacomo.travaglini@arm.com addr, /* Instruction address */ 41812642Sgiacomo.travaglini@arm.com opcode_str, /* Instruction opcode */ 41912642Sgiacomo.travaglini@arm.com iSetStateToStr(isetstate), /* Instruction Set */ 42012642Sgiacomo.travaglini@arm.com opModeToStr(mode), /* Exception level */ 42112642Sgiacomo.travaglini@arm.com secureMode? "s" : "ns", /* Security */ 42212642Sgiacomo.travaglini@arm.com disassemble); /* Instruction disass */ 42312642Sgiacomo.travaglini@arm.com} 42412642Sgiacomo.travaglini@arm.com 42512642Sgiacomo.travaglini@arm.comvoid 42612642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceMemEntry::print( 42712642Sgiacomo.travaglini@arm.com std::ostream& outs, 42812642Sgiacomo.travaglini@arm.com int verbosity, 42912642Sgiacomo.travaglini@arm.com const std::string &prefix) const 43012642Sgiacomo.travaglini@arm.com{ 43112642Sgiacomo.travaglini@arm.com // Print the memory record formatted according 43212642Sgiacomo.travaglini@arm.com // to the Tarmac specification 43312642Sgiacomo.travaglini@arm.com ccprintf(outs, "%s clk M%s%d %08x %0*x\n", 43412642Sgiacomo.travaglini@arm.com curTick(), /* Tick time */ 43512642Sgiacomo.travaglini@arm.com loadAccess? "R" : "W", /* Access type */ 43612642Sgiacomo.travaglini@arm.com size, /* Access size */ 43712642Sgiacomo.travaglini@arm.com addr, /* Memory address */ 43812642Sgiacomo.travaglini@arm.com size*2, /* Padding with access size */ 43912642Sgiacomo.travaglini@arm.com data); /* Memory data */ 44012642Sgiacomo.travaglini@arm.com} 44112642Sgiacomo.travaglini@arm.com 44212642Sgiacomo.travaglini@arm.comvoid 44312642Sgiacomo.travaglini@arm.comTarmacTracerRecord::TraceRegEntry::print( 44412642Sgiacomo.travaglini@arm.com std::ostream& outs, 44512642Sgiacomo.travaglini@arm.com int verbosity, 44612642Sgiacomo.travaglini@arm.com const std::string &prefix) const 44712642Sgiacomo.travaglini@arm.com{ 44812642Sgiacomo.travaglini@arm.com // Print the register record formatted according 44912642Sgiacomo.travaglini@arm.com // to the Tarmac specification 45012642Sgiacomo.travaglini@arm.com if (regValid) 45112642Sgiacomo.travaglini@arm.com ccprintf(outs, "%s clk R %s %08x\n", 45212642Sgiacomo.travaglini@arm.com curTick(), /* Tick time */ 45312642Sgiacomo.travaglini@arm.com regName, /* Register name */ 45412642Sgiacomo.travaglini@arm.com valueLo); /* Register value */ 45512642Sgiacomo.travaglini@arm.com} 45612642Sgiacomo.travaglini@arm.com 45712642Sgiacomo.travaglini@arm.com} // namespace Trace 458