blob: 96678b07b416579e1442e1489f5acb903e5fb763 [file] [log] [blame]
/*
* Copyright (c) 2011,2017-2019 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.
*/
#include <algorithm>
#include <cctype>
#include <cstring>
#include <iomanip>
#include <string>
#include "arch/arm/tracers/tarmac_parser.hh"
#include "arch/arm/tlb.hh"
#include "arch/arm/insts/static_inst.hh"
#include "config/the_isa.hh"
#include "cpu/static_inst.hh"
#include "cpu/thread_context.hh"
#include "mem/packet.hh"
#include "mem/port_proxy.hh"
#include "sim/core.hh"
#include "sim/faults.hh"
#include "sim/sim_exit.hh"
using namespace std;
using namespace ArmISA;
namespace Trace {
// TARMAC Parser static variables
const int TarmacParserRecord::MaxLineLength;
int8_t TarmacParserRecord::maxVectorLength = 0;
TarmacParserRecord::ParserInstEntry TarmacParserRecord::instRecord;
TarmacParserRecord::ParserRegEntry TarmacParserRecord::regRecord;
TarmacParserRecord::ParserMemEntry TarmacParserRecord::memRecord;
TarmacBaseRecord::TarmacRecordType TarmacParserRecord::currRecordType;
list<TarmacParserRecord::ParserRegEntry> TarmacParserRecord::destRegRecords;
char TarmacParserRecord::buf[TarmacParserRecord::MaxLineLength];
TarmacParserRecord::MiscRegMap TarmacParserRecord::miscRegMap = {
{ "cpsr", MISCREG_CPSR },
{ "nzcv", MISCREG_NZCV },
// AArch32 CP14 registers
{ "dbgdidr", MISCREG_DBGDIDR },
{ "dbgdscrint", MISCREG_DBGDSCRint },
{ "dbgdccint", MISCREG_DBGDCCINT },
{ "dbgdtrtxint", MISCREG_DBGDTRTXint },
{ "dbgdtrrxint", MISCREG_DBGDTRRXint },
{ "dbgwfar", MISCREG_DBGWFAR },
{ "dbgvcr", MISCREG_DBGVCR },
{ "dbgdtrrxext", MISCREG_DBGDTRRXext },
{ "dbgdscrext", MISCREG_DBGDSCRext },
{ "dbgdtrtxext", MISCREG_DBGDTRTXext },
{ "dbgoseccr", MISCREG_DBGOSECCR },
{ "dbgbvr0", MISCREG_DBGBVR0 },
{ "dbgbvr1", MISCREG_DBGBVR1 },
{ "dbgbvr2", MISCREG_DBGBVR2 },
{ "dbgbvr3", MISCREG_DBGBVR3 },
{ "dbgbvr4", MISCREG_DBGBVR4 },
{ "dbgbvr5", MISCREG_DBGBVR5 },
{ "dbgbcr0", MISCREG_DBGBCR0 },
{ "dbgbcr1", MISCREG_DBGBCR1 },
{ "dbgbcr2", MISCREG_DBGBCR2 },
{ "dbgbcr3", MISCREG_DBGBCR3 },
{ "dbgbcr4", MISCREG_DBGBCR4 },
{ "dbgbcr5", MISCREG_DBGBCR5 },
{ "dbgwvr0", MISCREG_DBGWVR0 },
{ "dbgwvr1", MISCREG_DBGWVR1 },
{ "dbgwvr2", MISCREG_DBGWVR2 },
{ "dbgwvr3", MISCREG_DBGWVR3 },
{ "dbgwcr0", MISCREG_DBGWCR0 },
{ "dbgwcr1", MISCREG_DBGWCR1 },
{ "dbgwcr2", MISCREG_DBGWCR2 },
{ "dbgwcr3", MISCREG_DBGWCR3 },
{ "dbgdrar", MISCREG_DBGDRAR },
{ "dbgbxvr4", MISCREG_DBGBXVR4 },
{ "dbgbxvr5", MISCREG_DBGBXVR5 },
{ "dbgoslar", MISCREG_DBGOSLAR },
{ "dbgoslsr", MISCREG_DBGOSLSR },
{ "dbgosdlr", MISCREG_DBGOSDLR },
{ "dbgprcr", MISCREG_DBGPRCR },
{ "dbgdsar", MISCREG_DBGDSAR },
{ "dbgclaimset", MISCREG_DBGCLAIMSET },
{ "dbgclaimclr", MISCREG_DBGCLAIMCLR },
{ "dbgauthstatus", MISCREG_DBGAUTHSTATUS },
{ "dbgdevid2", MISCREG_DBGDEVID2 },
{ "dbgdevid1", MISCREG_DBGDEVID1 },
{ "dbgdevid0", MISCREG_DBGDEVID0 },
{ "teecr", MISCREG_TEECR },
{ "jidr", MISCREG_JIDR },
{ "teehbr", MISCREG_TEEHBR },
{ "joscr", MISCREG_JOSCR },
{ "jmcr", MISCREG_JMCR },
// AArch32 CP15 registers
{ "midr", MISCREG_MIDR },
{ "ctr", MISCREG_CTR },
{ "tcmtr", MISCREG_TCMTR },
{ "tlbtr", MISCREG_TLBTR },
{ "mpidr", MISCREG_MPIDR },
{ "revidr", MISCREG_REVIDR },
{ "id_pfr0", MISCREG_ID_PFR0 },
{ "id_pfr1", MISCREG_ID_PFR1 },
{ "id_dfr0", MISCREG_ID_DFR0 },
{ "id_afr0", MISCREG_ID_AFR0 },
{ "id_mmfr0", MISCREG_ID_MMFR0 },
{ "id_mmfr1", MISCREG_ID_MMFR1 },
{ "id_mmfr2", MISCREG_ID_MMFR2 },
{ "id_mmfr3", MISCREG_ID_MMFR3 },
{ "id_isar0", MISCREG_ID_ISAR0 },
{ "id_isar1", MISCREG_ID_ISAR1 },
{ "id_isar2", MISCREG_ID_ISAR2 },
{ "id_isar3", MISCREG_ID_ISAR3 },
{ "id_isar4", MISCREG_ID_ISAR4 },
{ "id_isar5", MISCREG_ID_ISAR5 },
{ "ccsidr", MISCREG_CCSIDR },
{ "clidr", MISCREG_CLIDR },
{ "aidr", MISCREG_AIDR },
{ "csselr_ns", MISCREG_CSSELR_NS },
{ "csselr_s", MISCREG_CSSELR_S },
{ "vpidr", MISCREG_VPIDR },
{ "vmpidr", MISCREG_VMPIDR },
{ "sctlr_ns", MISCREG_SCTLR_NS },
{ "sctlr_s", MISCREG_SCTLR_S },
{ "actlr_ns", MISCREG_ACTLR_NS },
{ "actlr_s", MISCREG_ACTLR_S },
{ "cpacr", MISCREG_CPACR },
{ "scr", MISCREG_SCR },
{ "sder", MISCREG_SDER },
{ "nsacr", MISCREG_NSACR },
{ "hsctlr", MISCREG_HSCTLR },
{ "hactlr", MISCREG_HACTLR },
{ "hcr", MISCREG_HCR },
{ "hcr2", MISCREG_HCR2 },
{ "hdcr", MISCREG_HDCR },
{ "hcptr", MISCREG_HCPTR },
{ "hstr", MISCREG_HSTR },
{ "hacr", MISCREG_HACR },
{ "ttbr0_ns", MISCREG_TTBR0_NS },
{ "ttbr0_s", MISCREG_TTBR0_S },
{ "ttbr1_ns", MISCREG_TTBR1_NS },
{ "ttbr1_s", MISCREG_TTBR1_S },
{ "ttbcr_ns", MISCREG_TTBCR_NS },
{ "ttbcr_s", MISCREG_TTBCR_S },
{ "htcr", MISCREG_HTCR },
{ "vtcr", MISCREG_VTCR },
{ "dacr_ns", MISCREG_DACR_NS },
{ "dacr_s", MISCREG_DACR_S },
{ "dfsr_ns", MISCREG_DFSR_NS },
{ "dfsr_s", MISCREG_DFSR_S },
{ "ifsr_ns", MISCREG_IFSR_NS },
{ "ifsr_s", MISCREG_IFSR_S },
{ "adfsr_ns", MISCREG_ADFSR_NS },
{ "adfsr_s", MISCREG_ADFSR_S },
{ "aifsr_ns", MISCREG_AIFSR_NS },
{ "aifsr_s", MISCREG_AIFSR_S },
{ "hadfsr", MISCREG_HADFSR },
{ "haifsr", MISCREG_HAIFSR },
{ "hsr", MISCREG_HSR },
{ "dfar_ns", MISCREG_DFAR_NS },
{ "dfar_s", MISCREG_DFAR_S },
{ "ifar_ns", MISCREG_IFAR_NS },
{ "ifar_s", MISCREG_IFAR_S },
{ "hdfar", MISCREG_HDFAR },
{ "hifar", MISCREG_HIFAR },
{ "hpfar", MISCREG_HPFAR },
{ "icialluis", MISCREG_ICIALLUIS },
{ "bpiallis", MISCREG_BPIALLIS },
{ "par_ns", MISCREG_PAR_NS },
{ "par_s", MISCREG_PAR_S },
{ "iciallu", MISCREG_ICIALLU },
{ "icimvau", MISCREG_ICIMVAU },
{ "cp15isb", MISCREG_CP15ISB },
{ "bpiall", MISCREG_BPIALL },
{ "bpimva", MISCREG_BPIMVA },
{ "dcimvac", MISCREG_DCIMVAC },
{ "dcisw", MISCREG_DCISW },
{ "ats1cpr", MISCREG_ATS1CPR },
{ "ats1cpw", MISCREG_ATS1CPW },
{ "ats1cur", MISCREG_ATS1CUR },
{ "ats1cuw", MISCREG_ATS1CUW },
{ "ats12nsopr", MISCREG_ATS12NSOPR },
{ "ats12nsopw", MISCREG_ATS12NSOPW },
{ "ats12nsour", MISCREG_ATS12NSOUR },
{ "ats12nsouw", MISCREG_ATS12NSOUW },
{ "dccmvac", MISCREG_DCCMVAC },
{ "dccsw", MISCREG_DCCSW },
{ "cp15dsb", MISCREG_CP15DSB },
{ "cp15dmb", MISCREG_CP15DMB },
{ "dccmvau", MISCREG_DCCMVAU },
{ "dccimvac", MISCREG_DCCIMVAC },
{ "dccisw", MISCREG_DCCISW },
{ "ats1hr", MISCREG_ATS1HR },
{ "ats1hw", MISCREG_ATS1HW },
{ "tlbiallis", MISCREG_TLBIALLIS },
{ "tlbimvais", MISCREG_TLBIMVAIS },
{ "tlbiasidis", MISCREG_TLBIASIDIS },
{ "tlbimvaais", MISCREG_TLBIMVAAIS },
{ "tlbimvalis", MISCREG_TLBIMVALIS },
{ "tlbimvaalis", MISCREG_TLBIMVAALIS },
{ "itlbiall", MISCREG_ITLBIALL },
{ "itlbimva", MISCREG_ITLBIMVA },
{ "itlbiasid", MISCREG_ITLBIASID },
{ "dtlbiall", MISCREG_DTLBIALL },
{ "dtlbimva", MISCREG_DTLBIMVA },
{ "dtlbiasid", MISCREG_DTLBIASID },
{ "tlbiall", MISCREG_TLBIALL },
{ "tlbimva", MISCREG_TLBIMVA },
{ "tlbiasid", MISCREG_TLBIASID },
{ "tlbimvaa", MISCREG_TLBIMVAA },
{ "tlbimval", MISCREG_TLBIMVAL },
{ "tlbimvaal", MISCREG_TLBIMVAAL },
{ "tlbiipas2is", MISCREG_TLBIIPAS2IS },
{ "tlbiipas2lis", MISCREG_TLBIIPAS2LIS },
{ "tlbiallhis", MISCREG_TLBIALLHIS },
{ "tlbimvahis", MISCREG_TLBIMVAHIS },
{ "tlbiallnsnhis", MISCREG_TLBIALLNSNHIS },
{ "tlbimvalhis", MISCREG_TLBIMVALHIS },
{ "tlbiipas2", MISCREG_TLBIIPAS2 },
{ "tlbiipas2l", MISCREG_TLBIIPAS2L },
{ "tlbiallh", MISCREG_TLBIALLH },
{ "tlbimvah", MISCREG_TLBIMVAH },
{ "tlbiallnsnh", MISCREG_TLBIALLNSNH },
{ "tlbimvalh", MISCREG_TLBIMVALH },
{ "pmcr", MISCREG_PMCR },
{ "pmcntenset", MISCREG_PMCNTENSET },
{ "pmcntenclr", MISCREG_PMCNTENCLR },
{ "pmovsr", MISCREG_PMOVSR },
{ "pmswinc", MISCREG_PMSWINC },
{ "pmselr", MISCREG_PMSELR },
{ "pmceid0", MISCREG_PMCEID0 },
{ "pmceid1", MISCREG_PMCEID1 },
{ "pmccntr", MISCREG_PMCCNTR },
{ "pmxevtyper", MISCREG_PMXEVTYPER },
{ "pmccfiltr", MISCREG_PMCCFILTR },
{ "pmxevcntr", MISCREG_PMXEVCNTR },
{ "pmuserenr", MISCREG_PMUSERENR },
{ "pmintenset", MISCREG_PMINTENSET },
{ "pmintenclr", MISCREG_PMINTENCLR },
{ "pmovsset", MISCREG_PMOVSSET },
{ "l2ctlr", MISCREG_L2CTLR },
{ "l2ectlr", MISCREG_L2ECTLR },
{ "prrr_ns", MISCREG_PRRR_NS },
{ "prrr_s", MISCREG_PRRR_S },
{ "mair0_ns", MISCREG_MAIR0_NS },
{ "mair0_s", MISCREG_MAIR0_S },
{ "nmrr_ns", MISCREG_NMRR_NS },
{ "nmrr_s", MISCREG_NMRR_S },
{ "mair1_ns", MISCREG_MAIR1_NS },
{ "mair1_s", MISCREG_MAIR1_S },
{ "amair0_ns", MISCREG_AMAIR0_NS },
{ "amair0_s", MISCREG_AMAIR0_S },
{ "amair1_ns", MISCREG_AMAIR1_NS },
{ "amair1_s", MISCREG_AMAIR1_S },
{ "hmair0", MISCREG_HMAIR0 },
{ "hmair1", MISCREG_HMAIR1 },
{ "hamair0", MISCREG_HAMAIR0 },
{ "hamair1", MISCREG_HAMAIR1 },
{ "vbar_ns", MISCREG_VBAR_NS },
{ "vbar_s", MISCREG_VBAR_S },
{ "mvbar", MISCREG_MVBAR },
{ "rmr", MISCREG_RMR },
{ "isr", MISCREG_ISR },
{ "hvbar", MISCREG_HVBAR },
{ "fcseidr", MISCREG_FCSEIDR },
{ "contextidr_ns", MISCREG_CONTEXTIDR_NS },
{ "contextidr_s", MISCREG_CONTEXTIDR_S },
{ "tpidrurw_ns", MISCREG_TPIDRURW_NS },
{ "tpidrurw_s", MISCREG_TPIDRURW_S },
{ "tpidruro_ns", MISCREG_TPIDRURO_NS },
{ "tpidruro_s", MISCREG_TPIDRURO_S },
{ "tpidrprw_ns", MISCREG_TPIDRPRW_NS },
{ "tpidrprw_s", MISCREG_TPIDRPRW_S },
{ "htpidr", MISCREG_HTPIDR },
{ "cntfrq", MISCREG_CNTFRQ },
{ "cntkctl", MISCREG_CNTKCTL },
{ "cntp_tval_ns", MISCREG_CNTP_TVAL_NS },
{ "cntp_tval_s", MISCREG_CNTP_TVAL_S },
{ "cntp_ctl_ns", MISCREG_CNTP_CTL_NS },
{ "cntp_ctl_s", MISCREG_CNTP_CTL_S },
{ "cntv_tval", MISCREG_CNTV_TVAL },
{ "cntv_ctl", MISCREG_CNTV_CTL },
{ "cnthctl", MISCREG_CNTHCTL },
{ "cnthp_tval", MISCREG_CNTHP_TVAL },
{ "cnthp_ctl", MISCREG_CNTHP_CTL },
{ "il1data0", MISCREG_IL1DATA0 },
{ "il1data1", MISCREG_IL1DATA1 },
{ "il1data2", MISCREG_IL1DATA2 },
{ "il1data3", MISCREG_IL1DATA3 },
{ "dl1data0", MISCREG_DL1DATA0 },
{ "dl1data1", MISCREG_DL1DATA1 },
{ "dl1data2", MISCREG_DL1DATA2 },
{ "dl1data3", MISCREG_DL1DATA3 },
{ "dl1data4", MISCREG_DL1DATA4 },
{ "ramindex", MISCREG_RAMINDEX },
{ "l2actlr", MISCREG_L2ACTLR },
{ "cbar", MISCREG_CBAR },
{ "httbr", MISCREG_HTTBR },
{ "vttbr", MISCREG_VTTBR },
{ "cntpct", MISCREG_CNTPCT },
{ "cntvct", MISCREG_CNTVCT },
{ "cntp_cval_ns", MISCREG_CNTP_CVAL_NS },
{ "cntp_cval_s", MISCREG_CNTP_CVAL_S },
{ "cntv_cval", MISCREG_CNTV_CVAL },
{ "cntvoff", MISCREG_CNTVOFF },
{ "cnthp_cval", MISCREG_CNTHP_CVAL },
{ "cpumerrsr", MISCREG_CPUMERRSR },
{ "l2merrsr", MISCREG_L2MERRSR },
// AArch64 registers (Op0=2)
{ "mdccint_el1", MISCREG_MDCCINT_EL1 },
{ "osdtrrx_el1", MISCREG_OSDTRRX_EL1 },
{ "mdscr_el1", MISCREG_MDSCR_EL1 },
{ "osdtrtx_el1", MISCREG_OSDTRTX_EL1 },
{ "oseccr_el1", MISCREG_OSECCR_EL1 },
{ "dbgbvr0_el1", MISCREG_DBGBVR0_EL1 },
{ "dbgbvr1_el1", MISCREG_DBGBVR1_EL1 },
{ "dbgbvr2_el1", MISCREG_DBGBVR2_EL1 },
{ "dbgbvr3_el1", MISCREG_DBGBVR3_EL1 },
{ "dbgbvr4_el1", MISCREG_DBGBVR4_EL1 },
{ "dbgbvr5_el1", MISCREG_DBGBVR5_EL1 },
{ "dbgbcr0_el1", MISCREG_DBGBCR0_EL1 },
{ "dbgbcr1_el1", MISCREG_DBGBCR1_EL1 },
{ "dbgbcr2_el1", MISCREG_DBGBCR2_EL1 },
{ "dbgbcr3_el1", MISCREG_DBGBCR3_EL1 },
{ "dbgbcr4_el1", MISCREG_DBGBCR4_EL1 },
{ "dbgbcr5_el1", MISCREG_DBGBCR5_EL1 },
{ "dbgwvr0_el1", MISCREG_DBGWVR0_EL1 },
{ "dbgwvr1_el1", MISCREG_DBGWVR1_EL1 },
{ "dbgwvr2_el1", MISCREG_DBGWVR2_EL1 },
{ "dbgwvr3_el1", MISCREG_DBGWVR3_EL1 },
{ "dbgwcr0_el1", MISCREG_DBGWCR0_EL1 },
{ "dbgwcr1_el1", MISCREG_DBGWCR1_EL1 },
{ "dbgwcr2_el1", MISCREG_DBGWCR2_EL1 },
{ "dbgwcr3_el1", MISCREG_DBGWCR3_EL1 },
{ "mdccsr_el0", MISCREG_MDCCSR_EL0 },
{ "mddtr_el0", MISCREG_MDDTR_EL0 },
{ "mddtrtx_el0", MISCREG_MDDTRTX_EL0 },
{ "mddtrrx_el0", MISCREG_MDDTRRX_EL0 },
{ "dbgvcr32_el2", MISCREG_DBGVCR32_EL2 },
{ "mdrar_el1", MISCREG_MDRAR_EL1 },
{ "oslar_el1", MISCREG_OSLAR_EL1 },
{ "oslsr_el1", MISCREG_OSLSR_EL1 },
{ "osdlr_el1", MISCREG_OSDLR_EL1 },
{ "dbgprcr_el1", MISCREG_DBGPRCR_EL1 },
{ "dbgclaimset_el1", MISCREG_DBGCLAIMSET_EL1 },
{ "dbgclaimclr_el1", MISCREG_DBGCLAIMCLR_EL1 },
{ "dbgauthstatus_el1", MISCREG_DBGAUTHSTATUS_EL1 },
{ "teecr32_el1", MISCREG_TEECR32_EL1 },
{ "teehbr32_el1", MISCREG_TEEHBR32_EL1 },
// AArch64 registers (Op0=1,3)
{ "midr_el1", MISCREG_MIDR_EL1 },
{ "mpidr_el1", MISCREG_MPIDR_EL1 },
{ "revidr_el1", MISCREG_REVIDR_EL1 },
{ "id_pfr0_el1", MISCREG_ID_PFR0_EL1 },
{ "id_pfr1_el1", MISCREG_ID_PFR1_EL1 },
{ "id_dfr0_el1", MISCREG_ID_DFR0_EL1 },
{ "id_afr0_el1", MISCREG_ID_AFR0_EL1 },
{ "id_mmfr0_el1", MISCREG_ID_MMFR0_EL1 },
{ "id_mmfr1_el1", MISCREG_ID_MMFR1_EL1 },
{ "id_mmfr2_el1", MISCREG_ID_MMFR2_EL1 },
{ "id_mmfr3_el1", MISCREG_ID_MMFR3_EL1 },
{ "id_isar0_el1", MISCREG_ID_ISAR0_EL1 },
{ "id_isar1_el1", MISCREG_ID_ISAR1_EL1 },
{ "id_isar2_el1", MISCREG_ID_ISAR2_EL1 },
{ "id_isar3_el1", MISCREG_ID_ISAR3_EL1 },
{ "id_isar4_el1", MISCREG_ID_ISAR4_EL1 },
{ "id_isar5_el1", MISCREG_ID_ISAR5_EL1 },
{ "mvfr0_el1", MISCREG_MVFR0_EL1 },
{ "mvfr1_el1", MISCREG_MVFR1_EL1 },
{ "mvfr2_el1", MISCREG_MVFR2_EL1 },
{ "id_aa64pfr0_el1", MISCREG_ID_AA64PFR0_EL1 },
{ "id_aa64pfr1_el1", MISCREG_ID_AA64PFR1_EL1 },
{ "id_aa64dfr0_el1", MISCREG_ID_AA64DFR0_EL1 },
{ "id_aa64dfr1_el1", MISCREG_ID_AA64DFR1_EL1 },
{ "id_aa64afr0_el1", MISCREG_ID_AA64AFR0_EL1 },
{ "id_aa64afr1_el1", MISCREG_ID_AA64AFR1_EL1 },
{ "id_aa64isar0_el1", MISCREG_ID_AA64ISAR0_EL1 },
{ "id_aa64isar1_el1", MISCREG_ID_AA64ISAR1_EL1 },
{ "id_aa64mmfr0_el1", MISCREG_ID_AA64MMFR0_EL1 },
{ "id_aa64mmfr1_el1", MISCREG_ID_AA64MMFR1_EL1 },
{ "id_aa64mmfr2_el1", MISCREG_ID_AA64MMFR2_EL1 },
{ "ccsidr_el1", MISCREG_CCSIDR_EL1 },
{ "clidr_el1", MISCREG_CLIDR_EL1 },
{ "aidr_el1", MISCREG_AIDR_EL1 },
{ "csselr_el1", MISCREG_CSSELR_EL1 },
{ "ctr_el0", MISCREG_CTR_EL0 },
{ "dczid_el0", MISCREG_DCZID_EL0 },
{ "vpidr_el2", MISCREG_VPIDR_EL2 },
{ "vmpidr_el2", MISCREG_VMPIDR_EL2 },
{ "sctlr_el1", MISCREG_SCTLR_EL1 },
{ "actlr_el1", MISCREG_ACTLR_EL1 },
{ "cpacr_el1", MISCREG_CPACR_EL1 },
{ "sctlr_el2", MISCREG_SCTLR_EL2 },
{ "actlr_el2", MISCREG_ACTLR_EL2 },
{ "hcr_el2", MISCREG_HCR_EL2 },
{ "mdcr_el2", MISCREG_MDCR_EL2 },
{ "cptr_el2", MISCREG_CPTR_EL2 },
{ "hstr_el2", MISCREG_HSTR_EL2 },
{ "hacr_el2", MISCREG_HACR_EL2 },
{ "sctlr_el3", MISCREG_SCTLR_EL3 },
{ "actlr_el3", MISCREG_ACTLR_EL3 },
{ "scr_el3", MISCREG_SCR_EL3 },
{ "sder32_el3", MISCREG_SDER32_EL3 },
{ "cptr_el3", MISCREG_CPTR_EL3 },
{ "mdcr_el3", MISCREG_MDCR_EL3 },
{ "ttbr0_el1", MISCREG_TTBR0_EL1 },
{ "ttbr1_el1", MISCREG_TTBR1_EL1 },
{ "tcr_el1", MISCREG_TCR_EL1 },
{ "ttbr0_el2", MISCREG_TTBR0_EL2 },
{ "tcr_el2", MISCREG_TCR_EL2 },
{ "vttbr_el2", MISCREG_VTTBR_EL2 },
{ "vtcr_el2", MISCREG_VTCR_EL2 },
{ "ttbr0_el3", MISCREG_TTBR0_EL3 },
{ "tcr_el3", MISCREG_TCR_EL3 },
{ "dacr32_el2", MISCREG_DACR32_EL2 },
{ "spsr_el1", MISCREG_SPSR_EL1 },
{ "elr_el1", MISCREG_ELR_EL1 },
{ "sp_el0", MISCREG_SP_EL0 },
{ "spsel", MISCREG_SPSEL },
{ "currentel", MISCREG_CURRENTEL },
{ "nzcv", MISCREG_NZCV },
{ "daif", MISCREG_DAIF },
{ "fpcr", MISCREG_FPCR },
{ "fpsr", MISCREG_FPSR },
{ "dspsr_el0", MISCREG_DSPSR_EL0 },
{ "dlr_el0", MISCREG_DLR_EL0 },
{ "spsr_el2", MISCREG_SPSR_EL2 },
{ "elr_el2", MISCREG_ELR_EL2 },
{ "sp_el1", MISCREG_SP_EL1 },
{ "spsr_irq", MISCREG_SPSR_IRQ_AA64 },
{ "spsr_abt", MISCREG_SPSR_ABT_AA64 },
{ "spsr_und", MISCREG_SPSR_UND_AA64 },
{ "spsr_fiq", MISCREG_SPSR_FIQ_AA64 },
{ "spsr_el3", MISCREG_SPSR_EL3 },
{ "elr_el3", MISCREG_ELR_EL3 },
{ "sp_el2", MISCREG_SP_EL2 },
{ "afsr0_el1", MISCREG_AFSR0_EL1 },
{ "afsr1_el1", MISCREG_AFSR1_EL1 },
{ "esr_el1", MISCREG_ESR_EL1 },
{ "ifsr32_el2", MISCREG_IFSR32_EL2 },
{ "afsr0_el2", MISCREG_AFSR0_EL2 },
{ "afsr1_el2", MISCREG_AFSR1_EL2 },
{ "esr_el2", MISCREG_ESR_EL2 },
{ "fpexc32_el2", MISCREG_FPEXC32_EL2 },
{ "afsr0_el3", MISCREG_AFSR0_EL3 },
{ "afsr1_el3", MISCREG_AFSR1_EL3 },
{ "esr_el3", MISCREG_ESR_EL3 },
{ "far_el1", MISCREG_FAR_EL1 },
{ "far_el2", MISCREG_FAR_EL2 },
{ "hpfar_el2", MISCREG_HPFAR_EL2 },
{ "far_el3", MISCREG_FAR_EL3 },
{ "ic_ialluis", MISCREG_IC_IALLUIS },
{ "par_el1", MISCREG_PAR_EL1 },
{ "ic_iallu", MISCREG_IC_IALLU },
{ "dc_ivac_xt", MISCREG_DC_IVAC_Xt },
{ "dc_isw_xt", MISCREG_DC_ISW_Xt },
{ "at_s1e1r_xt", MISCREG_AT_S1E1R_Xt },
{ "at_s1e1w_xt", MISCREG_AT_S1E1W_Xt },
{ "at_s1e0r_xt", MISCREG_AT_S1E0R_Xt },
{ "at_s1e0w_xt", MISCREG_AT_S1E0W_Xt },
{ "dc_csw_xt", MISCREG_DC_CSW_Xt },
{ "dc_cisw_xt", MISCREG_DC_CISW_Xt },
{ "dc_zva_xt", MISCREG_DC_ZVA_Xt },
{ "ic_ivau_xt", MISCREG_IC_IVAU_Xt },
{ "dc_cvac_xt", MISCREG_DC_CVAC_Xt },
{ "dc_cvau_xt", MISCREG_DC_CVAU_Xt },
{ "dc_civac_xt", MISCREG_DC_CIVAC_Xt },
{ "at_s1e2r_xt", MISCREG_AT_S1E2R_Xt },
{ "at_s1e2w_xt", MISCREG_AT_S1E2W_Xt },
{ "at_s12e1r_xt", MISCREG_AT_S12E1R_Xt },
{ "at_s12e1w_xt", MISCREG_AT_S12E1W_Xt },
{ "at_s12e0r_xt", MISCREG_AT_S12E0R_Xt },
{ "at_s12e0w_xt", MISCREG_AT_S12E0W_Xt },
{ "at_s1e3r_xt", MISCREG_AT_S1E3R_Xt },
{ "at_s1e3w_xt", MISCREG_AT_S1E3W_Xt },
{ "tlbi_vmalle1is", MISCREG_TLBI_VMALLE1IS },
{ "tlbi_vae1is_xt", MISCREG_TLBI_VAE1IS_Xt },
{ "tlbi_aside1is_xt", MISCREG_TLBI_ASIDE1IS_Xt },
{ "tlbi_vaae1is_xt", MISCREG_TLBI_VAAE1IS_Xt },
{ "tlbi_vale1is_xt", MISCREG_TLBI_VALE1IS_Xt },
{ "tlbi_vaale1is_xt", MISCREG_TLBI_VAALE1IS_Xt },
{ "tlbi_vmalle1", MISCREG_TLBI_VMALLE1 },
{ "tlbi_vae1_xt", MISCREG_TLBI_VAE1_Xt },
{ "tlbi_aside1_xt", MISCREG_TLBI_ASIDE1_Xt },
{ "tlbi_vaae1_xt", MISCREG_TLBI_VAAE1_Xt },
{ "tlbi_vale1_xt", MISCREG_TLBI_VALE1_Xt },
{ "tlbi_vaale1_xt", MISCREG_TLBI_VAALE1_Xt },
{ "tlbi_ipas2e1is_xt", MISCREG_TLBI_IPAS2E1IS_Xt },
{ "tlbi_ipas2le1is_xt", MISCREG_TLBI_IPAS2LE1IS_Xt },
{ "tlbi_alle2is", MISCREG_TLBI_ALLE2IS },
{ "tlbi_vae2is_xt", MISCREG_TLBI_VAE2IS_Xt },
{ "tlbi_alle1is", MISCREG_TLBI_ALLE1IS },
{ "tlbi_vale2is_xt", MISCREG_TLBI_VALE2IS_Xt },
{ "tlbi_vmalls12e1is", MISCREG_TLBI_VMALLS12E1IS },
{ "tlbi_ipas2e1_xt", MISCREG_TLBI_IPAS2E1_Xt },
{ "tlbi_ipas2le1_xt", MISCREG_TLBI_IPAS2LE1_Xt },
{ "tlbi_alle2", MISCREG_TLBI_ALLE2 },
{ "tlbi_vae2_xt", MISCREG_TLBI_VAE2_Xt },
{ "tlbi_alle1", MISCREG_TLBI_ALLE1 },
{ "tlbi_vale2_xt", MISCREG_TLBI_VALE2_Xt },
{ "tlbi_vmalls12e1", MISCREG_TLBI_VMALLS12E1 },
{ "tlbi_alle3is", MISCREG_TLBI_ALLE3IS },
{ "tlbi_vae3is_xt", MISCREG_TLBI_VAE3IS_Xt },
{ "tlbi_vale3is_xt", MISCREG_TLBI_VALE3IS_Xt },
{ "tlbi_alle3", MISCREG_TLBI_ALLE3 },
{ "tlbi_vae3_xt", MISCREG_TLBI_VAE3_Xt },
{ "tlbi_vale3_xt", MISCREG_TLBI_VALE3_Xt },
{ "pmintenset_el1", MISCREG_PMINTENSET_EL1 },
{ "pmintenclr_el1", MISCREG_PMINTENCLR_EL1 },
{ "pmcr_el0", MISCREG_PMCR_EL0 },
{ "pmcntenset_el0", MISCREG_PMCNTENSET_EL0 },
{ "pmcntenclr_el0", MISCREG_PMCNTENCLR_EL0 },
{ "pmovsclr_el0", MISCREG_PMOVSCLR_EL0 },
{ "pmswinc_el0", MISCREG_PMSWINC_EL0 },
{ "pmselr_el0", MISCREG_PMSELR_EL0 },
{ "pmceid0_el0", MISCREG_PMCEID0_EL0 },
{ "pmceid1_el0", MISCREG_PMCEID1_EL0 },
{ "pmccntr_el0", MISCREG_PMCCNTR_EL0 },
{ "pmxevtyper_el0", MISCREG_PMXEVTYPER_EL0 },
{ "pmccfiltr_el0", MISCREG_PMCCFILTR_EL0 },
{ "pmxevcntr_el0", MISCREG_PMXEVCNTR_EL0 },
{ "pmuserenr_el0", MISCREG_PMUSERENR_EL0 },
{ "pmovsset_el0", MISCREG_PMOVSSET_EL0 },
{ "mair_el1", MISCREG_MAIR_EL1 },
{ "amair_el1", MISCREG_AMAIR_EL1 },
{ "mair_el2", MISCREG_MAIR_EL2 },
{ "amair_el2", MISCREG_AMAIR_EL2 },
{ "mair_el3", MISCREG_MAIR_EL3 },
{ "amair_el3", MISCREG_AMAIR_EL3 },
{ "l2ctlr_el1", MISCREG_L2CTLR_EL1 },
{ "l2ectlr_el1", MISCREG_L2ECTLR_EL1 },
{ "vbar_el1", MISCREG_VBAR_EL1 },
{ "rvbar_el1", MISCREG_RVBAR_EL1 },
{ "isr_el1", MISCREG_ISR_EL1 },
{ "vbar_el2", MISCREG_VBAR_EL2 },
{ "rvbar_el2", MISCREG_RVBAR_EL2 },
{ "vbar_el3", MISCREG_VBAR_EL3 },
{ "rvbar_el3", MISCREG_RVBAR_EL3 },
{ "rmr_el3", MISCREG_RMR_EL3 },
{ "contextidr_el1", MISCREG_CONTEXTIDR_EL1 },
{ "contextidr_el2", MISCREG_CONTEXTIDR_EL2 },
{ "tpidr_el1", MISCREG_TPIDR_EL1 },
{ "tpidr_el0", MISCREG_TPIDR_EL0 },
{ "tpidrro_el0", MISCREG_TPIDRRO_EL0 },
{ "tpidr_el2", MISCREG_TPIDR_EL2 },
{ "tpidr_el3", MISCREG_TPIDR_EL3 },
{ "cntkctl_el1", MISCREG_CNTKCTL_EL1 },
{ "cntfrq_el0", MISCREG_CNTFRQ_EL0 },
{ "cntpct_el0", MISCREG_CNTPCT_EL0 },
{ "cntvct_el0", MISCREG_CNTVCT_EL0 },
{ "cntp_tval_el0", MISCREG_CNTP_TVAL_EL0 },
{ "cntp_ctl_el0", MISCREG_CNTP_CTL_EL0 },
{ "cntp_cval_el0", MISCREG_CNTP_CVAL_EL0 },
{ "cntv_tval_el0", MISCREG_CNTV_TVAL_EL0 },
{ "cntv_ctl_el0", MISCREG_CNTV_CTL_EL0 },
{ "cntv_cval_el0", MISCREG_CNTV_CVAL_EL0 },
{ "pmevcntr0_el0", MISCREG_PMEVCNTR0_EL0 },
{ "pmevcntr1_el0", MISCREG_PMEVCNTR1_EL0 },
{ "pmevcntr2_el0", MISCREG_PMEVCNTR2_EL0 },
{ "pmevcntr3_el0", MISCREG_PMEVCNTR3_EL0 },
{ "pmevcntr4_el0", MISCREG_PMEVCNTR4_EL0 },
{ "pmevcntr5_el0", MISCREG_PMEVCNTR5_EL0 },
{ "pmevtyper0_el0", MISCREG_PMEVTYPER0_EL0 },
{ "pmevtyper1_el0", MISCREG_PMEVTYPER1_EL0 },
{ "pmevtyper2_el0", MISCREG_PMEVTYPER2_EL0 },
{ "pmevtyper3_el0", MISCREG_PMEVTYPER3_EL0 },
{ "pmevtyper4_el0", MISCREG_PMEVTYPER4_EL0 },
{ "pmevtyper5_el0", MISCREG_PMEVTYPER5_EL0 },
{ "cntvoff_el2", MISCREG_CNTVOFF_EL2 },
{ "cnthctl_el2", MISCREG_CNTHCTL_EL2 },
{ "cnthp_tval_el2", MISCREG_CNTHP_TVAL_EL2 },
{ "cnthp_ctl_el2", MISCREG_CNTHP_CTL_EL2 },
{ "cnthp_cval_el2", MISCREG_CNTHP_CVAL_EL2 },
{ "cntps_tval_el1", MISCREG_CNTPS_TVAL_EL1 },
{ "cntps_ctl_el1", MISCREG_CNTPS_CTL_EL1 },
{ "cntps_cval_el1", MISCREG_CNTPS_CVAL_EL1 },
{ "il1data0_el1", MISCREG_IL1DATA0_EL1 },
{ "il1data1_el1", MISCREG_IL1DATA1_EL1 },
{ "il1data2_el1", MISCREG_IL1DATA2_EL1 },
{ "il1data3_el1", MISCREG_IL1DATA3_EL1 },
{ "dl1data0_el1", MISCREG_DL1DATA0_EL1 },
{ "dl1data1_el1", MISCREG_DL1DATA1_EL1 },
{ "dl1data2_el1", MISCREG_DL1DATA2_EL1 },
{ "dl1data3_el1", MISCREG_DL1DATA3_EL1 },
{ "dl1data4_el1", MISCREG_DL1DATA4_EL1 },
{ "l2actlr_el1", MISCREG_L2ACTLR_EL1 },
{ "cpuactlr_el1", MISCREG_CPUACTLR_EL1 },
{ "cpuectlr_el1", MISCREG_CPUECTLR_EL1 },
{ "cpumerrsr_el1", MISCREG_CPUMERRSR_EL1 },
{ "l2merrsr_el1", MISCREG_L2MERRSR_EL1 },
{ "cbar_el1", MISCREG_CBAR_EL1 },
};
void
TarmacParserRecord::TarmacParserRecordEvent::process()
{
ostream &outs = Trace::output();
list<ParserRegEntry>::iterator it = destRegRecords.begin(),
end = destRegRecords.end();
std::vector<uint64_t> values;
for (; it != end; ++it) {
values.clear();
switch (it->type) {
case REG_R:
case REG_X:
values.push_back(thread->readIntReg(it->index));
break;
case REG_S:
if (instRecord.isetstate == ISET_A64) {
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint32_t>();
values.push_back(vv[0]);
} else {
const VecElem elem = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
values.push_back(elem);
}
break;
case REG_D:
if (instRecord.isetstate == ISET_A64) {
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
values.push_back(vv[0]);
} else {
const VecElem w0 = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
const VecElem w1 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 1) / NumVecElemPerNeonVecReg,
(it->index + 1) % NumVecElemPerNeonVecReg));
values.push_back((uint64_t)(w1) << 32 | w0);
}
break;
case REG_P:
{
const ArmISA::VecPredRegContainer& pc =
thread->readVecPredReg(RegId(VecPredRegClass, it->index));
auto pv = pc.as<uint8_t>();
uint64_t p = 0;
for (int i = maxVectorLength * 8; i > 0; ) {
p = (p << 1) | pv[--i];
}
values.push_back(p);
}
break;
case REG_Q:
if (instRecord.isetstate == ISET_A64) {
const ArmISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
values.push_back(vv[0]);
values.push_back(vv[1]);
} else {
const VecElem w0 = thread->readVecElem(
RegId(VecElemClass,
it->index / NumVecElemPerNeonVecReg,
it->index % NumVecElemPerNeonVecReg));
const VecElem w1 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 1) / NumVecElemPerNeonVecReg,
(it->index + 1) % NumVecElemPerNeonVecReg));
const VecElem w2 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 2) / NumVecElemPerNeonVecReg,
(it->index + 2) % NumVecElemPerNeonVecReg));
const VecElem w3 = thread->readVecElem(
RegId(VecElemClass,
(it->index + 3) / NumVecElemPerNeonVecReg,
(it->index + 3) % NumVecElemPerNeonVecReg));
values.push_back((uint64_t)(w1) << 32 | w0);
values.push_back((uint64_t)(w3) << 32 | w2);
}
break;
case REG_Z:
{
int8_t i = maxVectorLength;
const TheISA::VecRegContainer& vc = thread->readVecReg(
RegId(VecRegClass, it->index));
auto vv = vc.as<uint64_t>();
while (i > 0) {
values.push_back(vv[--i]);
}
}
break;
case REG_MISC:
if (it->index == MISCREG_CPSR) {
// Read condition codes from aliased integer regs
CPSR cpsr = thread->readMiscRegNoEffect(it->index);
cpsr.nz = thread->readCCReg(CCREG_NZ);
cpsr.c = thread->readCCReg(CCREG_C);
cpsr.v = thread->readCCReg(CCREG_V);
cpsr.ge = thread->readCCReg(CCREG_GE);
values.push_back(cpsr);
} else if (it->index == MISCREG_NZCV) {
CPSR cpsr = 0;
cpsr.nz = thread->readCCReg(CCREG_NZ);
cpsr.c = thread->readCCReg(CCREG_C);
cpsr.v = thread->readCCReg(CCREG_V);
values.push_back(cpsr);
} else if (it->index == MISCREG_FPCR) {
// Read FPSCR and extract FPCR value
FPSCR fpscr = thread->readMiscRegNoEffect(MISCREG_FPSCR);
const uint32_t ones = (uint32_t)(-1);
FPSCR fpcrMask = 0;
fpcrMask.ioe = ones;
fpcrMask.dze = ones;
fpcrMask.ofe = ones;
fpcrMask.ufe = ones;
fpcrMask.ixe = ones;
fpcrMask.ide = ones;
fpcrMask.len = ones;
fpcrMask.stride = ones;
fpcrMask.rMode = ones;
fpcrMask.fz = ones;
fpcrMask.dn = ones;
fpcrMask.ahp = ones;
values.push_back(fpscr & fpcrMask);
} else if (it->index == MISCREG_FPSR) {
// Read FPSCR and extract FPSR value
FPSCR fpscr = thread->readMiscRegNoEffect(MISCREG_FPSCR);
const uint32_t ones = (uint32_t)(-1);
FPSCR fpsrMask = 0;
fpsrMask.ioc = ones;
fpsrMask.dzc = ones;
fpsrMask.ofc = ones;
fpsrMask.ufc = ones;
fpsrMask.ixc = ones;
fpsrMask.idc = ones;
fpsrMask.qc = ones;
fpsrMask.v = ones;
fpsrMask.c = ones;
fpsrMask.z = ones;
fpsrMask.n = ones;
values.push_back(fpscr & fpsrMask);
} else {
values.push_back(thread->readMiscRegNoEffect(it->index));
}
break;
default:
panic("Unknown TARMAC trace record type!");
}
bool same = true;
if (values.size() != it->values.size()) same = false;
uint32_t size = values.size();
if (size > it->values.size())
size = it->values.size();
if (same) {
for (int i = 0; i < size; ++i) {
if (values[i] != it->values[i]) {
same = false;
break;
}
}
}
if (!same) {
if (!mismatch) {
TarmacParserRecord::printMismatchHeader(inst, pc);
mismatch = true;
}
outs << "diff> [" << it->repr << "] gem5: 0x" << hex;
for (auto v : values)
outs << setw(16) << setfill('0') << v;
outs << ", TARMAC: 0x" << hex;
for (auto v : it->values)
outs << setw(16) << setfill('0') << v;
outs << endl;
}
}
destRegRecords.clear();
if (mismatchOnPcOrOpcode && (parent.exitOnDiff ||
parent.exitOnInsnDiff))
exitSimLoop("a mismatch with the TARMAC trace has been detected "
"on PC or opcode", 1);
if (mismatch && parent.exitOnDiff)
exitSimLoop("a mismatch with the TARMAC trace has been detected "
"on data value", 1);
}
const char *
TarmacParserRecord::TarmacParserRecordEvent::description() const
{
return "TARMAC parser record event";
}
void
TarmacParserRecord::printMismatchHeader(const StaticInstPtr staticInst,
ArmISA::PCState pc)
{
ostream &outs = Trace::output();
outs << "\nMismatch between gem5 and TARMAC trace @ " << dec << curTick()
<< " ticks\n"
<< "[seq_num: " << dec << instRecord.seq_num
<< ", opcode: 0x" << hex << (staticInst->machInst & 0xffffffff)
<< ", PC: 0x" << pc.pc()
<< ", disasm: " << staticInst->disassemble(pc.pc()) << "]"
<< endl;
}
TarmacParserRecord::TarmacParserRecord(Tick _when, ThreadContext *_thread,
const StaticInstPtr _staticInst,
PCState _pc,
TarmacParser& _parent,
const StaticInstPtr _macroStaticInst)
: TarmacBaseRecord(_when, _thread, _staticInst,
_pc, _macroStaticInst),
parsingStarted(false), mismatch(false),
mismatchOnPcOrOpcode(false), parent(_parent)
{
memReq = std::make_shared<Request>();
if (maxVectorLength == 0) {
maxVectorLength = ArmStaticInst::getCurSveVecLen<uint64_t>(_thread);
}
}
void
TarmacParserRecord::dump()
{
ostream &outs = Trace::output();
uint64_t written_data = 0;
unsigned mem_flags = 3 | ArmISA::TLB::AllowUnaligned;
ISetState isetstate;
if (!staticInst->isMicroop() || staticInst->isLastMicroop()) {
if (parent.macroopInProgress && !staticInst->isLastMicroop()) {
// A microop faulted and it was not the last microop -> advance
// TARMAC trace to next instruction
advanceTrace();
}
parent.macroopInProgress = false;
auto arm_inst = static_cast<const ArmStaticInst*>(
staticInst.get()
);
while (advanceTrace()) {
switch (currRecordType) {
case TARMAC_INST:
parsingStarted = true;
if (pc.instAddr() != instRecord.addr) {
if (!mismatch)
printMismatchHeader(staticInst, pc);
outs << "diff> [PC] gem5: 0x" << hex << pc.instAddr()
<< ", TARMAC: 0x" << instRecord.addr << endl;
mismatch = true;
mismatchOnPcOrOpcode = true;
}
if (arm_inst->encoding() != instRecord.opcode) {
if (!mismatch)
printMismatchHeader(staticInst, pc);
outs << "diff> [opcode] gem5: 0x" << hex
<< arm_inst->encoding()
<< ", TARMAC: 0x" << instRecord.opcode << endl;
mismatch = true;
mismatchOnPcOrOpcode = true;
}
// Set the Instruction set state.
isetstate = pcToISetState(pc);
if (instRecord.isetstate != isetstate &&
isetstate != ISET_UNSUPPORTED) {
if (!mismatch)
printMismatchHeader(staticInst, pc);
outs << "diff> [iset_state] gem5: "
<< iSetStateToStr(isetstate)
<< ", TARMAC: "
<< iSetStateToStr(instRecord.isetstate);
mismatch = true;
}
// TODO(Giacomo): add support for predicate and mode checking
break;
case TARMAC_REG:
destRegRecords.push_back(regRecord);
break;
case TARMAC_MEM:
if (!readMemNoEffect(memRecord.addr, (uint8_t*) &written_data,
memRecord.size, mem_flags))
break;
if (written_data != memRecord.data) {
if (!mismatch)
printMismatchHeader(staticInst, pc);
outs << "diff> [mem(0x" << hex << memRecord.addr
<< ")] gem5: 0x" << written_data
<< ", TARMAC: 0x" << memRecord.data
<< endl;
}
break;
case TARMAC_UNSUPPORTED:
break;
default:
panic("Unknown TARMAC trace record type!");
}
}
// We are done with the current instruction, i.e. all the corresponding
// entries in the TARMAC trace have been parsed
if (destRegRecords.size()) {
TarmacParserRecordEvent *event = new TarmacParserRecordEvent(
parent, thread, staticInst, pc, mismatch,
mismatchOnPcOrOpcode);
mainEventQueue[0]->schedule(event, curTick());
} else if (mismatchOnPcOrOpcode && (parent.exitOnDiff ||
parent.exitOnInsnDiff)) {
exitSimLoop("a mismatch with the TARMAC trace has been detected "
"on PC or opcode", 1);
}
} else {
parent.macroopInProgress = true;
}
}
bool
TarmacParserRecord::advanceTrace()
{
ifstream& trace = parent.trace;
trace >> hex; // All integer values are in hex base
if (buf[0] != 'I') {
trace >> buf;
if (trace.eof())
return false;
trace >> buf >> buf;
if (parent.cpuId) {
assert((buf[0] == 'c') && (buf[1] == 'p') && (buf[2] == 'u'));
trace >> buf;
}
}
if (trace.eof())
return false;
if (buf[0] == 'I') {
// Instruction trace record
if (parsingStarted)
return false;
currRecordType = TARMAC_INST;
instRecord.taken = (buf[1] == 'T');
trace >> buf;
instRecord.seq_num = atoi(&buf[1]);
trace >> instRecord.addr;
char c = trace.peek();
if (c == ':') {
// Skip phys. address and _S/_NS suffix
trace >> c >> buf;
}
trace >> instRecord.opcode;
trace >> buf;
switch (buf[0]) {
case 'A':
instRecord.isetstate = ISET_ARM;
break;
case 'T':
instRecord.isetstate = ISET_THUMB;
break;
case 'O':
instRecord.isetstate = ISET_A64;
break;
default:
warn("Invalid TARMAC trace record (seq_num: %lld)",
instRecord.seq_num);
instRecord.isetstate = ISET_UNSUPPORTED;
currRecordType = TARMAC_UNSUPPORTED;
break;
}
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;
} else if (buf[0] == 'R') {
// Register trace record
currRecordType = TARMAC_REG;
regRecord.values.clear();
trace >> buf;
strcpy(regRecord.repr, buf);
if (std::tolower(buf[0]) == 'r' && isdigit(buf[1])) {
// R register
regRecord.type = REG_R;
int base_index = atoi(&buf[1]);
char* pch = strchr(buf, '_');
if (pch == NULL) {
regRecord.index = INTREG_USR(base_index);
} else {
++pch;
if (strncmp(pch, "usr", 3) == 0)
regRecord.index = INTREG_USR(base_index);
else if (strncmp(pch, "fiq", 3) == 0)
regRecord.index = INTREG_FIQ(base_index);
else if (strncmp(pch, "irq", 3) == 0)
regRecord.index = INTREG_IRQ(base_index);
else if (strncmp(pch, "svc", 3) == 0)
regRecord.index = INTREG_SVC(base_index);
else if (strncmp(pch, "mon", 3) == 0)
regRecord.index = INTREG_MON(base_index);
else if (strncmp(pch, "abt", 3) == 0)
regRecord.index = INTREG_ABT(base_index);
else if (strncmp(pch, "und", 3) == 0)
regRecord.index = INTREG_UND(base_index);
else if (strncmp(pch, "hyp", 3) == 0)
regRecord.index = INTREG_HYP(base_index);
}
} else if (std::tolower(buf[0]) == 'x' && isdigit(buf[1])) {
// X register (A64)
regRecord.type = REG_X;
regRecord.index = atoi(&buf[1]);
} else if (std::tolower(buf[0]) == 's' && isdigit(buf[1])) {
// S register
regRecord.type = REG_S;
regRecord.index = atoi(&buf[1]);
} else if (std::tolower(buf[0]) == 'd' && isdigit(buf[1])) {
// D register
regRecord.type = REG_D;
regRecord.index = atoi(&buf[1]);
} else if (std::tolower(buf[0]) == 'q' && isdigit(buf[1])) {
// Q register
regRecord.type = REG_Q;
regRecord.index = atoi(&buf[1]);
} else if (std::tolower(buf[0]) == 'z' && isdigit(buf[1])) {
// Z (SVE vector) register
regRecord.type = REG_Z;
regRecord.index = atoi(&buf[1]);
} else if (std::tolower(buf[0]) == 'p' && isdigit(buf[1])) {
// P (SVE predicate) register
regRecord.type = REG_P;
regRecord.index = atoi(&buf[1]);
} else if (strncmp(buf, "SP_EL", 5) == 0) {
// A64 stack pointer
regRecord.type = REG_X;
regRecord.index = INTREG_SP0 + atoi(&buf[5]);
} else if (miscRegMap.count(buf)) {
// Misc. register
regRecord.type = REG_MISC;
regRecord.index = miscRegMap[buf];
} else {
// Try match with upper case name (misc. register)
string reg_name = buf;
transform(reg_name.begin(), reg_name.end(), reg_name.begin(),
::tolower);
if (miscRegMap.count(reg_name.c_str())) {
regRecord.type = REG_MISC;
regRecord.index = miscRegMap[reg_name.c_str()];
} else {
warn("Unknown register in TARMAC trace (%s).\n", buf);
currRecordType = TARMAC_UNSUPPORTED;
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;
return true;
}
}
if (regRecord.type == REG_Q) {
trace.ignore();
trace.get(buf, 17);
uint64_t hi = strtoull(buf, NULL, 16);
trace.get(buf, 17);
uint64_t lo = strtoull(buf, NULL, 16);
regRecord.values.push_back(lo);
regRecord.values.push_back(hi);
} else if (regRecord.type == REG_Z) {
regRecord.values.resize(maxVectorLength);
for (uint8_t i = 0; i < maxVectorLength; ++i) {
uint64_t v;
trace >> v;
char c;
trace >> c;
assert(c == '_');
uint64_t lsw = 0;
trace >> lsw;
v = (v << 32) | lsw;
if (i < maxVectorLength - 1) trace >> c;
regRecord.values[i] = v;
}
} else {
// REG_P values are also parsed here
uint64_t v;
trace >> v;
char c = trace.peek();
if ((c == ':') || (c == '_')) {
// 64-bit value with : or _ in the middle
uint64_t lsw = 0;
trace >> c >> lsw;
v = (v << 32) | lsw;
}
regRecord.values.push_back(v);
}
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;
} else if (buf[0] == 'M' && (parent.memWrCheck && buf[1] == 'W')) {
currRecordType = TARMAC_MEM;
memRecord.size = atoi(&buf[2]);
trace >> memRecord.addr;
char c = trace.peek();
if (c == ':') {
// Skip phys. address and _S/_NS suffix
trace >> c >> buf;
}
uint64_t data = 0;
trace >> data;
c = trace.peek();
if (c == '_') {
// 64-bit value with _ in the middle
uint64_t lsw = 0;
trace >> c >> lsw;
data = (data << 32) | lsw;
}
memRecord.data = data;
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;
} else {
currRecordType = TARMAC_UNSUPPORTED;
trace.ignore(MaxLineLength, '\n');
buf[0] = 0;
}
return true;
}
bool
TarmacParserRecord::readMemNoEffect(Addr addr, uint8_t *data, unsigned size,
unsigned flags)
{
const RequestPtr &req = memReq;
ArmISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
req->setVirt(addr, size, flags, thread->pcState().instAddr(),
Request::funcMasterId);
// Translate to physical address
Fault fault = dtb->translateAtomic(req, thread, BaseTLB::Read);
// Ignore read if the address falls into the ignored range
if (parent.ignoredAddrRange.contains(addr))
return false;
// Now do the access
if (fault == NoFault &&
!req->getFlags().isSet(Request::NO_ACCESS)) {
if (req->isLLSC() || req->isLocalAccess())
// LLSCs and local accesses are ignored
return false;
// the translating proxy will perform the virtual to physical
// translation again
thread->getVirtProxy().readBlob(addr, data, size);
} else {
return false;
}
if (fault != NoFault) {
return false;
}
return true;
}
void
TarmacParser::advanceTraceToStartPc()
{
char buf[TarmacParserRecord::MaxLineLength];
Addr pc;
int saved_offset;
trace >> hex; // All integer values are in hex base
while (true) {
saved_offset = trace.tellg();
trace >> buf >> buf >> buf;
if (cpuId)
trace >> buf;
if (buf[0] == 'I') {
trace >> buf >> pc;
if (pc == startPc) {
// Set file pointer to the beginning of this line
trace.seekg(saved_offset, ios::beg);
return;
} else {
trace.ignore(TarmacParserRecord::MaxLineLength, '\n');
}
} else {
trace.ignore(TarmacParserRecord::MaxLineLength, '\n');
}
if (trace.eof())
panic("End of TARMAC trace reached before start PC\n");
}
}
const char*
TarmacParserRecord::iSetStateToStr(ISetState isetstate) const
{
switch (isetstate) {
case ISET_ARM:
return "ARM (A32)";
case ISET_THUMB:
return "Thumb (A32)";
case ISET_A64:
return "A64";
default:
return "UNSUPPORTED";
}
}
} // namespace Trace
Trace::TarmacParser *
TarmacParserParams::create()
{
return new Trace::TarmacParser(this);
}