gem5  v22.1.0.0
tarmac_record.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 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 
39 
40 #include <memory>
41 
43 #include "tarmac_tracer.hh"
44 
45 namespace gem5
46 {
47 
48 using namespace ArmISA;
49 
50 namespace trace {
51 
52 // TARMAC Instruction Record static variables
53 uint64_t TarmacTracerRecord::TraceInstEntry::instCount = 0;
54 
55 std::string
57 {
58  switch (isetstate) {
59  case TarmacBaseRecord::ISET_ARM:
60  return "A";
61  case TarmacBaseRecord::ISET_THUMB:
62  return "T";
63  case TarmacBaseRecord::ISET_A64:
64  return "O";
65  default:
66  return "Unsupported";
67  }
68 }
69 
70 std::string
72 {
73  switch (opMode) {
74  case MODE_EL0T:
75  return "EL0t";
76  case MODE_EL1T:
77  return "EL1t";
78  case MODE_EL1H:
79  return "EL1h";
80  case MODE_EL2T:
81  return "EL2t";
82  case MODE_EL2H:
83  return "EL2h";
84  case MODE_EL3T:
85  return "EL3t";
86  case MODE_EL3H:
87  return "EL3h";
88  case MODE_USER:
89  return "usr";
90  case MODE_FIQ:
91  return "fiq";
92  case MODE_IRQ:
93  return "irq";
94  case MODE_SVC:
95  return "svc";
96  case MODE_MON:
97  return "mon";
98  case MODE_ABORT:
99  return "abt";
100  case MODE_HYP:
101  return "hyp";
102  case MODE_UNDEFINED:
103  return "und";
104  case MODE_SYSTEM:
105  return "sys";
106  default:
107  return "Unsupported";
108  }
109 }
110 
111 // TarmacTracerRecord ctor
112 TarmacTracerRecord::TarmacTracerRecord(Tick _when, ThreadContext *_thread,
113  const StaticInstPtr _staticInst,
114  const PCStateBase &_pc,
115  TarmacTracer& _tracer,
116  const StaticInstPtr _macroStaticInst)
117  : TarmacBaseRecord(_when, _thread, _staticInst,
118  _pc, _macroStaticInst),
119  tracer(_tracer)
120 {
121 }
122 
124  const TarmacContext& tarmCtx,
125  bool predicate)
126  : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate)
127 {
128  secureMode = isSecure(tarmCtx.thread);
129 
130  auto arm_inst = static_cast<const ArmStaticInst*>(
131  tarmCtx.staticInst.get()
132  );
133 
134  // Get the instruction size as a number of bits:
135  // (multiply byte size by 8)
136  instSize = (arm_inst->instSize() << 3);
137 
138  // Mask the opcode using the instruction size: the
139  // opcode field will otherwise be 32 bit wide even
140  // for 16bit (Thumb) instruction.
141  opcode = arm_inst->encoding();
142 
143  // Update the instruction count: number of executed
144  // instructions.
145  instCount++;
146 }
147 
149  const TarmacContext& tarmCtx,
150  uint8_t _size, Addr _addr, uint64_t _data)
151  : MemEntry(_size, _addr, _data),
152  loadAccess(tarmCtx.staticInst->isLoad())
153 {
154 }
155 
157  const TarmacContext& tarmCtx,
158  const RegId& reg)
159  : RegEntry(*tarmCtx.pc),
160  regValid(false),
161  regId(reg)
162 {
163 }
164 
165 void
167 {
168  // Fill the register entry data, according to register
169  // class.
170  switch (regId.classValue()) {
171  case CCRegClass:
172  updateCC(tarmCtx);
173  break;
174  case FloatRegClass:
175  updateFloat(tarmCtx);
176  break;
177  case IntRegClass:
178  updateInt(tarmCtx);
179  break;
180  case MiscRegClass:
181  updateMisc(tarmCtx);
182  break;
183  case VecRegClass:
184  updateVec(tarmCtx);
185  break;
186  case VecPredRegClass:
187  updatePred(tarmCtx);
188  break;
189  default:
190  // If unsupported format, do nothing: non updating
191  // the register will prevent it to be printed.
192  break;
193  }
194 }
195 
196 void
198 {
199  auto thread = tarmCtx.thread;
200 
201  regValid = true;
202  regName = miscRegName[regId.index()];
203  values[Lo] = thread->readMiscRegNoEffect(regId.index());
204 
205  // If it is the CPSR:
206  // update the value of the CPSR register and add
207  // the CC flags on top of the value
208  if (regId.index() == MISCREG_CPSR) {
210  cpsr.nz = thread->getReg(cc_reg::Nz);
211  cpsr.c = thread->getReg(cc_reg::C);
212  cpsr.v = thread->getReg(cc_reg::V);
213  cpsr.ge = thread->getReg(cc_reg::Ge);
214 
215  // update the entry value
216  values[Lo] = cpsr;
217  }
218 }
219 
220 void
222 {
223  auto thread = tarmCtx.thread;
224 
225  regValid = true;
226  regName = cc_reg::RegName[regId.index()];
227  values[Lo] = thread->getReg(regId);
228 }
229 
230 void
232 {
233  regValid = true;
234  regName = "f" + std::to_string(regId.index());
235  panic("ARM doesn't support float registers.");
236 }
237 
238 void
240 {
241  auto thread = tarmCtx.thread;
242 
243  // Reading operating mode from CPSR.
244  // This is needed when printing the register name in case
245  // of banked register (e.g. lr_svc)
247  OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
248 
249  std::string reg_suffix;
250  if (mode != MODE_USER) {
251  reg_suffix = "_" + opModeToStr(mode);
252  }
253 
254  regValid = true;
255  switch (regId.index()) {
256  case int_reg::Pc:
257  regName = "pc";
258  break;
259  case StackPointerReg:
260  regName = "sp" + reg_suffix ;
261  break;
262  case FramePointerReg:
263  regName = "fp" + reg_suffix;
264  break;
265  case ReturnAddressReg:
266  regName = "lr" + reg_suffix;
267  break;
268  default:
269  regName = "r" + std::to_string(regId.index());
270  break;
271  }
272  values[Lo] = thread->getReg(regId);
273 }
274 
275 void
277  const TarmacContext& tarmCtx)
278 {
279  // Generate an instruction entry in the record and
280  // add it to the Instruction Queue
281  queue.push_back(
282  std::make_unique<TraceInstEntry>(tarmCtx, predicate)
283  );
284 }
285 
286 void
288  const TarmacContext& tarmCtx)
289 {
290  // Generate a memory entry in the record if the record
291  // implies a valid memory access, and add it to the
292  // Memory Queue
293  if (getMemValid()) {
294  queue.push_back(
295  std::make_unique<TraceMemEntry>(tarmCtx,
296  static_cast<uint8_t>(getSize()),
297  getAddr(), getIntData())
298  );
299  }
300 }
301 
302 void
304  const TarmacContext& tarmCtx)
305 {
306  // Generate an entry for every ARM register being
307  // written by the current instruction
308  for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) {
309 
310  RegId reg_id = staticInst->destRegIdx(reg);
311 
312  // Creating a single register change entry
313  auto single_reg = genRegister<TraceRegEntry>(tarmCtx, reg_id);
314 
315  // Copying the entry and adding it to the "list"
316  // of entries to be dumped to trace.
317  queue.push_back(std::make_unique<TraceRegEntry>(single_reg));
318  }
319 
320  // Gem5 is treating CPSR flags as separate registers (CC registers),
321  // in contrast with Tarmac specification: we need to merge the gem5 CC
322  // entries altogether with the CPSR register and produce a single entry.
323  mergeCCEntry<TraceRegEntry>(queue, tarmCtx);
324 }
325 
326 void
328 {
329  // Generate and print all the record's entries.
330  auto &instQueue = tracer.instQueue;
331  auto &memQueue = tracer.memQueue;
332  auto &regQueue = tracer.regQueue;
333 
334  const TarmacContext tarmCtx(
335  thread,
337  *pc
338  );
339 
340  if (!staticInst->isMicroop()) {
341  // Current instruction is NOT a micro-instruction:
342  // Generate Tarmac entries and dump them immediately
343 
344  // Generate Tarmac entries and add them to the respective
345  // queues.
346  addInstEntry(instQueue, tarmCtx);
347  addMemEntry(memQueue, tarmCtx);
348  addRegEntry(regQueue, tarmCtx);
349 
350  // Flush (print) any queued entry.
351  flushQueues(instQueue, memQueue, regQueue);
352 
353  } else {
354  // Current instruction is a micro-instruction:
355  // save micro entries into dedicated queues and flush them
356  // into the tracefile only when the MACRO-instruction
357  // has completed.
358 
359  if (staticInst->isFirstMicroop()) {
360  addInstEntry(instQueue, tarmCtx);
361  }
362 
363  addRegEntry(regQueue, tarmCtx);
364  addMemEntry(memQueue, tarmCtx);
365 
366  if (staticInst->isLastMicroop()) {
367  // Flush (print) any queued entry.
368  flushQueues(instQueue, memQueue, regQueue);
369  }
370  }
371 }
372 
373 template<typename Queue>
374 void
376 {
377  std::ostream &outs = tracer.output();
378 
379  for (const auto &single_entry : queue) {
380  single_entry->print(outs);
381  }
382 
383  queue.clear();
384 }
385 
386 template<typename Queue, typename... Args>
387 void
388 TarmacTracerRecord::flushQueues(Queue& queue, Args & ... args)
389 {
390  flushQueues(queue);
391  flushQueues(args...);
392 }
393 
394 void
396  std::ostream& outs,
397  int verbosity,
398  const std::string &prefix) const
399 {
400  // Pad the opcode
401  std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode);
402 
403  // Print the instruction record formatted according
404  // to the Tarmac specification
405  ccprintf(outs, "%s clk %s (%u) %08x %s %s %s_%s : %s\n",
406  curTick(), /* Tick time */
407  taken? "IT" : "IS", /* Instruction taken/skipped */
408  instCount, /* Instruction count */
409  addr, /* Instruction address */
410  opcode_str, /* Instruction opcode */
411  iSetStateToStr(isetstate), /* Instruction Set */
412  opModeToStr(mode), /* Exception level */
413  secureMode? "s" : "ns", /* Security */
414  disassemble); /* Instruction disass */
415 }
416 
417 void
419  std::ostream& outs,
420  int verbosity,
421  const std::string &prefix) const
422 {
423  // Print the memory record formatted according
424  // to the Tarmac specification
425  ccprintf(outs, "%s clk M%s%d %08x %0*x\n",
426  curTick(), /* Tick time */
427  loadAccess? "R" : "W", /* Access type */
428  size, /* Access size */
429  addr, /* Memory address */
430  size*2, /* Padding with access size */
431  data); /* Memory data */
432 }
433 
434 void
436  std::ostream& outs,
437  int verbosity,
438  const std::string &prefix) const
439 {
440  // Print the register record formatted according
441  // to the Tarmac specification
442  if (regValid)
443  ccprintf(outs, "%s clk R %s %08x\n",
444  curTick(), /* Tick time */
445  regName, /* Register name */
446  values[Lo]); /* Register value */
447 }
448 
449 } // namespace trace
450 } // namespace gem5
A high-level queue interface, to be used by both the MSHR queue and the write buffer.
Definition: queue.hh:71
T * get() const
Directly access the pointer itself without taking a reference.
Definition: refcnt.hh:227
Register ID: describe an architectural register with its class and index.
Definition: reg_class.hh:91
bool isFirstMicroop() const
Definition: static_inst.hh:189
uint8_t numDestRegs() const
Number of destination registers.
Definition: static_inst.hh:125
bool isLastMicroop() const
Definition: static_inst.hh:188
const RegId & destRegIdx(int i) const
Return logical index (architectural reg num) of i'th destination reg.
Definition: static_inst.hh:215
bool isMicroop() const
Definition: static_inst.hh:186
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId &reg) const
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
Addr addr
The address that was accessed.
Definition: insttracer.hh:85
StaticInstPtr staticInst
Definition: insttracer.hh:70
StaticInstPtr macroStaticInst
Definition: insttracer.hh:72
bool getMemValid() const
Definition: insttracer.hh:274
ThreadContext * thread
Definition: insttracer.hh:67
std::unique_ptr< PCStateBase > pc
Definition: insttracer.hh:71
uint64_t getIntData() const
Definition: insttracer.hh:276
bool predicate
is the predicate for execution this inst true or false (not execed)?
Definition: insttracer.hh:150
union gem5::trace::InstRecord::Data data
Addr size
The size of the memory request.
Definition: insttracer.hh:86
ISetState
ARM instruction set state.
Definition: tarmac_base.hh:78
This object type is encapsulating the informations needed by a Tarmac record to generate it's own ent...
const StaticInstPtr staticInst
virtual void addInstEntry(std::vector< InstPtr > &queue, const TarmacContext &ptr)
Generates an Entry for the executed instruction.
virtual void addRegEntry(std::vector< RegPtr > &queue, const TarmacContext &ptr)
Generate an Entry for every register being written.
virtual void dump() override
void flushQueues(Queue &queue)
Flush queues to the trace output.
virtual void addMemEntry(std::vector< MemPtr > &queue, const TarmacContext &ptr)
Generates an Entry for every triggered memory access.
TarmacTracer & tracer
Reference to tracer.
Tarmac Tracer: this tracer generates a new Tarmac Record for every instruction being executed in gem5...
std::vector< InstPtr > instQueue
Collection of heterogeneous printable entries: could be representing either instructions,...
std::vector< RegPtr > regQueue
std::vector< MemPtr > memQueue
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
constexpr RegId V
Definition: cc.hh:75
constexpr RegId C
Definition: cc.hh:74
constexpr RegId Ge
Definition: cc.hh:76
const char *const RegName[NumRegs]
Definition: cc.hh:80
constexpr RegId Nz
Definition: cc.hh:73
constexpr auto & Pc
Definition: int.hh:276
@ MODE_SYSTEM
Definition: types.hh:296
@ MODE_ABORT
Definition: types.hh:293
@ MODE_UNDEFINED
Definition: types.hh:295
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
bool isSecure(ThreadContext *tc)
Definition: utility.cc:74
constexpr auto & StackPointerReg
Definition: int.hh:654
constexpr auto & ReturnAddressReg
Definition: int.hh:655
@ MISCREG_CPSR
Definition: misc.hh:65
Bitfield< 24, 21 > opcode
Definition: types.hh:92
const char *const miscRegName[]
Definition: misc.hh:1697
constexpr auto & FramePointerReg
Definition: int.hh:653
constexpr auto & Lo
Definition: int.hh:205
Bitfield< 4 > pc
Bitfield< 5, 3 > reg
Definition: types.hh:92
bool regValid(Addr daddr)
Definition: sinicreg.hh:236
std::string iSetStateToStr(TarmacBaseRecord::ISetState isetstate)
Returns the string representation of the instruction set being currently run according to the Tarmac ...
std::string opModeToStr(OperatingMode opMode)
Returns the string representation of the ARM Operating Mode (CPSR.M[3:0] field) according to the Tarm...
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
@ VecPredRegClass
Definition: reg_class.hh:66
@ FloatRegClass
Floating-point register.
Definition: reg_class.hh:61
@ CCRegClass
Condition-code register.
Definition: reg_class.hh:67
@ VecRegClass
Vector Register.
Definition: reg_class.hh:63
@ IntRegClass
Integer register.
Definition: reg_class.hh:60
@ MiscRegClass
Control (misc) register.
Definition: reg_class.hh:68
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60
TARMAC instruction trace record.
Definition: tarmac_base.hh:86
TARMAC memory access trace record (stores only).
Definition: tarmac_base.hh:123
TARMAC register trace record.
Definition: tarmac_base.hh:103
bool secureMode
True if instruction is executed in secure mode.
virtual void print(std::ostream &outs, int verbosity=0, const std::string &prefix="") const override
static uint64_t instCount
Number of instructions being traced.
uint8_t instSize
Instruction size: 16 for 16-bit Thumb Instruction 32 otherwise (ARM and BigThumb)
TraceInstEntry(const TarmacContext &tarmCtx, bool predicate)
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
void update(const TarmacContext &tarmCtx)
This updates the register entry using the update table.
virtual void updateCC(const TarmacContext &tarmCtx)
virtual void updateFloat(const TarmacContext &tarmCtx)
virtual void print(std::ostream &outs, int verbosity=0, const std::string &prefix="") const override
virtual void updateMisc(const TarmacContext &tarmCtx)
Register update functions.
TraceRegEntry(const TarmacContext &tarmCtx, const RegId &reg)
virtual void updateInt(const TarmacContext &tarmCtx)

Generated on Wed Dec 21 2022 10:22:27 for gem5 by doxygen 1.9.1