112641Sgiacomo.travaglini@arm.com/*
212641Sgiacomo.travaglini@arm.com * Copyright (c) 2011,2017-2018 ARM Limited
312641Sgiacomo.travaglini@arm.com * All rights reserved
412641Sgiacomo.travaglini@arm.com *
512641Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall
612641Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual
712641Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating
812641Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software
912641Sgiacomo.travaglini@arm.com * licensed hereunder.  You may use the software subject to the license
1012641Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated
1112641Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software,
1212641Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form.
1312641Sgiacomo.travaglini@arm.com *
1412641Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without
1512641Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are
1612641Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright
1712641Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer;
1812641Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright
1912641Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the
2012641Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution;
2112641Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its
2212641Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from
2312641Sgiacomo.travaglini@arm.com * this software without specific prior written permission.
2412641Sgiacomo.travaglini@arm.com *
2512641Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612641Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712641Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812641Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912641Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012641Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112641Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212641Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312641Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412641Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512641Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612641Sgiacomo.travaglini@arm.com *
3712641Sgiacomo.travaglini@arm.com * Authors: Giacomo Gabrielli
3812641Sgiacomo.travaglini@arm.com */
3912641Sgiacomo.travaglini@arm.com
4012641Sgiacomo.travaglini@arm.com/**
4112641Sgiacomo.travaglini@arm.com * @file This module implements a bridge between TARMAC traces, as generated by
4212641Sgiacomo.travaglini@arm.com * other models, and gem5 (AtomicCPU model). Its goal is to detect possible
4312641Sgiacomo.travaglini@arm.com * inconsistencies between the two models as soon as they occur.  The module
4412641Sgiacomo.travaglini@arm.com * takes a TARMAC trace as input, which is used to compare the architectural
4512641Sgiacomo.travaglini@arm.com * state of the two models after each simulated instruction.
4612641Sgiacomo.travaglini@arm.com */
4712641Sgiacomo.travaglini@arm.com
4812641Sgiacomo.travaglini@arm.com#ifndef __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__
4912641Sgiacomo.travaglini@arm.com#define __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__
5012641Sgiacomo.travaglini@arm.com
5112641Sgiacomo.travaglini@arm.com#include <fstream>
5212641Sgiacomo.travaglini@arm.com#include <unordered_map>
5312641Sgiacomo.travaglini@arm.com
5412641Sgiacomo.travaglini@arm.com#include "arch/arm/registers.hh"
5512641Sgiacomo.travaglini@arm.com#include "base/trace.hh"
5612641Sgiacomo.travaglini@arm.com#include "base/types.hh"
5712641Sgiacomo.travaglini@arm.com#include "cpu/static_inst.hh"
5812641Sgiacomo.travaglini@arm.com#include "cpu/thread_context.hh"
5912641Sgiacomo.travaglini@arm.com#include "mem/request.hh"
6012641Sgiacomo.travaglini@arm.com#include "params/TarmacParser.hh"
6112641Sgiacomo.travaglini@arm.com#include "sim/insttracer.hh"
6212641Sgiacomo.travaglini@arm.com#include "tarmac_base.hh"
6312641Sgiacomo.travaglini@arm.com
6412641Sgiacomo.travaglini@arm.comnamespace Trace {
6512641Sgiacomo.travaglini@arm.com
6612641Sgiacomo.travaglini@arm.comclass TarmacParserRecord : public TarmacBaseRecord
6712641Sgiacomo.travaglini@arm.com{
6812641Sgiacomo.travaglini@arm.com  public:
6912641Sgiacomo.travaglini@arm.com    /**
7012641Sgiacomo.travaglini@arm.com     * Event triggered to check the value of the destination registers.  Needed
7112641Sgiacomo.travaglini@arm.com     * to handle some cases where registers are modified after the trace record
7212641Sgiacomo.travaglini@arm.com     * has been dumped.  E.g., the SVC instruction updates the CPSR and SPSR as
7312641Sgiacomo.travaglini@arm.com     * part of the fault handling routine.
7412641Sgiacomo.travaglini@arm.com     */
7512641Sgiacomo.travaglini@arm.com    struct TarmacParserRecordEvent: public Event
7612641Sgiacomo.travaglini@arm.com    {
7712641Sgiacomo.travaglini@arm.com        /**
7812641Sgiacomo.travaglini@arm.com         * Reference to the TARMAC trace object to which this record belongs.
7912641Sgiacomo.travaglini@arm.com         */
8012641Sgiacomo.travaglini@arm.com        TarmacParser& parent;
8112641Sgiacomo.travaglini@arm.com        /** Current thread context. */
8212641Sgiacomo.travaglini@arm.com        ThreadContext* thread;
8312641Sgiacomo.travaglini@arm.com        /** Current instruction. */
8412641Sgiacomo.travaglini@arm.com        const StaticInstPtr inst;
8512641Sgiacomo.travaglini@arm.com        /** PC of the current instruction. */
8613915Sgabeblack@google.com        ArmISA::PCState pc;
8712641Sgiacomo.travaglini@arm.com        /** True if a mismatch has been detected for this instruction. */
8812641Sgiacomo.travaglini@arm.com        bool mismatch;
8912641Sgiacomo.travaglini@arm.com        /**
9012641Sgiacomo.travaglini@arm.com         * True if a mismatch has been detected for this instruction on PC or
9112641Sgiacomo.travaglini@arm.com         * opcode.
9212641Sgiacomo.travaglini@arm.com         */
9312641Sgiacomo.travaglini@arm.com        bool mismatchOnPcOrOpcode;
9412641Sgiacomo.travaglini@arm.com
9512641Sgiacomo.travaglini@arm.com        TarmacParserRecordEvent(TarmacParser& _parent,
9612641Sgiacomo.travaglini@arm.com                                ThreadContext *_thread,
9712641Sgiacomo.travaglini@arm.com                                const StaticInstPtr _inst,
9813915Sgabeblack@google.com                                ArmISA::PCState _pc,
9912641Sgiacomo.travaglini@arm.com                                bool _mismatch,
10012641Sgiacomo.travaglini@arm.com                                bool _mismatch_on_pc_or_opcode) :
10112641Sgiacomo.travaglini@arm.com            parent(_parent), thread(_thread), inst(_inst), pc(_pc),
10212641Sgiacomo.travaglini@arm.com            mismatch(_mismatch),
10312641Sgiacomo.travaglini@arm.com            mismatchOnPcOrOpcode(_mismatch_on_pc_or_opcode)
10412641Sgiacomo.travaglini@arm.com        {
10512641Sgiacomo.travaglini@arm.com        }
10612641Sgiacomo.travaglini@arm.com
10712641Sgiacomo.travaglini@arm.com        void process();
10812641Sgiacomo.travaglini@arm.com        const char *description() const;
10912641Sgiacomo.travaglini@arm.com    };
11012641Sgiacomo.travaglini@arm.com
11112641Sgiacomo.travaglini@arm.com    struct ParserInstEntry : public InstEntry
11212641Sgiacomo.travaglini@arm.com    {
11312641Sgiacomo.travaglini@arm.com      public:
11412641Sgiacomo.travaglini@arm.com        uint64_t seq_num;
11512641Sgiacomo.travaglini@arm.com    };
11612641Sgiacomo.travaglini@arm.com
11712641Sgiacomo.travaglini@arm.com    struct ParserRegEntry : public RegEntry
11812641Sgiacomo.travaglini@arm.com    {
11912641Sgiacomo.travaglini@arm.com      public:
12012641Sgiacomo.travaglini@arm.com        char repr[16];
12112641Sgiacomo.travaglini@arm.com    };
12212641Sgiacomo.travaglini@arm.com
12312641Sgiacomo.travaglini@arm.com    struct ParserMemEntry : public MemEntry
12412641Sgiacomo.travaglini@arm.com    { };
12512641Sgiacomo.travaglini@arm.com
12612641Sgiacomo.travaglini@arm.com    static const int MaxLineLength = 256;
12712641Sgiacomo.travaglini@arm.com
12812641Sgiacomo.travaglini@arm.com    /**
12912641Sgiacomo.travaglini@arm.com     * Print a mismatch header containing the instruction fields as reported
13012641Sgiacomo.travaglini@arm.com     * by gem5.
13112641Sgiacomo.travaglini@arm.com     */
13212641Sgiacomo.travaglini@arm.com    static void printMismatchHeader(const StaticInstPtr inst,
13313915Sgabeblack@google.com                                    ArmISA::PCState pc);
13412641Sgiacomo.travaglini@arm.com
13512641Sgiacomo.travaglini@arm.com    TarmacParserRecord(Tick _when, ThreadContext *_thread,
13613915Sgabeblack@google.com                       const StaticInstPtr _staticInst, ArmISA::PCState _pc,
13712641Sgiacomo.travaglini@arm.com                       TarmacParser& _parent,
13812641Sgiacomo.travaglini@arm.com                       const StaticInstPtr _macroStaticInst = NULL);
13912641Sgiacomo.travaglini@arm.com
14012641Sgiacomo.travaglini@arm.com    void dump() override;
14112641Sgiacomo.travaglini@arm.com
14212641Sgiacomo.travaglini@arm.com    /**
14312641Sgiacomo.travaglini@arm.com     * Performs a memory access to read the value written by a previous write.
14412641Sgiacomo.travaglini@arm.com     * @return False if the result of the memory access should be ignored
14512641Sgiacomo.travaglini@arm.com     * (faulty memory access, etc.).
14612641Sgiacomo.travaglini@arm.com     */
14712641Sgiacomo.travaglini@arm.com    bool readMemNoEffect(Addr addr, uint8_t *data, unsigned size,
14812641Sgiacomo.travaglini@arm.com                         unsigned flags);
14912641Sgiacomo.travaglini@arm.com
15012641Sgiacomo.travaglini@arm.com  private:
15112641Sgiacomo.travaglini@arm.com    /**
15212641Sgiacomo.travaglini@arm.com     * Advances the TARMAC trace up to the next instruction,
15312641Sgiacomo.travaglini@arm.com     * register, or memory access record. The collected data is stored
15412641Sgiacomo.travaglini@arm.com     * in one of {inst/reg/mem}_record.
15512641Sgiacomo.travaglini@arm.com     * @return False if EOF is reached.
15612641Sgiacomo.travaglini@arm.com     */
15712641Sgiacomo.travaglini@arm.com    bool advanceTrace();
15812641Sgiacomo.travaglini@arm.com
15912641Sgiacomo.travaglini@arm.com    /** Returns the string representation of an instruction set state. */
16012641Sgiacomo.travaglini@arm.com    const char *iSetStateToStr(ISetState isetstate) const;
16112641Sgiacomo.travaglini@arm.com
16212641Sgiacomo.travaglini@arm.com    /** Buffer for instruction trace records. */
16312641Sgiacomo.travaglini@arm.com    static ParserInstEntry instRecord;
16412641Sgiacomo.travaglini@arm.com
16512641Sgiacomo.travaglini@arm.com    /** Buffer for register trace records. */
16612641Sgiacomo.travaglini@arm.com    static ParserRegEntry regRecord;
16712641Sgiacomo.travaglini@arm.com
16812641Sgiacomo.travaglini@arm.com    /** Buffer for memory access trace records (stores only). */
16912641Sgiacomo.travaglini@arm.com    static ParserMemEntry memRecord;
17012641Sgiacomo.travaglini@arm.com
17112641Sgiacomo.travaglini@arm.com    /** Type of last parsed record. */
17212641Sgiacomo.travaglini@arm.com    static TarmacRecordType currRecordType;
17312641Sgiacomo.travaglini@arm.com
17412641Sgiacomo.travaglini@arm.com    /** Buffer used for trace file parsing. */
17512641Sgiacomo.travaglini@arm.com    static char buf[MaxLineLength];
17612641Sgiacomo.travaglini@arm.com
17712641Sgiacomo.travaglini@arm.com    /** List of records of destination registers. */
17812641Sgiacomo.travaglini@arm.com    static std::list<ParserRegEntry> destRegRecords;
17912641Sgiacomo.travaglini@arm.com
18012641Sgiacomo.travaglini@arm.com    /** Map from misc. register names to indexes. */
18112641Sgiacomo.travaglini@arm.com    using MiscRegMap = std::unordered_map<std::string, RegIndex>;
18212641Sgiacomo.travaglini@arm.com    static MiscRegMap miscRegMap;
18312641Sgiacomo.travaglini@arm.com
18412641Sgiacomo.travaglini@arm.com    /**
18512641Sgiacomo.travaglini@arm.com     * True if a TARMAC instruction record has already been parsed for this
18612641Sgiacomo.travaglini@arm.com     * instruction.
18712641Sgiacomo.travaglini@arm.com     */
18812641Sgiacomo.travaglini@arm.com    bool parsingStarted;
18912641Sgiacomo.travaglini@arm.com
19012641Sgiacomo.travaglini@arm.com    /** True if a mismatch has been detected for this instruction. */
19112641Sgiacomo.travaglini@arm.com    bool mismatch;
19212641Sgiacomo.travaglini@arm.com
19312641Sgiacomo.travaglini@arm.com    /**
19412641Sgiacomo.travaglini@arm.com     * True if a mismatch has been detected for this instruction on PC or
19512641Sgiacomo.travaglini@arm.com     * opcode.
19612641Sgiacomo.travaglini@arm.com     */
19712641Sgiacomo.travaglini@arm.com    bool mismatchOnPcOrOpcode;
19812641Sgiacomo.travaglini@arm.com
19912641Sgiacomo.travaglini@arm.com    /** Request for memory write checks. */
20012749Sgiacomo.travaglini@arm.com    RequestPtr memReq;
20112641Sgiacomo.travaglini@arm.com
20212641Sgiacomo.travaglini@arm.com  protected:
20312641Sgiacomo.travaglini@arm.com    TarmacParser& parent;
20412641Sgiacomo.travaglini@arm.com};
20512641Sgiacomo.travaglini@arm.com
20612641Sgiacomo.travaglini@arm.com/**
20712641Sgiacomo.travaglini@arm.com * Tarmac Parser: this tracer parses an existing Tarmac trace and it
20812641Sgiacomo.travaglini@arm.com * diffs it with gem5 simulation status, comparing results and
20912641Sgiacomo.travaglini@arm.com * reporting architectural mismatches if any.
21012641Sgiacomo.travaglini@arm.com */
21112641Sgiacomo.travaglini@arm.comclass TarmacParser : public InstTracer
21212641Sgiacomo.travaglini@arm.com{
21312641Sgiacomo.travaglini@arm.com    friend class TarmacParserRecord;
21412641Sgiacomo.travaglini@arm.com
21512641Sgiacomo.travaglini@arm.com  public:
21612641Sgiacomo.travaglini@arm.com    typedef TarmacParserParams Params;
21712641Sgiacomo.travaglini@arm.com
21812641Sgiacomo.travaglini@arm.com    TarmacParser(const Params *p) : InstTracer(p), startPc(p->start_pc),
21912641Sgiacomo.travaglini@arm.com                                    exitOnDiff(p->exit_on_diff),
22012641Sgiacomo.travaglini@arm.com                                    exitOnInsnDiff(p->exit_on_insn_diff),
22112641Sgiacomo.travaglini@arm.com                                    memWrCheck(p->mem_wr_check),
22212641Sgiacomo.travaglini@arm.com                                    ignoredAddrRange(p->ignore_mem_addr),
22312641Sgiacomo.travaglini@arm.com                                    cpuId(p->cpu_id),
22412641Sgiacomo.travaglini@arm.com                                    macroopInProgress(false)
22512641Sgiacomo.travaglini@arm.com    {
22612641Sgiacomo.travaglini@arm.com        assert(!(exitOnDiff && exitOnInsnDiff));
22712641Sgiacomo.travaglini@arm.com
22812641Sgiacomo.travaglini@arm.com        trace.open(p->path_to_trace.c_str());
22912641Sgiacomo.travaglini@arm.com        if (startPc == 0x0) {
23012641Sgiacomo.travaglini@arm.com            started = true;
23112641Sgiacomo.travaglini@arm.com        } else {
23212641Sgiacomo.travaglini@arm.com            advanceTraceToStartPc();
23312641Sgiacomo.travaglini@arm.com            started = false;
23412641Sgiacomo.travaglini@arm.com        }
23512641Sgiacomo.travaglini@arm.com    }
23612641Sgiacomo.travaglini@arm.com
23712641Sgiacomo.travaglini@arm.com    virtual ~TarmacParser()
23812641Sgiacomo.travaglini@arm.com    {
23912641Sgiacomo.travaglini@arm.com        trace.close();
24012641Sgiacomo.travaglini@arm.com    }
24112641Sgiacomo.travaglini@arm.com
24212641Sgiacomo.travaglini@arm.com    InstRecord *
24312641Sgiacomo.travaglini@arm.com    getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst,
24413915Sgabeblack@google.com                  ArmISA::PCState pc,
24512641Sgiacomo.travaglini@arm.com                  const StaticInstPtr macroStaticInst = NULL)
24612641Sgiacomo.travaglini@arm.com    {
24712641Sgiacomo.travaglini@arm.com        if (!started && pc.pc() == startPc)
24812641Sgiacomo.travaglini@arm.com            started = true;
24912641Sgiacomo.travaglini@arm.com
25012641Sgiacomo.travaglini@arm.com        if (started)
25112641Sgiacomo.travaglini@arm.com            return new TarmacParserRecord(when, tc, staticInst, pc, *this,
25212641Sgiacomo.travaglini@arm.com                                          macroStaticInst);
25312641Sgiacomo.travaglini@arm.com        else
25412641Sgiacomo.travaglini@arm.com            return NULL;
25512641Sgiacomo.travaglini@arm.com    }
25612641Sgiacomo.travaglini@arm.com
25712641Sgiacomo.travaglini@arm.com  private:
25812641Sgiacomo.travaglini@arm.com    /** Helper function to advance the trace up to startPc. */
25912641Sgiacomo.travaglini@arm.com    void advanceTraceToStartPc();
26012641Sgiacomo.travaglini@arm.com
26112641Sgiacomo.travaglini@arm.com    /** TARMAC trace file. */
26212641Sgiacomo.travaglini@arm.com    std::ifstream trace;
26312641Sgiacomo.travaglini@arm.com
26412641Sgiacomo.travaglini@arm.com    /**
26512641Sgiacomo.travaglini@arm.com     * Tracing starts when the PC gets this value for the first time (ignored
26612641Sgiacomo.travaglini@arm.com     * if 0x0).
26712641Sgiacomo.travaglini@arm.com     */
26812641Sgiacomo.travaglini@arm.com    Addr startPc;
26912641Sgiacomo.travaglini@arm.com
27012641Sgiacomo.travaglini@arm.com    /**
27112641Sgiacomo.travaglini@arm.com     * If true, the simulation is stopped as the first mismatch is detected.
27212641Sgiacomo.travaglini@arm.com     */
27312641Sgiacomo.travaglini@arm.com    bool exitOnDiff;
27412641Sgiacomo.travaglini@arm.com
27512641Sgiacomo.travaglini@arm.com    /**
27612641Sgiacomo.travaglini@arm.com     * If true, the simulation is stopped as the first mismatch is detected on
27712641Sgiacomo.travaglini@arm.com     * PC or opcode.
27812641Sgiacomo.travaglini@arm.com     */
27912641Sgiacomo.travaglini@arm.com    bool exitOnInsnDiff;
28012641Sgiacomo.travaglini@arm.com
28112641Sgiacomo.travaglini@arm.com    /** If true, memory write accesses are checked. */
28212641Sgiacomo.travaglini@arm.com    bool memWrCheck;
28312641Sgiacomo.travaglini@arm.com
28412641Sgiacomo.travaglini@arm.com    /** Ignored addresses (ignored if empty). */
28512641Sgiacomo.travaglini@arm.com    AddrRange ignoredAddrRange;
28612641Sgiacomo.travaglini@arm.com
28712641Sgiacomo.travaglini@arm.com    /** If true, the trace format includes the CPU id. */
28812641Sgiacomo.travaglini@arm.com    bool cpuId;
28912641Sgiacomo.travaglini@arm.com
29012641Sgiacomo.travaglini@arm.com    /** True if tracing has started. */
29112641Sgiacomo.travaglini@arm.com    bool started;
29212641Sgiacomo.travaglini@arm.com
29312641Sgiacomo.travaglini@arm.com    /** True if a macroop is currently in progress. */
29412641Sgiacomo.travaglini@arm.com    bool macroopInProgress;
29512641Sgiacomo.travaglini@arm.com};
29612641Sgiacomo.travaglini@arm.com
29712641Sgiacomo.travaglini@arm.com} // namespace Trace
29812641Sgiacomo.travaglini@arm.com
29912641Sgiacomo.travaglini@arm.com#endif // __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__
300