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 &regQueue = 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