/* * Copyright (c) 2017-2018 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall * not be construed as granting a license to any other intellectual * property including but not limited to intellectual property relating * to a hardware implementation of the functionality of the software * licensed hereunder. You may use the software subject to the license * terms below provided that you ensure that this notice is replicated * unmodified and in its entirety in all distributions of the software, * modified or unmodified, in source code or in binary form. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Giacomo Travaglini */ /** * @file: The file contains the informations used to generate records * for the pre-ARMv8 cores. */ #ifndef __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__ #define __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__ #include "arch/arm/tracers/tarmac_base.hh" #include "base/printable.hh" #include "config/the_isa.hh" #include "cpu/reg_class.hh" #include "cpu/static_inst.hh" namespace Trace { class TarmacContext; class TarmacTracer; /** * Returns the string representation of the instruction set being * currently run according to the Tarmac format. * * @param isetstate: enum variable (ISetState) specifying an ARM * instruction set. * @return instruction set in string format. */ std::string iSetStateToStr(TarmacBaseRecord::ISetState isetstate); /** * Returns the string representation of the ARM Operating Mode * (CPSR.M[3:0] field) according to the Tarmac format. * * @param opMode: ARM operating mode. * @return operating mode in string format. */ std::string opModeToStr(ArmISA::OperatingMode opMode); /** * TarmacTracer Record: * Record generated by the TarmacTracer for every executed instruction. * The record is composed by a set of entries, matching the tracing * capabilities provided by the Tarmac specifications: * * - Instruction Entry * - Register Entry * - Memory Entry */ class TarmacTracerRecord : public TarmacBaseRecord { public: /** Instruction Entry */ struct TraceInstEntry: public InstEntry, Printable { TraceInstEntry(const TarmacContext& tarmCtx, bool predicate); virtual void print(std::ostream& outs, int verbosity = 0, const std::string &prefix = "") const override; protected: /** Number of instructions being traced */ static uint64_t instCount; /** True if instruction is executed in secure mode */ bool secureMode; /** * Instruction size: * 16 for 16-bit Thumb Instruction * 32 otherwise (ARM and BigThumb) */ uint8_t instSize; }; /** Register Entry */ struct TraceRegEntry: public RegEntry, Printable { public: TraceRegEntry(const TarmacContext& tarmCtx, const RegId& reg); /** * This updates the register entry using the update table. It is * a required step after the register entry generation. * If unupdated, the entry will be marked as invalid. * The entry update cannot be done automatically at TraceRegEntry * construction: the entries are extended by consequent Tarmac * Tracer versions (like V8), and virtual functions should * be avoided during construction. */ void update(const TarmacContext& tarmCtx); virtual void print(std::ostream& outs, int verbosity = 0, const std::string &prefix = "") const override; protected: /** Register update functions. */ virtual void updateMisc(const TarmacContext& tarmCtx, RegIndex regRelIdx); virtual void updateCC(const TarmacContext& tarmCtx, RegIndex regRelIdx); virtual void updateFloat(const TarmacContext& tarmCtx, RegIndex regRelIdx); virtual void updateInt(const TarmacContext& tarmCtx, RegIndex regRelIdx); public: /** True if register entry is valid */ bool regValid; /** Register class */ RegClass regClass; /** Register arch number */ RegIndex regRel; /** Register name to be printed */ std::string regName; }; /** Memory Entry */ struct TraceMemEntry: public MemEntry, Printable { public: TraceMemEntry(const TarmacContext& tarmCtx, uint8_t _size, Addr _addr, uint64_t _data); virtual void print(std::ostream& outs, int verbosity = 0, const std::string &prefix = "") const override; protected: /** True if memory access is a load */ bool loadAccess; }; public: TarmacTracerRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, TheISA::PCState _pc, TarmacTracer& _tracer, const StaticInstPtr _macroStaticInst = NULL); virtual void dump() override; using InstPtr = std::unique_ptr; using MemPtr = std::unique_ptr; using RegPtr = std::unique_ptr; protected: /** Generates an Entry for the executed instruction. */ virtual void addInstEntry(std::vector& queue, const TarmacContext& ptr); /** Generates an Entry for every triggered memory access */ virtual void addMemEntry(std::vector& queue, const TarmacContext& ptr); /** Generate an Entry for every register being written. */ virtual void addRegEntry(std::vector& queue, const TarmacContext& ptr); protected: /** Generate and update a register entry. */ template RegEntry genRegister(const TarmacContext& tarmCtx, const RegId& reg) { RegEntry single_reg(tarmCtx, reg); single_reg.update(tarmCtx); return single_reg; } template void mergeCCEntry(std::vector& queue, const TarmacContext& tarmCtx) { // Find all CC Entries and move them at the end of the queue auto it = std::remove_if( queue.begin(), queue.end(), [] (RegPtr& reg) ->bool { return (reg->regClass == CCRegClass); } ); if (it != queue.end()) { // Remove all CC Entries. queue.erase(it, queue.end()); auto is_cpsr = [] (RegPtr& reg) ->bool { return (reg->regClass == MiscRegClass) && (reg->regRel == ArmISA::MISCREG_CPSR); }; // Looking for the presence of a CPSR register entry. auto cpsr_it = std::find_if( queue.begin(), queue.end(), is_cpsr ); // If CPSR entry not present, generate one if (cpsr_it == queue.end()) { RegId reg(MiscRegClass, ArmISA::MISCREG_CPSR); queue.push_back( m5::make_unique( genRegister(tarmCtx, reg)) ); } } } /** Flush queues to the trace output */ template void flushQueues(Queue& queue); template void flushQueues(Queue& queue, Args & ... args); protected: /** Reference to tracer */ TarmacTracer& tracer; }; } // namespace Trace #endif // __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__