2 * Copyright (c) 2017-2019 ARM Limited
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.
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.
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.
38 #include "arch/arm/tracers/tarmac_record_v8.hh"
40 #include "arch/arm/insts/static_inst.hh"
41 #include "arch/arm/tlb.hh"
42 #include "arch/arm/tracers/tarmac_tracer.hh"
44 using namespace ArmISA
;
48 TarmacTracerRecordV8::TraceInstEntryV8::TraceInstEntryV8(
49 const TarmacContext
& tarmCtx
,
51 : TraceInstEntry(tarmCtx
, predicate
),
52 TraceEntryV8(tarmCtx
.tarmacCpuName()),
56 const auto thread
= tarmCtx
.thread
;
58 // Evaluate physical address
59 ArmISA::TLB
* dtb
= static_cast<TLB
*>(thread
->getDTBPtr());
60 paddrValid
= dtb
->translateFunctional(thread
, addr
, paddr
);
63 TarmacTracerRecordV8::TraceMemEntryV8::TraceMemEntryV8(
64 const TarmacContext
& tarmCtx
,
65 uint8_t _size
, Addr _addr
, uint64_t _data
)
66 : TraceMemEntry(tarmCtx
, _size
, _addr
, _data
),
67 TraceEntryV8(tarmCtx
.tarmacCpuName()),
70 const auto thread
= tarmCtx
.thread
;
72 // Evaluate physical address
73 ArmISA::TLB
* dtb
= static_cast<TLB
*>(thread
->getDTBPtr());
74 dtb
->translateFunctional(thread
, addr
, paddr
);
77 TarmacTracerRecordV8::TraceRegEntryV8::TraceRegEntryV8(
78 const TarmacContext
& tarmCtx
,
80 : TraceRegEntry(tarmCtx
, reg
),
81 TraceEntryV8(tarmCtx
.tarmacCpuName()),
87 TarmacTracerRecordV8::TraceRegEntryV8::updateInt(
88 const TarmacContext
& tarmCtx
,
92 // Do not trace pseudo register accesses: invalid
94 if (regRelIdx
> NUM_ARCH_INTREGS
) {
99 TraceRegEntry::updateInt(tarmCtx
, regRelIdx
);
101 if ((regRelIdx
!= PCReg
) || (regRelIdx
!= StackPointerReg
) ||
102 (regRelIdx
!= FramePointerReg
) || (regRelIdx
!= ReturnAddressReg
)) {
104 const auto* arm_inst
= static_cast<const ArmStaticInst
*>(
105 tarmCtx
.staticInst
.get()
108 regWidth
= (arm_inst
->getIntWidth());
109 if (regWidth
== 32) {
110 regName
= "W" + std::to_string(regRelIdx
);
112 regName
= "X" + std::to_string(regRelIdx
);
118 TarmacTracerRecordV8::TraceRegEntryV8::updateMisc(
119 const TarmacContext
& tarmCtx
,
123 TraceRegEntry::updateMisc(tarmCtx
, regRelIdx
);
124 // System registers are 32bit wide
129 TarmacTracerRecordV8::TraceRegEntryV8::updateVec(
130 const TarmacContext
& tarmCtx
,
134 auto thread
= tarmCtx
.thread
;
135 const auto& vec_container
= thread
->readVecReg(
136 RegId(regClass
, regRelIdx
));
137 auto vv
= vec_container
.as
<VecElem
>();
139 regWidth
= ArmStaticInst::getCurSveVecLenInBits(thread
);
140 auto num_elements
= regWidth
/ (sizeof(VecElem
) * 8);
142 // Resize vector of values
143 values
.resize(num_elements
);
145 for (auto i
= 0; i
< num_elements
; i
++) {
150 regName
= "Z" + std::to_string(regRelIdx
);
154 TarmacTracerRecordV8::TraceRegEntryV8::updatePred(
155 const TarmacContext
& tarmCtx
,
159 auto thread
= tarmCtx
.thread
;
160 const auto& pred_container
= thread
->readVecPredReg(
161 RegId(regClass
, regRelIdx
));
163 // Predicate registers are always 1/8 the size of related vector
164 // registers. (getCurSveVecLenInBits(thread) / 8)
165 regWidth
= ArmStaticInst::getCurSveVecLenInBits(thread
) / 8;
166 auto num_elements
= regWidth
/ 16;
168 // Resize vector of values
169 values
.resize(num_elements
);
171 // Get a copy of pred_container as a vector of half-words
172 auto vv
= pred_container
.as
<uint16_t>();
173 for (auto i
= 0; i
< num_elements
; i
++) {
178 regName
= "P" + std::to_string(regRelIdx
);
182 TarmacTracerRecordV8::addInstEntry(std::vector
<InstPtr
>& queue
,
183 const TarmacContext
& tarmCtx
)
185 // Generate an instruction entry in the record and
186 // add it to the Instruction Queue
188 m5::make_unique
<TraceInstEntryV8
>(tarmCtx
, predicate
)
193 TarmacTracerRecordV8::addMemEntry(std::vector
<MemPtr
>& queue
,
194 const TarmacContext
& tarmCtx
)
196 // Generate a memory entry in the record if the record
197 // implies a valid memory access, and add it to the
201 m5::make_unique
<TraceMemEntryV8
>(tarmCtx
,
202 static_cast<uint8_t>(getSize()),
203 getAddr(), getIntData())
209 TarmacTracerRecordV8::addRegEntry(std::vector
<RegPtr
>& queue
,
210 const TarmacContext
& tarmCtx
)
212 // Generate an entry for every ARM register being
213 // written by the current instruction
214 for (auto reg
= 0; reg
< staticInst
->numDestRegs(); ++reg
) {
216 RegId reg_id
= staticInst
->destRegIdx(reg
);
218 // Creating a single register change entry
219 auto single_reg
= genRegister
<TraceRegEntryV8
>(tarmCtx
, reg_id
);
221 // Copying the entry and adding it to the "list"
222 // of entries to be dumped to trace.
224 m5::make_unique
<TraceRegEntryV8
>(single_reg
)
228 // Gem5 is treating CPSR flags as separate registers (CC registers),
229 // in contrast with Tarmac specification: we need to merge the gem5 CC
230 // entries altogether with the CPSR register and produce a single entry.
231 mergeCCEntry
<TraceRegEntryV8
>(queue
, tarmCtx
);
235 TarmacTracerRecordV8::TraceInstEntryV8::print(
238 const std::string
&prefix
) const
240 // If there is a valid vaddr->paddr translation, print the
241 // physical address, otherwise print the virtual address only.
242 std::string paddr_str
= paddrValid
? csprintf(":%012x",paddr
) :
246 std::string opcode_str
= csprintf("%0*x", instSize
>> 2, opcode
);
248 // Print the instruction record formatted according
249 // to the Tarmac specification
250 ccprintf(outs
, "%s clk %s %s (%u) %08x%s %s %s %s_%s : %s\n",
251 curTick(), /* Tick time */
252 cpuName
, /* Cpu name */
253 taken
? "IT" : "IS", /* Instruction taken/skipped */
254 instCount
, /* Instruction count */
255 addr
, /* Instruction virt address */
256 paddr_str
, /* Instruction phys address */
257 opcode_str
, /* Instruction opcode */
258 iSetStateToStr(isetstate
), /* Instruction Set */
259 opModeToStr(mode
), /* Exception level */
260 secureMode
? "s" : "ns", /* Security */
261 disassemble
); /* Instruction disass */
265 TarmacTracerRecordV8::TraceMemEntryV8::print(
268 const std::string
&prefix
) const
270 // Print the memory record formatted according
271 // to the Tarmac specification
272 ccprintf(outs
, "%s clk %s M%s%d %08x:%012x %0*x\n",
273 curTick(), /* Tick time */
274 cpuName
, /* Cpu name */
275 loadAccess
? "R" : "W", /* Access type */
276 size
, /* Access size */
277 addr
, /* Virt Memory address */
278 paddr
, /* Phys Memory address */
279 size
*2, /* Padding with access size */
280 data
); /* Memory data */
284 TarmacTracerRecordV8::TraceRegEntryV8::print(
287 const std::string
&prefix
) const
289 // Print the register record formatted according
290 // to the Tarmac specification
292 ccprintf(outs
, "%s clk %s R %s %s\n",
293 curTick(), /* Tick time */
294 cpuName
, /* Cpu name */
295 regName
, /* Register name */
296 formatReg()); /* Register value */
301 TarmacTracerRecordV8::TraceRegEntryV8::formatReg() const
303 if (regWidth
<= 64) {
304 // Register width is < 64 bit (scalar register).
305 return csprintf("%0*x", regWidth
/ 4, values
[Lo
]);
308 // Register width is > 64 bit (vector). Iterate over every vector
309 // element. Since the vector values are stored in Little Endian, print
310 // starting from the last element.
312 for (auto it
= values
.rbegin(); it
!= values
.rend(); it
++) {
313 reg_val
+= csprintf("%0*x_",
314 static_cast<int>(sizeof(VecElem
) * 2), *it
);
317 // Remove trailing underscore