gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
tarmac_record.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017-2019, 2023 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
45namespace gem5
46{
47
48using namespace ArmISA;
49
50namespace trace {
51
52// TARMAC Instruction Record static variables
54
55std::string
57{
58 switch (isetstate) {
60 return "A";
62 return "T";
64 return "O";
65 default:
66 return "Unsupported";
67 }
68}
69
70std::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
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 disassemble(tarmCtx.tracer.disassemble(tarmCtx.staticInst, *tarmCtx.pc))
128{
129 secureMode = isSecure(tarmCtx.thread);
130
131 auto arm_inst = static_cast<const ArmStaticInst*>(
132 tarmCtx.staticInst.get()
133 );
134
135 // Get the instruction size as a number of bits:
136 // (multiply byte size by 8)
137 instSize = (arm_inst->instSize() << 3);
138
139 // Mask the opcode using the instruction size: the
140 // opcode field will otherwise be 32 bit wide even
141 // for 16bit (Thumb) instruction.
142 opcode = arm_inst->encoding();
143
144 // In Tarmac, instruction names are printed in capital
145 // letters.
146 std::for_each(disassemble.begin(), disassemble.end(),
147 [](char& c) { c = toupper(c); });
148
149 // Update the instruction count: number of executed
150 // instructions.
151 instCount++;
152}
153
155 const TarmacContext& tarmCtx,
156 uint8_t _size, Addr _addr, uint64_t _data)
157 : MemEntry(_size, _addr, _data),
158 loadAccess(tarmCtx.staticInst->isLoad())
159{
160}
161
163 const TarmacContext& tarmCtx,
164 const RegId& reg)
165 : RegEntry(*tarmCtx.pc),
166 regValid(false),
167 regId(reg)
168{
169}
170
171void
173{
174 // Fill the register entry data, according to register
175 // class.
176 switch (regId.classValue()) {
177 case CCRegClass:
178 updateCC(tarmCtx);
179 break;
180 case FloatRegClass:
181 updateFloat(tarmCtx);
182 break;
183 case IntRegClass:
184 updateInt(tarmCtx);
185 break;
186 case MiscRegClass:
187 updateMisc(tarmCtx);
188 break;
189 case VecRegClass:
190 updateVec(tarmCtx);
191 break;
192 case VecPredRegClass:
193 updatePred(tarmCtx);
194 break;
195 default:
196 // If unsupported format, do nothing: non updating
197 // the register will prevent it to be printed.
198 break;
199 }
200}
201
202void
204{
205 auto thread = tarmCtx.thread;
206
207 regValid = true;
208 regName = miscRegName[regId.index()];
209 values[Lo] = thread->readMiscRegNoEffect(regId.index());
210
211 // If it is the CPSR:
212 // update the value of the CPSR register and add
213 // the CC flags on top of the value
214 if (regId.index() == MISCREG_CPSR) {
215 CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR);
216 cpsr.nz = thread->getReg(cc_reg::Nz);
217 cpsr.c = thread->getReg(cc_reg::C);
218 cpsr.v = thread->getReg(cc_reg::V);
219 cpsr.ge = thread->getReg(cc_reg::Ge);
220
221 // update the entry value
222 values[Lo] = cpsr;
223 }
224}
225
226void
228{
229 auto thread = tarmCtx.thread;
230
231 regValid = true;
232 regName = cc_reg::RegName[regId.index()];
233 values[Lo] = thread->getReg(regId);
234}
235
236void
238{
239 regValid = true;
240 regName = "f" + std::to_string(regId.index());
241 panic("ARM doesn't support float registers.");
242}
243
244void
246{
247 auto thread = tarmCtx.thread;
248
249 // Reading operating mode from CPSR.
250 // This is needed when printing the register name in case
251 // of banked register (e.g. lr_svc)
252 CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR);
253 OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
254
255 std::string reg_suffix;
256 if (mode != MODE_USER) {
257 reg_suffix = "_" + opModeToStr(mode);
258 }
259
260 regValid = true;
261 switch (regId.index()) {
262 case int_reg::Pc:
263 regName = "pc";
264 break;
265 case StackPointerReg:
266 regName = "sp" + reg_suffix ;
267 break;
268 case FramePointerReg:
269 regName = "fp" + reg_suffix;
270 break;
271 case ReturnAddressReg:
272 regName = "lr" + reg_suffix;
273 break;
274 default:
275 regName = "r" + std::to_string(regId.index());
276 break;
277 }
278 values[Lo] = thread->getReg(regId);
279}
280
281void
283 const TarmacContext& tarmCtx)
284{
285 // Generate an instruction entry in the record and
286 // add it to the Instruction Queue
287 queue.push_back(
288 std::make_unique<TraceInstEntry>(tarmCtx, predicate)
289 );
290}
291
292void
294 const TarmacContext& tarmCtx)
295{
296 // Generate a memory entry in the record if the record
297 // implies a valid memory access, and add it to the
298 // Memory Queue
299 if (getMemValid()) {
300 queue.push_back(
301 std::make_unique<TraceMemEntry>(tarmCtx,
302 static_cast<uint8_t>(getSize()),
303 getAddr(), getIntData())
304 );
305 }
306}
307
308void
310 const TarmacContext& tarmCtx)
311{
312 // Generate an entry for every ARM register being
313 // written by the current instruction
314 for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) {
315
316 RegId reg_id = staticInst->destRegIdx(reg);
317
318 // Creating a single register change entry
319 auto single_reg = genRegister<TraceRegEntry>(tarmCtx, reg_id);
320
321 // Copying the entry and adding it to the "list"
322 // of entries to be dumped to trace.
323 queue.push_back(std::make_unique<TraceRegEntry>(single_reg));
324 }
325
326 // Gem5 is treating CPSR flags as separate registers (CC registers),
327 // in contrast with Tarmac specification: we need to merge the gem5 CC
328 // entries altogether with the CPSR register and produce a single entry.
329 mergeCCEntry<TraceRegEntry>(queue, tarmCtx);
330}
331
332void
334{
335 // Generate and print all the record's entries.
336 auto &instQueue = tracer.instQueue;
337 auto &memQueue = tracer.memQueue;
338 auto &regQueue = tracer.regQueue;
339
340 const TarmacContext tarmCtx(
341 tracer,
342 thread,
343 staticInst->isMicroop()? macroStaticInst : staticInst,
344 *pc
345 );
346
347 if (!staticInst->isMicroop()) {
348 // Current instruction is NOT a micro-instruction:
349 // Generate Tarmac entries and dump them immediately
350
351 // Generate Tarmac entries and add them to the respective
352 // queues.
353 addInstEntry(instQueue, tarmCtx);
354 addMemEntry(memQueue, tarmCtx);
355 addRegEntry(regQueue, tarmCtx);
356
357 // Flush (print) any queued entry.
358 flushQueues(instQueue, memQueue, regQueue);
359
360 } else {
361 // Current instruction is a micro-instruction:
362 // save micro entries into dedicated queues and flush them
363 // into the tracefile only when the MACRO-instruction
364 // has completed.
365
366 if (staticInst->isFirstMicroop()) {
367 addInstEntry(instQueue, tarmCtx);
368 }
369
370 addRegEntry(regQueue, tarmCtx);
371 addMemEntry(memQueue, tarmCtx);
372
373 if (staticInst->isLastMicroop()) {
374 // Flush (print) any queued entry.
375 flushQueues(instQueue, memQueue, regQueue);
376 }
377 }
378}
379
380template<typename Queue>
381void
383{
384 std::ostream &outs = tracer.output();
385
386 for (const auto &single_entry : queue) {
387 single_entry->print(outs);
388 }
389
390 queue.clear();
391}
392
393template<typename Queue, typename... Args>
394void
396{
397 flushQueues(queue);
398 flushQueues(args...);
399}
400
401void
403 std::ostream& outs,
404 int verbosity,
405 const std::string &prefix) const
406{
407 // Pad the opcode
408 std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode);
409
410 // Print the instruction record formatted according
411 // to the Tarmac specification
412 ccprintf(outs, "%s clk %s (%u) %08x %s %s %s_%s : %s\n",
413 curTick(), /* Tick time */
414 taken? "IT" : "IS", /* Instruction taken/skipped */
415 instCount, /* Instruction count */
416 addr, /* Instruction address */
417 opcode_str, /* Instruction opcode */
418 iSetStateToStr(isetstate), /* Instruction Set */
419 opModeToStr(mode), /* Exception level */
420 secureMode? "s" : "ns", /* Security */
421 disassemble); /* Instruction disass */
422}
423
424void
426 std::ostream& outs,
427 int verbosity,
428 const std::string &prefix) const
429{
430 // Print the memory record formatted according
431 // to the Tarmac specification
432 ccprintf(outs, "%s clk M%s%d %08x %0*x\n",
433 curTick(), /* Tick time */
434 loadAccess? "R" : "W", /* Access type */
435 size, /* Access size */
436 addr, /* Memory address */
437 size*2, /* Padding with access size */
438 data); /* Memory data */
439}
440
441void
443 std::ostream& outs,
444 int verbosity,
445 const std::string &prefix) const
446{
447 // Print the register record formatted according
448 // to the Tarmac specification
449 if (regValid)
450 ccprintf(outs, "%s clk R %s %08x\n",
451 curTick(), /* Tick time */
452 regName, /* Register name */
453 values[Lo]); /* Register value */
454}
455
456} // namespace trace
457} // 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:94
ThreadContext is the external interface to all thread state for anything outside of the CPU.
StaticInstPtr staticInst
Definition insttracer.hh:71
StaticInstPtr macroStaticInst
Definition insttracer.hh:73
ThreadContext * thread
Definition insttracer.hh:68
std::unique_ptr< PCStateBase > pc
Definition insttracer.hh:72
uint64_t getIntData() const
bool predicate
is the predicate for execution this inst true or false (not execed)?
ISetState
ARM instruction set state.
TarmacBaseRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, const StaticInstPtr _macroStaticInst=nullptr)
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.
void mergeCCEntry(std::vector< RegPtr > &queue, const TarmacContext &tarmCtx)
RegEntry genRegister(const TarmacContext &tarmCtx, const RegId &reg)
Generate and update a register entry.
virtual void addRegEntry(std::vector< RegPtr > &queue, const TarmacContext &ptr)
Generate an Entry for every register being written.
virtual void dump() override
TarmacTracerRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, TarmacTracer &_tracer, const StaticInstPtr _macroStaticInst=NULL)
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...
STL vector class.
Definition stl.hh:37
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
constexpr RegId V
Definition cc.hh:96
constexpr RegId C
Definition cc.hh:95
constexpr RegId Ge
Definition cc.hh:97
const char *const RegName[NumRegs]
Definition cc.hh:64
constexpr RegId Nz
Definition cc.hh:94
constexpr auto & Pc
Definition int.hh:276
@ MODE_UNDEFINED
Definition types.hh:332
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
Bitfield< 29 > c
Definition misc_types.hh:53
@ MISCREG_CPSR
Definition misc.hh:79
const char *const miscRegName[]
Definition misc.hh:1849
constexpr auto & FramePointerReg
Definition int.hh:653
Bitfield< 5, 3 > reg
Definition types.hh:92
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...
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
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
RefCountingPtr< StaticInst > StaticInstPtr
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
@ VecPredRegClass
Definition reg_class.hh:67
@ FloatRegClass
Floating-point register.
Definition reg_class.hh:62
@ CCRegClass
Condition-code register.
Definition reg_class.hh:69
@ VecRegClass
Vector Register.
Definition reg_class.hh:64
@ IntRegClass
Integer register.
Definition reg_class.hh:61
@ MiscRegClass
Control (misc) register.
Definition reg_class.hh:70
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
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
std::string disassemble
Instruction disassembly.
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
bool loadAccess
True if memory access is a load.
void update(const TarmacContext &tarmCtx)
This updates the register entry using the update table.
bool regValid
True if register entry is valid.
virtual void updateCC(const TarmacContext &tarmCtx)
virtual void updatePred(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.
virtual void updateVec(const TarmacContext &tarmCtx)
TraceRegEntry(const TarmacContext &tarmCtx, const RegId &reg)
std::string regName
Register name to be printed.
virtual void updateInt(const TarmacContext &tarmCtx)

Generated on Mon May 26 2025 09:18:58 for gem5 by doxygen 1.13.2