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_v8.hh"
4112642Sgiacomo.travaglini@arm.com
4212642Sgiacomo.travaglini@arm.com#include "arch/arm/insts/static_inst.hh"
4312642Sgiacomo.travaglini@arm.com#include "arch/arm/tlb.hh"
4412642Sgiacomo.travaglini@arm.com#include "arch/arm/tracers/tarmac_tracer.hh"
4512642Sgiacomo.travaglini@arm.com
4612642Sgiacomo.travaglini@arm.comnamespace Trace {
4712642Sgiacomo.travaglini@arm.com
4812642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceInstEntryV8::TraceInstEntryV8(
4912642Sgiacomo.travaglini@arm.com    const TarmacContext& tarmCtx,
5012642Sgiacomo.travaglini@arm.com    bool predicate)
5112642Sgiacomo.travaglini@arm.com      : TraceInstEntry(tarmCtx, predicate),
5212642Sgiacomo.travaglini@arm.com        TraceEntryV8(tarmCtx.tarmacCpuName()),
5312642Sgiacomo.travaglini@arm.com        paddr(0),
5412642Sgiacomo.travaglini@arm.com        paddrValid(false)
5512642Sgiacomo.travaglini@arm.com{
5612642Sgiacomo.travaglini@arm.com    const auto thread = tarmCtx.thread;
5712642Sgiacomo.travaglini@arm.com
5812642Sgiacomo.travaglini@arm.com    // Evaluate physical address
5913915Sgabeblack@google.com    ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
6012642Sgiacomo.travaglini@arm.com    paddrValid = dtb->translateFunctional(thread, addr, paddr);
6112642Sgiacomo.travaglini@arm.com}
6212642Sgiacomo.travaglini@arm.com
6312642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceMemEntryV8::TraceMemEntryV8(
6412642Sgiacomo.travaglini@arm.com    const TarmacContext& tarmCtx,
6512642Sgiacomo.travaglini@arm.com    uint8_t _size, Addr _addr, uint64_t _data)
6612642Sgiacomo.travaglini@arm.com      : TraceMemEntry(tarmCtx, _size, _addr, _data),
6712642Sgiacomo.travaglini@arm.com        TraceEntryV8(tarmCtx.tarmacCpuName()),
6812642Sgiacomo.travaglini@arm.com        paddr(_addr)
6912642Sgiacomo.travaglini@arm.com{
7012642Sgiacomo.travaglini@arm.com    const auto thread = tarmCtx.thread;
7112642Sgiacomo.travaglini@arm.com
7212642Sgiacomo.travaglini@arm.com    // Evaluate physical address
7313915Sgabeblack@google.com    ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
7412642Sgiacomo.travaglini@arm.com    dtb->translateFunctional(thread, addr, paddr);
7512642Sgiacomo.travaglini@arm.com}
7612642Sgiacomo.travaglini@arm.com
7712642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceRegEntryV8::TraceRegEntryV8(
7812642Sgiacomo.travaglini@arm.com    const TarmacContext& tarmCtx,
7912642Sgiacomo.travaglini@arm.com    const RegId& reg)
8012642Sgiacomo.travaglini@arm.com      : TraceRegEntry(tarmCtx, reg),
8112642Sgiacomo.travaglini@arm.com        TraceEntryV8(tarmCtx.tarmacCpuName()),
8212642Sgiacomo.travaglini@arm.com        regWidth(64)
8312642Sgiacomo.travaglini@arm.com{
8412642Sgiacomo.travaglini@arm.com}
8512642Sgiacomo.travaglini@arm.com
8612642Sgiacomo.travaglini@arm.comvoid
8712642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceRegEntryV8::updateInt(
8812642Sgiacomo.travaglini@arm.com    const TarmacContext& tarmCtx,
8912642Sgiacomo.travaglini@arm.com    RegIndex regRelIdx
9012642Sgiacomo.travaglini@arm.com)
9112642Sgiacomo.travaglini@arm.com{
9212642Sgiacomo.travaglini@arm.com    // Do not trace pseudo register accesses: invalid
9312642Sgiacomo.travaglini@arm.com    // register entry.
9412642Sgiacomo.travaglini@arm.com    if (regRelIdx > NUM_ARCH_INTREGS) {
9512642Sgiacomo.travaglini@arm.com        regValid = false;
9612642Sgiacomo.travaglini@arm.com        return;
9712642Sgiacomo.travaglini@arm.com    }
9812642Sgiacomo.travaglini@arm.com
9912642Sgiacomo.travaglini@arm.com    TraceRegEntry::updateInt(tarmCtx, regRelIdx);
10012642Sgiacomo.travaglini@arm.com
10112642Sgiacomo.travaglini@arm.com    if ((regRelIdx != PCReg) || (regRelIdx != StackPointerReg) ||
10212642Sgiacomo.travaglini@arm.com        (regRelIdx != FramePointerReg) || (regRelIdx != ReturnAddressReg)) {
10312642Sgiacomo.travaglini@arm.com
10412642Sgiacomo.travaglini@arm.com        const auto* arm_inst = static_cast<const ArmStaticInst*>(
10512642Sgiacomo.travaglini@arm.com            tarmCtx.staticInst.get()
10612642Sgiacomo.travaglini@arm.com        );
10712642Sgiacomo.travaglini@arm.com
10812642Sgiacomo.travaglini@arm.com        regWidth = (arm_inst->getIntWidth());
10912642Sgiacomo.travaglini@arm.com        if (regWidth == 32) {
11012642Sgiacomo.travaglini@arm.com            regName = "W" + std::to_string(regRelIdx);
11112642Sgiacomo.travaglini@arm.com        } else {
11212642Sgiacomo.travaglini@arm.com            regName = "X" + std::to_string(regRelIdx);
11312642Sgiacomo.travaglini@arm.com        }
11412642Sgiacomo.travaglini@arm.com    }
11512642Sgiacomo.travaglini@arm.com}
11612642Sgiacomo.travaglini@arm.com
11712642Sgiacomo.travaglini@arm.comvoid
11812642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceRegEntryV8::updateMisc(
11912642Sgiacomo.travaglini@arm.com    const TarmacContext& tarmCtx,
12012642Sgiacomo.travaglini@arm.com    RegIndex regRelIdx
12112642Sgiacomo.travaglini@arm.com)
12212642Sgiacomo.travaglini@arm.com{
12312642Sgiacomo.travaglini@arm.com    TraceRegEntry::updateMisc(tarmCtx, regRelIdx);
12412642Sgiacomo.travaglini@arm.com    // System registers are 32bit wide
12512642Sgiacomo.travaglini@arm.com    regWidth = 32;
12612642Sgiacomo.travaglini@arm.com}
12712642Sgiacomo.travaglini@arm.com
12812642Sgiacomo.travaglini@arm.comvoid
12912642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::addInstEntry(std::vector<InstPtr>& queue,
13012642Sgiacomo.travaglini@arm.com                                   const TarmacContext& tarmCtx)
13112642Sgiacomo.travaglini@arm.com{
13212642Sgiacomo.travaglini@arm.com    // Generate an instruction entry in the record and
13312642Sgiacomo.travaglini@arm.com    // add it to the Instruction Queue
13412642Sgiacomo.travaglini@arm.com    queue.push_back(
13512642Sgiacomo.travaglini@arm.com        m5::make_unique<TraceInstEntryV8>(tarmCtx, predicate)
13612642Sgiacomo.travaglini@arm.com    );
13712642Sgiacomo.travaglini@arm.com}
13812642Sgiacomo.travaglini@arm.com
13912642Sgiacomo.travaglini@arm.comvoid
14012642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::addMemEntry(std::vector<MemPtr>& queue,
14112642Sgiacomo.travaglini@arm.com                                  const TarmacContext& tarmCtx)
14212642Sgiacomo.travaglini@arm.com{
14312642Sgiacomo.travaglini@arm.com    // Generate a memory entry in the record if the record
14412642Sgiacomo.travaglini@arm.com    // implies a valid memory access, and add it to the
14512642Sgiacomo.travaglini@arm.com    // Memory Queue
14612642Sgiacomo.travaglini@arm.com    if (getMemValid()) {
14712642Sgiacomo.travaglini@arm.com        queue.push_back(
14812642Sgiacomo.travaglini@arm.com            m5::make_unique<TraceMemEntryV8>(tarmCtx,
14912642Sgiacomo.travaglini@arm.com                                             static_cast<uint8_t>(getSize()),
15012642Sgiacomo.travaglini@arm.com                                             getAddr(), getIntData())
15112642Sgiacomo.travaglini@arm.com        );
15212642Sgiacomo.travaglini@arm.com    }
15312642Sgiacomo.travaglini@arm.com}
15412642Sgiacomo.travaglini@arm.com
15512642Sgiacomo.travaglini@arm.comvoid
15612642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::addRegEntry(std::vector<RegPtr>& queue,
15712642Sgiacomo.travaglini@arm.com                                  const TarmacContext& tarmCtx)
15812642Sgiacomo.travaglini@arm.com{
15912642Sgiacomo.travaglini@arm.com    // Generate an entry for every ARM register being
16012642Sgiacomo.travaglini@arm.com    // written by the current instruction
16112642Sgiacomo.travaglini@arm.com    for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) {
16212642Sgiacomo.travaglini@arm.com
16312642Sgiacomo.travaglini@arm.com        RegId reg_id = staticInst->destRegIdx(reg);
16412642Sgiacomo.travaglini@arm.com
16512642Sgiacomo.travaglini@arm.com        // Creating a single register change entry
16612642Sgiacomo.travaglini@arm.com        auto single_reg = genRegister<TraceRegEntryV8>(tarmCtx, reg_id);
16712642Sgiacomo.travaglini@arm.com
16812642Sgiacomo.travaglini@arm.com        // Copying the entry and adding it to the "list"
16912642Sgiacomo.travaglini@arm.com        // of entries to be dumped to trace.
17012642Sgiacomo.travaglini@arm.com        queue.push_back(
17112642Sgiacomo.travaglini@arm.com            m5::make_unique<TraceRegEntryV8>(single_reg)
17212642Sgiacomo.travaglini@arm.com        );
17312642Sgiacomo.travaglini@arm.com    }
17412642Sgiacomo.travaglini@arm.com
17512642Sgiacomo.travaglini@arm.com    // Gem5 is treating CPSR flags as separate registers (CC registers),
17612642Sgiacomo.travaglini@arm.com    // in contrast with Tarmac specification: we need to merge the gem5 CC
17712642Sgiacomo.travaglini@arm.com    // entries altogether with the CPSR register and produce a single entry.
17812642Sgiacomo.travaglini@arm.com    mergeCCEntry<TraceRegEntryV8>(queue, tarmCtx);
17912642Sgiacomo.travaglini@arm.com}
18012642Sgiacomo.travaglini@arm.com
18112642Sgiacomo.travaglini@arm.comvoid
18212642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceInstEntryV8::print(
18312642Sgiacomo.travaglini@arm.com    std::ostream& outs,
18412642Sgiacomo.travaglini@arm.com    int verbosity,
18512642Sgiacomo.travaglini@arm.com    const std::string &prefix) const
18612642Sgiacomo.travaglini@arm.com{
18712642Sgiacomo.travaglini@arm.com    // If there is a valid vaddr->paddr translation, print the
18812642Sgiacomo.travaglini@arm.com    // physical address, otherwise print the virtual address only.
18912642Sgiacomo.travaglini@arm.com    std::string paddr_str = paddrValid? csprintf(":%012x",paddr) :
19012642Sgiacomo.travaglini@arm.com                                        std::string();
19112642Sgiacomo.travaglini@arm.com
19212642Sgiacomo.travaglini@arm.com    // Pad the opcode.
19312642Sgiacomo.travaglini@arm.com    std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode);
19412642Sgiacomo.travaglini@arm.com
19512642Sgiacomo.travaglini@arm.com    // Print the instruction record formatted according
19612642Sgiacomo.travaglini@arm.com    // to the Tarmac specification
19712642Sgiacomo.travaglini@arm.com    ccprintf(outs, "%s clk %s %s (%u) %08x%s %s %s %s_%s : %s\n",
19812642Sgiacomo.travaglini@arm.com             curTick(),                     /* Tick time */
19912642Sgiacomo.travaglini@arm.com             cpuName,                       /* Cpu name */
20012642Sgiacomo.travaglini@arm.com             taken? "IT" : "IS",            /* Instruction taken/skipped */
20112642Sgiacomo.travaglini@arm.com             instCount,                     /* Instruction count */
20212642Sgiacomo.travaglini@arm.com             addr,                          /* Instruction virt address */
20312642Sgiacomo.travaglini@arm.com             paddr_str,                     /* Instruction phys address */
20412642Sgiacomo.travaglini@arm.com             opcode_str,                    /* Instruction opcode */
20512642Sgiacomo.travaglini@arm.com             iSetStateToStr(isetstate),     /* Instruction Set */
20612642Sgiacomo.travaglini@arm.com             opModeToStr(mode),             /* Exception level */
20712642Sgiacomo.travaglini@arm.com             secureMode? "s" : "ns",        /* Security */
20812642Sgiacomo.travaglini@arm.com             disassemble);                  /* Instruction disass */
20912642Sgiacomo.travaglini@arm.com}
21012642Sgiacomo.travaglini@arm.com
21112642Sgiacomo.travaglini@arm.comvoid
21212642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceMemEntryV8::print(
21312642Sgiacomo.travaglini@arm.com    std::ostream& outs,
21412642Sgiacomo.travaglini@arm.com    int verbosity,
21512642Sgiacomo.travaglini@arm.com    const std::string &prefix) const
21612642Sgiacomo.travaglini@arm.com{
21712642Sgiacomo.travaglini@arm.com    // Print the memory record formatted according
21812642Sgiacomo.travaglini@arm.com    // to the Tarmac specification
21912642Sgiacomo.travaglini@arm.com    ccprintf(outs, "%s clk %s M%s%d %08x:%012x %0*x\n",
22012642Sgiacomo.travaglini@arm.com             curTick(),                 /* Tick time */
22112642Sgiacomo.travaglini@arm.com             cpuName,                   /* Cpu name */
22212642Sgiacomo.travaglini@arm.com             loadAccess? "R" : "W",     /* Access type */
22312642Sgiacomo.travaglini@arm.com             size,                      /* Access size */
22412642Sgiacomo.travaglini@arm.com             addr,                      /* Virt Memory address */
22512642Sgiacomo.travaglini@arm.com             paddr,                     /* Phys Memory address */
22612642Sgiacomo.travaglini@arm.com             size*2,                    /* Padding with access size */
22712642Sgiacomo.travaglini@arm.com             data);                     /* Memory data */
22812642Sgiacomo.travaglini@arm.com}
22912642Sgiacomo.travaglini@arm.com
23012642Sgiacomo.travaglini@arm.comvoid
23112642Sgiacomo.travaglini@arm.comTarmacTracerRecordV8::TraceRegEntryV8::print(
23212642Sgiacomo.travaglini@arm.com    std::ostream& outs,
23312642Sgiacomo.travaglini@arm.com    int verbosity,
23412642Sgiacomo.travaglini@arm.com    const std::string &prefix) const
23512642Sgiacomo.travaglini@arm.com{
23612642Sgiacomo.travaglini@arm.com    // Print the register record formatted according
23712642Sgiacomo.travaglini@arm.com    // to the Tarmac specification
23812642Sgiacomo.travaglini@arm.com    if (regValid) {
23912642Sgiacomo.travaglini@arm.com        ccprintf(outs, "%s clk %s R %s %0*x\n",
24012642Sgiacomo.travaglini@arm.com                 curTick(),            /* Tick time */
24112642Sgiacomo.travaglini@arm.com                 cpuName,              /* Cpu name */
24212642Sgiacomo.travaglini@arm.com                 regName,              /* Register name */
24312642Sgiacomo.travaglini@arm.com                 regWidth >> 2,        /* Register value padding */
24412642Sgiacomo.travaglini@arm.com                 valueLo);             /* Register value */
24512642Sgiacomo.travaglini@arm.com    }
24612642Sgiacomo.travaglini@arm.com}
24712642Sgiacomo.travaglini@arm.com
24812642Sgiacomo.travaglini@arm.com} // namespace Trace
249