1/* 2 * Copyright (c) 2011,2017-2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Giacomo Gabrielli 38 */ 39 40/** 41 * @file This module implements a bridge between TARMAC traces, as generated by 42 * other models, and gem5 (AtomicCPU model). Its goal is to detect possible 43 * inconsistencies between the two models as soon as they occur. The module 44 * takes a TARMAC trace as input, which is used to compare the architectural 45 * state of the two models after each simulated instruction. 46 */ 47 48#ifndef __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__ 49#define __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__ 50 51#include <fstream> 52#include <unordered_map> 53 54#include "arch/arm/registers.hh" 55#include "base/trace.hh" 56#include "base/types.hh" 57#include "cpu/static_inst.hh" 58#include "cpu/thread_context.hh" 59#include "mem/request.hh" 60#include "params/TarmacParser.hh" 61#include "sim/insttracer.hh" 62#include "tarmac_base.hh" 63 64namespace Trace { 65 66class TarmacParserRecord : public TarmacBaseRecord 67{ 68 public: 69 /** 70 * Event triggered to check the value of the destination registers. Needed 71 * to handle some cases where registers are modified after the trace record 72 * has been dumped. E.g., the SVC instruction updates the CPSR and SPSR as 73 * part of the fault handling routine. 74 */ 75 struct TarmacParserRecordEvent: public Event 76 { 77 /** 78 * Reference to the TARMAC trace object to which this record belongs. 79 */ 80 TarmacParser& parent; 81 /** Current thread context. */ 82 ThreadContext* thread; 83 /** Current instruction. */ 84 const StaticInstPtr inst; 85 /** PC of the current instruction. */ 86 ArmISA::PCState pc; 87 /** True if a mismatch has been detected for this instruction. */ 88 bool mismatch; 89 /** 90 * True if a mismatch has been detected for this instruction on PC or 91 * opcode. 92 */ 93 bool mismatchOnPcOrOpcode; 94 95 TarmacParserRecordEvent(TarmacParser& _parent, 96 ThreadContext *_thread, 97 const StaticInstPtr _inst, 98 ArmISA::PCState _pc, 99 bool _mismatch, 100 bool _mismatch_on_pc_or_opcode) : 101 parent(_parent), thread(_thread), inst(_inst), pc(_pc), 102 mismatch(_mismatch), 103 mismatchOnPcOrOpcode(_mismatch_on_pc_or_opcode) 104 { 105 } 106 107 void process(); 108 const char *description() const; 109 }; 110 111 struct ParserInstEntry : public InstEntry 112 { 113 public: 114 uint64_t seq_num; 115 }; 116 117 struct ParserRegEntry : public RegEntry 118 { 119 public: 120 char repr[16]; 121 }; 122 123 struct ParserMemEntry : public MemEntry 124 { }; 125 126 static const int MaxLineLength = 256; 127 128 /** 129 * Print a mismatch header containing the instruction fields as reported 130 * by gem5. 131 */ 132 static void printMismatchHeader(const StaticInstPtr inst, 133 ArmISA::PCState pc); 134 135 TarmacParserRecord(Tick _when, ThreadContext *_thread, 136 const StaticInstPtr _staticInst, ArmISA::PCState _pc, 137 TarmacParser& _parent, 138 const StaticInstPtr _macroStaticInst = NULL); 139 140 void dump() override; 141 142 /** 143 * Performs a memory access to read the value written by a previous write. 144 * @return False if the result of the memory access should be ignored 145 * (faulty memory access, etc.). 146 */ 147 bool readMemNoEffect(Addr addr, uint8_t *data, unsigned size, 148 unsigned flags); 149 150 private: 151 /** 152 * Advances the TARMAC trace up to the next instruction, 153 * register, or memory access record. The collected data is stored 154 * in one of {inst/reg/mem}_record. 155 * @return False if EOF is reached. 156 */ 157 bool advanceTrace(); 158 159 /** Returns the string representation of an instruction set state. */ 160 const char *iSetStateToStr(ISetState isetstate) const; 161 162 /** Buffer for instruction trace records. */ 163 static ParserInstEntry instRecord; 164 165 /** Buffer for register trace records. */ 166 static ParserRegEntry regRecord; 167 168 /** Buffer for memory access trace records (stores only). */ 169 static ParserMemEntry memRecord; 170 171 /** Type of last parsed record. */ 172 static TarmacRecordType currRecordType; 173 174 /** Buffer used for trace file parsing. */ 175 static char buf[MaxLineLength]; 176 177 /** List of records of destination registers. */ 178 static std::list<ParserRegEntry> destRegRecords; 179 180 /** Map from misc. register names to indexes. */ 181 using MiscRegMap = std::unordered_map<std::string, RegIndex>; 182 static MiscRegMap miscRegMap; 183 184 /** 185 * True if a TARMAC instruction record has already been parsed for this 186 * instruction. 187 */ 188 bool parsingStarted; 189 190 /** True if a mismatch has been detected for this instruction. */ 191 bool mismatch; 192 193 /** 194 * True if a mismatch has been detected for this instruction on PC or 195 * opcode. 196 */ 197 bool mismatchOnPcOrOpcode; 198 199 /** Request for memory write checks. */ 200 RequestPtr memReq; 201 202 protected: 203 TarmacParser& parent; 204}; 205 206/** 207 * Tarmac Parser: this tracer parses an existing Tarmac trace and it 208 * diffs it with gem5 simulation status, comparing results and 209 * reporting architectural mismatches if any. 210 */ 211class TarmacParser : public InstTracer 212{ 213 friend class TarmacParserRecord; 214 215 public: 216 typedef TarmacParserParams Params; 217 218 TarmacParser(const Params *p) : InstTracer(p), startPc(p->start_pc), 219 exitOnDiff(p->exit_on_diff), 220 exitOnInsnDiff(p->exit_on_insn_diff), 221 memWrCheck(p->mem_wr_check), 222 ignoredAddrRange(p->ignore_mem_addr), 223 cpuId(p->cpu_id), 224 macroopInProgress(false) 225 { 226 assert(!(exitOnDiff && exitOnInsnDiff)); 227 228 trace.open(p->path_to_trace.c_str()); 229 if (startPc == 0x0) { 230 started = true; 231 } else { 232 advanceTraceToStartPc(); 233 started = false; 234 } 235 } 236 237 virtual ~TarmacParser() 238 { 239 trace.close(); 240 } 241 242 InstRecord * 243 getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, 244 ArmISA::PCState pc, 245 const StaticInstPtr macroStaticInst = NULL) 246 { 247 if (!started && pc.pc() == startPc) 248 started = true; 249 250 if (started) 251 return new TarmacParserRecord(when, tc, staticInst, pc, *this, 252 macroStaticInst); 253 else 254 return NULL; 255 } 256 257 private: 258 /** Helper function to advance the trace up to startPc. */ 259 void advanceTraceToStartPc(); 260 261 /** TARMAC trace file. */ 262 std::ifstream trace; 263 264 /** 265 * Tracing starts when the PC gets this value for the first time (ignored 266 * if 0x0). 267 */ 268 Addr startPc; 269 270 /** 271 * If true, the simulation is stopped as the first mismatch is detected. 272 */ 273 bool exitOnDiff; 274 275 /** 276 * If true, the simulation is stopped as the first mismatch is detected on 277 * PC or opcode. 278 */ 279 bool exitOnInsnDiff; 280 281 /** If true, memory write accesses are checked. */ 282 bool memWrCheck; 283 284 /** Ignored addresses (ignored if empty). */ 285 AddrRange ignoredAddrRange; 286 287 /** If true, the trace format includes the CPU id. */ 288 bool cpuId; 289 290 /** True if tracing has started. */ 291 bool started; 292 293 /** True if a macroop is currently in progress. */ 294 bool macroopInProgress; 295}; 296 297} // namespace Trace 298 299#endif // __ARCH_ARM_TRACERS_TARMAC_PARSER_HH__ 300