exetrace.cc (4011:e6899d7ca5b1) exetrace.cc (4046:ef34b290091e)
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 * Lisa Hsu
30 * Nathan Binkert
31 * Steve Raasch
32 */
33
34#include <fstream>
35#include <iomanip>
36#include <sys/ipc.h>
37#include <sys/shm.h>
38
39#include "arch/regfile.hh"
40#include "arch/utility.hh"
41#include "base/loader/symtab.hh"
42#include "config/full_system.hh"
43#include "cpu/base.hh"
44#include "cpu/exetrace.hh"
45#include "cpu/static_inst.hh"
46#include "sim/param.hh"
47#include "sim/system.hh"
48
49#if FULL_SYSTEM
50#include "arch/tlb.hh"
51#endif
52
53//XXX This is temporary
54#include "arch/isa_specific.hh"
55#include "cpu/m5legion_interface.h"
56
57using namespace std;
58using namespace TheISA;
59
60#if THE_ISA == SPARC_ISA && FULL_SYSTEM
61static int diffcount = 0;
62static bool wasMicro = false;
63#endif
64
65namespace Trace {
66SharedData *shared_data = NULL;
67}
68
69////////////////////////////////////////////////////////////////////////
70//
71// Methods for the InstRecord object
72//
73
74#if THE_ISA == SPARC_ISA
75
76inline char * genCenteredLabel(int length, char * buffer, char * label)
77{
78 int labelLength = strlen(label);
79 assert(labelLength <= length);
80 int leftPad = (length - labelLength) / 2;
81 int rightPad = length - leftPad - labelLength;
82 char format[64];
83 sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
84 sprintf(buffer, format, "", label, "");
85 return buffer;
86}
87
88inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
89{
90 ccprintf(os, " %16s | %#018x %s %#-018x \n",
91 title, a, (a == b) ? "|" : "X", b);
92}
93
94inline void printColumnLabels(ostream & os)
95{
96 static char * regLabel = genCenteredLabel(16, new char[17], "Register");
97 static char * m5Label = genCenteredLabel(18, new char[18], "M5");
98 static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
99 ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel);
100 ccprintf(os, "--------------------+-----------------------+-----------------------\n");
101}
102
103inline void printSectionHeader(ostream & os, char * name)
104{
105 char sectionString[70];
106 genCenteredLabel(69, sectionString, name);
107 ccprintf(os, "====================================================================\n");
108 ccprintf(os, "%69s\n", sectionString);
109 ccprintf(os, "====================================================================\n");
110}
111
112inline void printLevelHeader(ostream & os, int level)
113{
114 char sectionString[70];
115 char levelName[70];
116 sprintf(levelName, "Trap stack level %d", level);
117 genCenteredLabel(69, sectionString, levelName);
118 ccprintf(os, "====================================================================\n");
119 ccprintf(os, "%69s\n", sectionString);
120 ccprintf(os, "====================================================================\n");
121}
122
123#endif
124
125void
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 * Lisa Hsu
30 * Nathan Binkert
31 * Steve Raasch
32 */
33
34#include <fstream>
35#include <iomanip>
36#include <sys/ipc.h>
37#include <sys/shm.h>
38
39#include "arch/regfile.hh"
40#include "arch/utility.hh"
41#include "base/loader/symtab.hh"
42#include "config/full_system.hh"
43#include "cpu/base.hh"
44#include "cpu/exetrace.hh"
45#include "cpu/static_inst.hh"
46#include "sim/param.hh"
47#include "sim/system.hh"
48
49#if FULL_SYSTEM
50#include "arch/tlb.hh"
51#endif
52
53//XXX This is temporary
54#include "arch/isa_specific.hh"
55#include "cpu/m5legion_interface.h"
56
57using namespace std;
58using namespace TheISA;
59
60#if THE_ISA == SPARC_ISA && FULL_SYSTEM
61static int diffcount = 0;
62static bool wasMicro = false;
63#endif
64
65namespace Trace {
66SharedData *shared_data = NULL;
67}
68
69////////////////////////////////////////////////////////////////////////
70//
71// Methods for the InstRecord object
72//
73
74#if THE_ISA == SPARC_ISA
75
76inline char * genCenteredLabel(int length, char * buffer, char * label)
77{
78 int labelLength = strlen(label);
79 assert(labelLength <= length);
80 int leftPad = (length - labelLength) / 2;
81 int rightPad = length - leftPad - labelLength;
82 char format[64];
83 sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
84 sprintf(buffer, format, "", label, "");
85 return buffer;
86}
87
88inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
89{
90 ccprintf(os, " %16s | %#018x %s %#-018x \n",
91 title, a, (a == b) ? "|" : "X", b);
92}
93
94inline void printColumnLabels(ostream & os)
95{
96 static char * regLabel = genCenteredLabel(16, new char[17], "Register");
97 static char * m5Label = genCenteredLabel(18, new char[18], "M5");
98 static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
99 ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel);
100 ccprintf(os, "--------------------+-----------------------+-----------------------\n");
101}
102
103inline void printSectionHeader(ostream & os, char * name)
104{
105 char sectionString[70];
106 genCenteredLabel(69, sectionString, name);
107 ccprintf(os, "====================================================================\n");
108 ccprintf(os, "%69s\n", sectionString);
109 ccprintf(os, "====================================================================\n");
110}
111
112inline void printLevelHeader(ostream & os, int level)
113{
114 char sectionString[70];
115 char levelName[70];
116 sprintf(levelName, "Trap stack level %d", level);
117 genCenteredLabel(69, sectionString, levelName);
118 ccprintf(os, "====================================================================\n");
119 ccprintf(os, "%69s\n", sectionString);
120 ccprintf(os, "====================================================================\n");
121}
122
123#endif
124
125void
126Trace::InstRecord::dump(ostream &outs)
126Trace::InstRecord::dump()
127{
127{
128 ostream &outs = Trace::output();
129
128 DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
129 if (flags[PRINT_REG_DELTA])
130 {
131#if THE_ISA == SPARC_ISA
132 //Don't print what happens for each micro-op, just print out
133 //once at the last op, and for regular instructions.
134 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
135 {
136 static uint64_t regs[32] = {
137 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0};
141 static uint64_t ccr = 0;
142 static uint64_t y = 0;
143 static uint64_t floats[32];
144 uint64_t newVal;
145 static const char * prefixes[4] = {"G", "O", "L", "I"};
146
147 outs << hex;
148 outs << "PC = " << thread->readNextPC();
149 outs << " NPC = " << thread->readNextNPC();
150 newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
151 //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
152 if(newVal != ccr)
153 {
154 outs << " CCR = " << newVal;
155 ccr = newVal;
156 }
157 newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
158 //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
159 if(newVal != y)
160 {
161 outs << " Y = " << newVal;
162 y = newVal;
163 }
164 for(int y = 0; y < 4; y++)
165 {
166 for(int x = 0; x < 8; x++)
167 {
168 int index = x + 8 * y;
169 newVal = thread->readIntReg(index);
170 if(regs[index] != newVal)
171 {
172 outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
173 regs[index] = newVal;
174 }
175 }
176 }
177 for(int y = 0; y < 32; y++)
178 {
179 newVal = thread->readFloatRegBits(2 * y, 64);
180 if(floats[y] != newVal)
181 {
182 outs << " F" << dec << (2 * y) << " = " << hex << newVal;
183 floats[y] = newVal;
184 }
185 }
186 outs << dec << endl;
187 }
188#endif
189 }
190 else if (flags[INTEL_FORMAT]) {
191#if FULL_SYSTEM
192 bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
193#else
194 bool is_trace_system = true;
195#endif
196 if (is_trace_system) {
130 DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
131 if (flags[PRINT_REG_DELTA])
132 {
133#if THE_ISA == SPARC_ISA
134 //Don't print what happens for each micro-op, just print out
135 //once at the last op, and for regular instructions.
136 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
137 {
138 static uint64_t regs[32] = {
139 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0};
143 static uint64_t ccr = 0;
144 static uint64_t y = 0;
145 static uint64_t floats[32];
146 uint64_t newVal;
147 static const char * prefixes[4] = {"G", "O", "L", "I"};
148
149 outs << hex;
150 outs << "PC = " << thread->readNextPC();
151 outs << " NPC = " << thread->readNextNPC();
152 newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
153 //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
154 if(newVal != ccr)
155 {
156 outs << " CCR = " << newVal;
157 ccr = newVal;
158 }
159 newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
160 //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
161 if(newVal != y)
162 {
163 outs << " Y = " << newVal;
164 y = newVal;
165 }
166 for(int y = 0; y < 4; y++)
167 {
168 for(int x = 0; x < 8; x++)
169 {
170 int index = x + 8 * y;
171 newVal = thread->readIntReg(index);
172 if(regs[index] != newVal)
173 {
174 outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
175 regs[index] = newVal;
176 }
177 }
178 }
179 for(int y = 0; y < 32; y++)
180 {
181 newVal = thread->readFloatRegBits(2 * y, 64);
182 if(floats[y] != newVal)
183 {
184 outs << " F" << dec << (2 * y) << " = " << hex << newVal;
185 floats[y] = newVal;
186 }
187 }
188 outs << dec << endl;
189 }
190#endif
191 }
192 else if (flags[INTEL_FORMAT]) {
193#if FULL_SYSTEM
194 bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
195#else
196 bool is_trace_system = true;
197#endif
198 if (is_trace_system) {
197 ccprintf(outs, "%7d ) ", cycle);
199 ccprintf(outs, "%7d ) ", when);
198 outs << "0x" << hex << PC << ":\t";
199 if (staticInst->isLoad()) {
200 outs << "<RD 0x" << hex << addr;
201 outs << ">";
202 } else if (staticInst->isStore()) {
203 outs << "<WR 0x" << hex << addr;
204 outs << ">";
205 }
206 outs << endl;
207 }
208 } else {
200 outs << "0x" << hex << PC << ":\t";
201 if (staticInst->isLoad()) {
202 outs << "<RD 0x" << hex << addr;
203 outs << ">";
204 } else if (staticInst->isStore()) {
205 outs << "<WR 0x" << hex << addr;
206 outs << ">";
207 }
208 outs << endl;
209 }
210 } else {
209 if (flags[PRINT_CYCLE])
210 ccprintf(outs, "%7d: ", cycle);
211 if (flags[PRINT_TICKS])
212 ccprintf(outs, "%7d: ", when);
211
212 outs << thread->getCpuPtr()->name() << " ";
213
214 if (flags[TRACE_MISSPEC])
215 outs << (misspeculating ? "-" : "+") << " ";
216
217 if (flags[PRINT_THREAD_NUM])
218 outs << "T" << thread->getThreadNum() << " : ";
219
220
221 std::string sym_str;
222 Addr sym_addr;
223 if (debugSymbolTable
224 && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
225 && flags[PC_SYMBOL]) {
226 if (PC != sym_addr)
227 sym_str += csprintf("+%d", PC - sym_addr);
228 outs << "@" << sym_str << " : ";
229 }
230 else {
231 outs << "0x" << hex << PC << " : ";
232 }
233
234 //
235 // Print decoded instruction
236 //
237
238#if defined(__GNUC__) && (__GNUC__ < 3)
239 // There's a bug in gcc 2.x library that prevents setw()
240 // from working properly on strings
241 string mc(staticInst->disassemble(PC, debugSymbolTable));
242 while (mc.length() < 26)
243 mc += " ";
244 outs << mc;
245#else
246 outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
247#endif
248
249 outs << " : ";
250
251 if (flags[PRINT_OP_CLASS]) {
252 outs << opClassStrings[staticInst->opClass()] << " : ";
253 }
254
255 if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
256 outs << " D=";
257#if 0
258 if (data_status == DataDouble)
259 ccprintf(outs, "%f", data.as_double);
260 else
261 ccprintf(outs, "%#018x", data.as_int);
262#else
263 ccprintf(outs, "%#018x", data.as_int);
264#endif
265 }
266
267 if (flags[PRINT_EFF_ADDR] && addr_valid)
268 outs << " A=0x" << hex << addr;
269
270 if (flags[PRINT_INT_REGS] && regs_valid) {
271 for (int i = 0; i < TheISA::NumIntRegs;)
272 for (int j = i + 1; i <= j; i++)
273 ccprintf(outs, "r%02d = %#018x%s", i,
274 iregs->regs.readReg(i),
275 ((i == j) ? "\n" : " "));
276 outs << "\n";
277 }
278
279 if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
280 outs << " FetchSeq=" << dec << fetch_seq;
281
282 if (flags[PRINT_CP_SEQ] && cp_seq_valid)
283 outs << " CPSeq=" << dec << cp_seq;
284
285 //
286 // End of line...
287 //
288 outs << endl;
289 }
290#if THE_ISA == SPARC_ISA && FULL_SYSTEM
291 // Compare
292 if (flags[LEGION_LOCKSTEP])
293 {
294 bool compared = false;
295 bool diffPC = false;
296 bool diffCC = false;
297 bool diffInst = false;
298 bool diffIntRegs = false;
299 bool diffFpRegs = false;
300 bool diffTpc = false;
301 bool diffTnpc = false;
302 bool diffTstate = false;
303 bool diffTt = false;
304 bool diffTba = false;
305 bool diffHpstate = false;
306 bool diffHtstate = false;
307 bool diffHtba = false;
308 bool diffPstate = false;
309 bool diffY = false;
310 bool diffFsr = false;
311 bool diffCcr = false;
312 bool diffTl = false;
313 bool diffGl = false;
314 bool diffAsi = false;
315 bool diffPil = false;
316 bool diffCwp = false;
317 bool diffCansave = false;
318 bool diffCanrestore = false;
319 bool diffOtherwin = false;
320 bool diffCleanwin = false;
321 bool diffTlb = false;
322 Addr m5Pc, lgnPc;
323
324 // We took a trap on a micro-op...
325 if (wasMicro && !staticInst->isMicroOp())
326 {
213
214 outs << thread->getCpuPtr()->name() << " ";
215
216 if (flags[TRACE_MISSPEC])
217 outs << (misspeculating ? "-" : "+") << " ";
218
219 if (flags[PRINT_THREAD_NUM])
220 outs << "T" << thread->getThreadNum() << " : ";
221
222
223 std::string sym_str;
224 Addr sym_addr;
225 if (debugSymbolTable
226 && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
227 && flags[PC_SYMBOL]) {
228 if (PC != sym_addr)
229 sym_str += csprintf("+%d", PC - sym_addr);
230 outs << "@" << sym_str << " : ";
231 }
232 else {
233 outs << "0x" << hex << PC << " : ";
234 }
235
236 //
237 // Print decoded instruction
238 //
239
240#if defined(__GNUC__) && (__GNUC__ < 3)
241 // There's a bug in gcc 2.x library that prevents setw()
242 // from working properly on strings
243 string mc(staticInst->disassemble(PC, debugSymbolTable));
244 while (mc.length() < 26)
245 mc += " ";
246 outs << mc;
247#else
248 outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
249#endif
250
251 outs << " : ";
252
253 if (flags[PRINT_OP_CLASS]) {
254 outs << opClassStrings[staticInst->opClass()] << " : ";
255 }
256
257 if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
258 outs << " D=";
259#if 0
260 if (data_status == DataDouble)
261 ccprintf(outs, "%f", data.as_double);
262 else
263 ccprintf(outs, "%#018x", data.as_int);
264#else
265 ccprintf(outs, "%#018x", data.as_int);
266#endif
267 }
268
269 if (flags[PRINT_EFF_ADDR] && addr_valid)
270 outs << " A=0x" << hex << addr;
271
272 if (flags[PRINT_INT_REGS] && regs_valid) {
273 for (int i = 0; i < TheISA::NumIntRegs;)
274 for (int j = i + 1; i <= j; i++)
275 ccprintf(outs, "r%02d = %#018x%s", i,
276 iregs->regs.readReg(i),
277 ((i == j) ? "\n" : " "));
278 outs << "\n";
279 }
280
281 if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
282 outs << " FetchSeq=" << dec << fetch_seq;
283
284 if (flags[PRINT_CP_SEQ] && cp_seq_valid)
285 outs << " CPSeq=" << dec << cp_seq;
286
287 //
288 // End of line...
289 //
290 outs << endl;
291 }
292#if THE_ISA == SPARC_ISA && FULL_SYSTEM
293 // Compare
294 if (flags[LEGION_LOCKSTEP])
295 {
296 bool compared = false;
297 bool diffPC = false;
298 bool diffCC = false;
299 bool diffInst = false;
300 bool diffIntRegs = false;
301 bool diffFpRegs = false;
302 bool diffTpc = false;
303 bool diffTnpc = false;
304 bool diffTstate = false;
305 bool diffTt = false;
306 bool diffTba = false;
307 bool diffHpstate = false;
308 bool diffHtstate = false;
309 bool diffHtba = false;
310 bool diffPstate = false;
311 bool diffY = false;
312 bool diffFsr = false;
313 bool diffCcr = false;
314 bool diffTl = false;
315 bool diffGl = false;
316 bool diffAsi = false;
317 bool diffPil = false;
318 bool diffCwp = false;
319 bool diffCansave = false;
320 bool diffCanrestore = false;
321 bool diffOtherwin = false;
322 bool diffCleanwin = false;
323 bool diffTlb = false;
324 Addr m5Pc, lgnPc;
325
326 // We took a trap on a micro-op...
327 if (wasMicro && !staticInst->isMicroOp())
328 {
327 // let's skip comparing this cycle
329 // let's skip comparing this tick
328 while (!compared)
329 if (shared_data->flags == OWN_M5) {
330 shared_data->flags = OWN_LEGION;
331 compared = true;
332 }
333 compared = false;
334 wasMicro = false;
335 }
336
337 if (staticInst->isLastMicroOp())
338 wasMicro = false;
339 else if (staticInst->isMicroOp())
340 wasMicro = true;
341
342
343 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
344 while (!compared) {
345 if (shared_data->flags == OWN_M5) {
346 m5Pc = PC & TheISA::PAddrImplMask;
347 if (bits(shared_data->pstate,3,3)) {
348 m5Pc &= mask(32);
349 }
350 lgnPc = shared_data->pc & TheISA::PAddrImplMask;
351 if (lgnPc != m5Pc)
352 diffPC = true;
353
354 if (shared_data->cycle_count !=
355 thread->getCpuPtr()->instCount())
356 diffCC = true;
357
358 if (shared_data->instruction !=
359 (SparcISA::MachInst)staticInst->machInst) {
360 diffInst = true;
361 }
362 // assume we have %g0 working correctly
363 for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
364 if (thread->readIntReg(i) != shared_data->intregs[i]) {
365 diffIntRegs = true;
366 }
367 }
368 for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
369 if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
370 diffFpRegs = true;
371 }
372 }
373 uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
374 if (oldTl != shared_data->tl)
375 diffTl = true;
376 for (int i = 1; i <= MaxTL; i++) {
377 thread->setMiscReg(MISCREG_TL, i);
378 if (thread->readMiscReg(MISCREG_TPC) !=
379 shared_data->tpc[i-1])
380 diffTpc = true;
381 if (thread->readMiscReg(MISCREG_TNPC) !=
382 shared_data->tnpc[i-1])
383 diffTnpc = true;
384 if (thread->readMiscReg(MISCREG_TSTATE) !=
385 shared_data->tstate[i-1])
386 diffTstate = true;
387 if (thread->readMiscReg(MISCREG_TT) !=
388 shared_data->tt[i-1])
389 diffTt = true;
390 if (thread->readMiscReg(MISCREG_HTSTATE) !=
391 shared_data->htstate[i-1])
392 diffHtstate = true;
393 }
394 thread->setMiscReg(MISCREG_TL, oldTl);
395
396 if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
397 diffTba = true;
398 //When the hpstate register is read by an instruction,
399 //legion has bit 11 set. When it's in storage, it doesn't.
400 //Since we don't directly support seperate interpretations
401 //of the registers like that, the bit is always set to 1 and
402 //we just don't compare it. It's not supposed to matter
403 //anyway.
404 if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
405 diffHpstate = true;
406 if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
407 diffHtba = true;
408 if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
409 diffPstate = true;
410 //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
411 if(shared_data->y !=
412 thread->readIntReg(NumIntArchRegs + 1))
413 diffY = true;
414 if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) {
415 diffFsr = true;
416 if (mbits(shared_data->fsr, 63,10) ==
417 mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) {
418 thread->setMiscReg(MISCREG_FSR, shared_data->fsr);
419 diffFsr = false;
420 }
421 }
422 //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
423 if(shared_data->ccr !=
424 thread->readIntReg(NumIntArchRegs + 2))
425 diffCcr = true;
426 if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
427 diffGl = true;
428 if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
429 diffAsi = true;
430 if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
431 diffPil = true;
432 if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
433 diffCwp = true;
434 //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
435 if(shared_data->cansave !=
436 thread->readIntReg(NumIntArchRegs + 3))
437 diffCansave = true;
438 //if(shared_data->canrestore !=
439 // thread->readMiscReg(MISCREG_CANRESTORE))
440 if(shared_data->canrestore !=
441 thread->readIntReg(NumIntArchRegs + 4))
442 diffCanrestore = true;
443 //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
444 if(shared_data->otherwin !=
445 thread->readIntReg(NumIntArchRegs + 6))
446 diffOtherwin = true;
447 //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
448 if(shared_data->cleanwin !=
449 thread->readIntReg(NumIntArchRegs + 5))
450 diffCleanwin = true;
451
452 for (int i = 0; i < 64; i++) {
453 if (shared_data->itb[i] != thread->getITBPtr()->TteRead(i))
454 diffTlb = true;
455 if (shared_data->dtb[i] != thread->getDTBPtr()->TteRead(i))
456 diffTlb = true;
457 }
458
459 if (diffPC || diffCC || diffInst || diffIntRegs ||
460 diffFpRegs || diffTpc || diffTnpc || diffTstate ||
461 diffTt || diffHpstate || diffHtstate || diffHtba ||
462 diffPstate || diffY || diffCcr || diffTl || diffFsr ||
463 diffGl || diffAsi || diffPil || diffCwp || diffCansave ||
464 diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
465 {
466
467 outs << "Differences found between M5 and Legion:";
468 if (diffPC)
469 outs << " [PC]";
470 if (diffCC)
471 outs << " [CC]";
472 if (diffInst)
473 outs << " [Instruction]";
474 if (diffIntRegs)
475 outs << " [IntRegs]";
476 if (diffFpRegs)
477 outs << " [FpRegs]";
478 if (diffTpc)
479 outs << " [Tpc]";
480 if (diffTnpc)
481 outs << " [Tnpc]";
482 if (diffTstate)
483 outs << " [Tstate]";
484 if (diffTt)
485 outs << " [Tt]";
486 if (diffHpstate)
487 outs << " [Hpstate]";
488 if (diffHtstate)
489 outs << " [Htstate]";
490 if (diffHtba)
491 outs << " [Htba]";
492 if (diffPstate)
493 outs << " [Pstate]";
494 if (diffY)
495 outs << " [Y]";
496 if (diffFsr)
497 outs << " [FSR]";
498 if (diffCcr)
499 outs << " [Ccr]";
500 if (diffTl)
501 outs << " [Tl]";
502 if (diffGl)
503 outs << " [Gl]";
504 if (diffAsi)
505 outs << " [Asi]";
506 if (diffPil)
507 outs << " [Pil]";
508 if (diffCwp)
509 outs << " [Cwp]";
510 if (diffCansave)
511 outs << " [Cansave]";
512 if (diffCanrestore)
513 outs << " [Canrestore]";
514 if (diffOtherwin)
515 outs << " [Otherwin]";
516 if (diffCleanwin)
517 outs << " [Cleanwin]";
518 if (diffTlb)
519 outs << " [Tlb]";
520 outs << endl << endl;
521
522 outs << right << setfill(' ') << setw(15)
523 << "M5 PC: " << "0x"<< setw(16) << setfill('0')
524 << hex << m5Pc << endl;
525 outs << setfill(' ') << setw(15)
526 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
527 << lgnPc << endl << endl;
528
529 outs << right << setfill(' ') << setw(15)
530 << "M5 CC: " << "0x"<< setw(16) << setfill('0')
531 << hex << thread->getCpuPtr()->instCount() << endl;
532 outs << setfill(' ') << setw(15)
533 << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
534 << shared_data->cycle_count << endl << endl;
535
536 outs << setfill(' ') << setw(15)
537 << "M5 Inst: " << "0x"<< setw(8)
538 << setfill('0') << hex << staticInst->machInst
539 << staticInst->disassemble(m5Pc, debugSymbolTable)
540 << endl;
541
542 StaticInstPtr legionInst =
543 StaticInst::decode(makeExtMI(shared_data->instruction,
544 thread));
545 outs << setfill(' ') << setw(15)
546 << " Legion Inst: "
547 << "0x" << setw(8) << setfill('0') << hex
548 << shared_data->instruction
549 << legionInst->disassemble(lgnPc, debugSymbolTable)
550 << endl << endl;
551
552 printSectionHeader(outs, "General State");
553 printColumnLabels(outs);
554 printRegPair(outs, "HPstate",
555 thread->readMiscReg(MISCREG_HPSTATE),
556 shared_data->hpstate | (1 << 11));
557 printRegPair(outs, "Htba",
558 thread->readMiscReg(MISCREG_HTBA),
559 shared_data->htba);
560 printRegPair(outs, "Pstate",
561 thread->readMiscReg(MISCREG_PSTATE),
562 shared_data->pstate);
563 printRegPair(outs, "Y",
564 //thread->readMiscReg(MISCREG_Y),
565 thread->readIntReg(NumIntArchRegs + 1),
566 shared_data->y);
567 printRegPair(outs, "FSR",
568 thread->readMiscReg(MISCREG_FSR),
569 shared_data->fsr);
570 printRegPair(outs, "Ccr",
571 //thread->readMiscReg(MISCREG_CCR),
572 thread->readIntReg(NumIntArchRegs + 2),
573 shared_data->ccr);
574 printRegPair(outs, "Tl",
575 thread->readMiscReg(MISCREG_TL),
576 shared_data->tl);
577 printRegPair(outs, "Gl",
578 thread->readMiscReg(MISCREG_GL),
579 shared_data->gl);
580 printRegPair(outs, "Asi",
581 thread->readMiscReg(MISCREG_ASI),
582 shared_data->asi);
583 printRegPair(outs, "Pil",
584 thread->readMiscReg(MISCREG_PIL),
585 shared_data->pil);
586 printRegPair(outs, "Cwp",
587 thread->readMiscReg(MISCREG_CWP),
588 shared_data->cwp);
589 printRegPair(outs, "Cansave",
590 //thread->readMiscReg(MISCREG_CANSAVE),
591 thread->readIntReg(NumIntArchRegs + 3),
592 shared_data->cansave);
593 printRegPair(outs, "Canrestore",
594 //thread->readMiscReg(MISCREG_CANRESTORE),
595 thread->readIntReg(NumIntArchRegs + 4),
596 shared_data->canrestore);
597 printRegPair(outs, "Otherwin",
598 //thread->readMiscReg(MISCREG_OTHERWIN),
599 thread->readIntReg(NumIntArchRegs + 6),
600 shared_data->otherwin);
601 printRegPair(outs, "Cleanwin",
602 //thread->readMiscReg(MISCREG_CLEANWIN),
603 thread->readIntReg(NumIntArchRegs + 5),
604 shared_data->cleanwin);
605 outs << endl;
606 for (int i = 1; i <= MaxTL; i++) {
607 printLevelHeader(outs, i);
608 printColumnLabels(outs);
609 thread->setMiscReg(MISCREG_TL, i);
610 printRegPair(outs, "Tpc",
611 thread->readMiscReg(MISCREG_TPC),
612 shared_data->tpc[i-1]);
613 printRegPair(outs, "Tnpc",
614 thread->readMiscReg(MISCREG_TNPC),
615 shared_data->tnpc[i-1]);
616 printRegPair(outs, "Tstate",
617 thread->readMiscReg(MISCREG_TSTATE),
618 shared_data->tstate[i-1]);
619 printRegPair(outs, "Tt",
620 thread->readMiscReg(MISCREG_TT),
621 shared_data->tt[i-1]);
622 printRegPair(outs, "Htstate",
623 thread->readMiscReg(MISCREG_HTSTATE),
624 shared_data->htstate[i-1]);
625 }
626 thread->setMiscReg(MISCREG_TL, oldTl);
627 outs << endl;
628
629 printSectionHeader(outs, "General Purpose Registers");
630 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
631 for(int y = 0; y < 4; y++) {
632 for(int x = 0; x < 8; x++) {
633 char label[8];
634 sprintf(label, "%s%d", regtypes[y], x);
635 printRegPair(outs, label,
636 thread->readIntReg(y*8+x),
637 shared_data->intregs[y*8+x]);
638 }
639 }
640 if (diffFpRegs) {
641 for (int x = 0; x < 32; x++) {
642 char label[8];
643 sprintf(label, "%%f%d", x);
644 printRegPair(outs, label,
645 thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth),
646 shared_data->fpregs[x]);
647 }
648 }
649 if (diffTlb) {
650 printColumnLabels(outs);
651 char label[8];
652 for (int x = 0; x < 64; x++) {
653 if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
654 thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
655 sprintf(label, "I-TLB:%02d", x);
656 printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
657 shared_data->itb[x]);
658 }
659 }
660 for (int x = 0; x < 64; x++) {
661 if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
662 thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
663 sprintf(label, "D-TLB:%02d", x);
664 printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
665 shared_data->dtb[x]);
666 }
667 }
668 thread->getITBPtr()->dumpAll();
669 thread->getDTBPtr()->dumpAll();
670 }
671
672 diffcount++;
673 if (diffcount > 3)
674 fatal("Differences found between Legion and M5\n");
675 } else
676 diffcount = 0;
677
678 compared = true;
679 shared_data->flags = OWN_LEGION;
680 }
681 } // while
682 } // if not microop
683 }
684#endif
685}
686
687
688vector<bool> Trace::InstRecord::flags(NUM_BITS);
689string Trace::InstRecord::trace_system;
690
691////////////////////////////////////////////////////////////////////////
692//
693// Parameter space for per-cycle execution address tracing options.
694// Derive from ParamContext so we can override checkParams() function.
695//
696class ExecutionTraceParamContext : public ParamContext
697{
698 public:
699 ExecutionTraceParamContext(const string &_iniSection)
700 : ParamContext(_iniSection)
701 {
702 }
703
704 void checkParams(); // defined at bottom of file
705};
706
707ExecutionTraceParamContext exeTraceParams("exetrace");
708
709Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
710 "capture speculative instructions", true);
711
712Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
713 "print cycle number", true);
714Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
715 "print op class", true);
716Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
717 "print thread number", true);
718Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
719 "print effective address", true);
720Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
721 "print result data", true);
722Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
723 "print all integer regs", false);
724Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
725 "print fetch sequence number", false);
726Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
727 "print correct-path sequence number", false);
728Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
729 "print which registers changed to what", false);
730Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
731 "Use symbols for the PC if available", true);
732Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
733 "print trace in intel compatible format", false);
734Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
735 "Compare sim state to legion state every cycle",
736 false);
737Param<string> exe_trace_system(&exeTraceParams, "trace_system",
738 "print trace of which system (client or server)",
739 "client");
740
741
742//
743// Helper function for ExecutionTraceParamContext::checkParams() just
744// to get us into the InstRecord namespace
745//
746void
747Trace::InstRecord::setParams()
748{
749 flags[TRACE_MISSPEC] = exe_trace_spec;
750
330 while (!compared)
331 if (shared_data->flags == OWN_M5) {
332 shared_data->flags = OWN_LEGION;
333 compared = true;
334 }
335 compared = false;
336 wasMicro = false;
337 }
338
339 if (staticInst->isLastMicroOp())
340 wasMicro = false;
341 else if (staticInst->isMicroOp())
342 wasMicro = true;
343
344
345 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
346 while (!compared) {
347 if (shared_data->flags == OWN_M5) {
348 m5Pc = PC & TheISA::PAddrImplMask;
349 if (bits(shared_data->pstate,3,3)) {
350 m5Pc &= mask(32);
351 }
352 lgnPc = shared_data->pc & TheISA::PAddrImplMask;
353 if (lgnPc != m5Pc)
354 diffPC = true;
355
356 if (shared_data->cycle_count !=
357 thread->getCpuPtr()->instCount())
358 diffCC = true;
359
360 if (shared_data->instruction !=
361 (SparcISA::MachInst)staticInst->machInst) {
362 diffInst = true;
363 }
364 // assume we have %g0 working correctly
365 for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
366 if (thread->readIntReg(i) != shared_data->intregs[i]) {
367 diffIntRegs = true;
368 }
369 }
370 for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
371 if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
372 diffFpRegs = true;
373 }
374 }
375 uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
376 if (oldTl != shared_data->tl)
377 diffTl = true;
378 for (int i = 1; i <= MaxTL; i++) {
379 thread->setMiscReg(MISCREG_TL, i);
380 if (thread->readMiscReg(MISCREG_TPC) !=
381 shared_data->tpc[i-1])
382 diffTpc = true;
383 if (thread->readMiscReg(MISCREG_TNPC) !=
384 shared_data->tnpc[i-1])
385 diffTnpc = true;
386 if (thread->readMiscReg(MISCREG_TSTATE) !=
387 shared_data->tstate[i-1])
388 diffTstate = true;
389 if (thread->readMiscReg(MISCREG_TT) !=
390 shared_data->tt[i-1])
391 diffTt = true;
392 if (thread->readMiscReg(MISCREG_HTSTATE) !=
393 shared_data->htstate[i-1])
394 diffHtstate = true;
395 }
396 thread->setMiscReg(MISCREG_TL, oldTl);
397
398 if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
399 diffTba = true;
400 //When the hpstate register is read by an instruction,
401 //legion has bit 11 set. When it's in storage, it doesn't.
402 //Since we don't directly support seperate interpretations
403 //of the registers like that, the bit is always set to 1 and
404 //we just don't compare it. It's not supposed to matter
405 //anyway.
406 if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
407 diffHpstate = true;
408 if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
409 diffHtba = true;
410 if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
411 diffPstate = true;
412 //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
413 if(shared_data->y !=
414 thread->readIntReg(NumIntArchRegs + 1))
415 diffY = true;
416 if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) {
417 diffFsr = true;
418 if (mbits(shared_data->fsr, 63,10) ==
419 mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) {
420 thread->setMiscReg(MISCREG_FSR, shared_data->fsr);
421 diffFsr = false;
422 }
423 }
424 //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
425 if(shared_data->ccr !=
426 thread->readIntReg(NumIntArchRegs + 2))
427 diffCcr = true;
428 if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
429 diffGl = true;
430 if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
431 diffAsi = true;
432 if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
433 diffPil = true;
434 if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
435 diffCwp = true;
436 //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
437 if(shared_data->cansave !=
438 thread->readIntReg(NumIntArchRegs + 3))
439 diffCansave = true;
440 //if(shared_data->canrestore !=
441 // thread->readMiscReg(MISCREG_CANRESTORE))
442 if(shared_data->canrestore !=
443 thread->readIntReg(NumIntArchRegs + 4))
444 diffCanrestore = true;
445 //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
446 if(shared_data->otherwin !=
447 thread->readIntReg(NumIntArchRegs + 6))
448 diffOtherwin = true;
449 //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
450 if(shared_data->cleanwin !=
451 thread->readIntReg(NumIntArchRegs + 5))
452 diffCleanwin = true;
453
454 for (int i = 0; i < 64; i++) {
455 if (shared_data->itb[i] != thread->getITBPtr()->TteRead(i))
456 diffTlb = true;
457 if (shared_data->dtb[i] != thread->getDTBPtr()->TteRead(i))
458 diffTlb = true;
459 }
460
461 if (diffPC || diffCC || diffInst || diffIntRegs ||
462 diffFpRegs || diffTpc || diffTnpc || diffTstate ||
463 diffTt || diffHpstate || diffHtstate || diffHtba ||
464 diffPstate || diffY || diffCcr || diffTl || diffFsr ||
465 diffGl || diffAsi || diffPil || diffCwp || diffCansave ||
466 diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
467 {
468
469 outs << "Differences found between M5 and Legion:";
470 if (diffPC)
471 outs << " [PC]";
472 if (diffCC)
473 outs << " [CC]";
474 if (diffInst)
475 outs << " [Instruction]";
476 if (diffIntRegs)
477 outs << " [IntRegs]";
478 if (diffFpRegs)
479 outs << " [FpRegs]";
480 if (diffTpc)
481 outs << " [Tpc]";
482 if (diffTnpc)
483 outs << " [Tnpc]";
484 if (diffTstate)
485 outs << " [Tstate]";
486 if (diffTt)
487 outs << " [Tt]";
488 if (diffHpstate)
489 outs << " [Hpstate]";
490 if (diffHtstate)
491 outs << " [Htstate]";
492 if (diffHtba)
493 outs << " [Htba]";
494 if (diffPstate)
495 outs << " [Pstate]";
496 if (diffY)
497 outs << " [Y]";
498 if (diffFsr)
499 outs << " [FSR]";
500 if (diffCcr)
501 outs << " [Ccr]";
502 if (diffTl)
503 outs << " [Tl]";
504 if (diffGl)
505 outs << " [Gl]";
506 if (diffAsi)
507 outs << " [Asi]";
508 if (diffPil)
509 outs << " [Pil]";
510 if (diffCwp)
511 outs << " [Cwp]";
512 if (diffCansave)
513 outs << " [Cansave]";
514 if (diffCanrestore)
515 outs << " [Canrestore]";
516 if (diffOtherwin)
517 outs << " [Otherwin]";
518 if (diffCleanwin)
519 outs << " [Cleanwin]";
520 if (diffTlb)
521 outs << " [Tlb]";
522 outs << endl << endl;
523
524 outs << right << setfill(' ') << setw(15)
525 << "M5 PC: " << "0x"<< setw(16) << setfill('0')
526 << hex << m5Pc << endl;
527 outs << setfill(' ') << setw(15)
528 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
529 << lgnPc << endl << endl;
530
531 outs << right << setfill(' ') << setw(15)
532 << "M5 CC: " << "0x"<< setw(16) << setfill('0')
533 << hex << thread->getCpuPtr()->instCount() << endl;
534 outs << setfill(' ') << setw(15)
535 << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
536 << shared_data->cycle_count << endl << endl;
537
538 outs << setfill(' ') << setw(15)
539 << "M5 Inst: " << "0x"<< setw(8)
540 << setfill('0') << hex << staticInst->machInst
541 << staticInst->disassemble(m5Pc, debugSymbolTable)
542 << endl;
543
544 StaticInstPtr legionInst =
545 StaticInst::decode(makeExtMI(shared_data->instruction,
546 thread));
547 outs << setfill(' ') << setw(15)
548 << " Legion Inst: "
549 << "0x" << setw(8) << setfill('0') << hex
550 << shared_data->instruction
551 << legionInst->disassemble(lgnPc, debugSymbolTable)
552 << endl << endl;
553
554 printSectionHeader(outs, "General State");
555 printColumnLabels(outs);
556 printRegPair(outs, "HPstate",
557 thread->readMiscReg(MISCREG_HPSTATE),
558 shared_data->hpstate | (1 << 11));
559 printRegPair(outs, "Htba",
560 thread->readMiscReg(MISCREG_HTBA),
561 shared_data->htba);
562 printRegPair(outs, "Pstate",
563 thread->readMiscReg(MISCREG_PSTATE),
564 shared_data->pstate);
565 printRegPair(outs, "Y",
566 //thread->readMiscReg(MISCREG_Y),
567 thread->readIntReg(NumIntArchRegs + 1),
568 shared_data->y);
569 printRegPair(outs, "FSR",
570 thread->readMiscReg(MISCREG_FSR),
571 shared_data->fsr);
572 printRegPair(outs, "Ccr",
573 //thread->readMiscReg(MISCREG_CCR),
574 thread->readIntReg(NumIntArchRegs + 2),
575 shared_data->ccr);
576 printRegPair(outs, "Tl",
577 thread->readMiscReg(MISCREG_TL),
578 shared_data->tl);
579 printRegPair(outs, "Gl",
580 thread->readMiscReg(MISCREG_GL),
581 shared_data->gl);
582 printRegPair(outs, "Asi",
583 thread->readMiscReg(MISCREG_ASI),
584 shared_data->asi);
585 printRegPair(outs, "Pil",
586 thread->readMiscReg(MISCREG_PIL),
587 shared_data->pil);
588 printRegPair(outs, "Cwp",
589 thread->readMiscReg(MISCREG_CWP),
590 shared_data->cwp);
591 printRegPair(outs, "Cansave",
592 //thread->readMiscReg(MISCREG_CANSAVE),
593 thread->readIntReg(NumIntArchRegs + 3),
594 shared_data->cansave);
595 printRegPair(outs, "Canrestore",
596 //thread->readMiscReg(MISCREG_CANRESTORE),
597 thread->readIntReg(NumIntArchRegs + 4),
598 shared_data->canrestore);
599 printRegPair(outs, "Otherwin",
600 //thread->readMiscReg(MISCREG_OTHERWIN),
601 thread->readIntReg(NumIntArchRegs + 6),
602 shared_data->otherwin);
603 printRegPair(outs, "Cleanwin",
604 //thread->readMiscReg(MISCREG_CLEANWIN),
605 thread->readIntReg(NumIntArchRegs + 5),
606 shared_data->cleanwin);
607 outs << endl;
608 for (int i = 1; i <= MaxTL; i++) {
609 printLevelHeader(outs, i);
610 printColumnLabels(outs);
611 thread->setMiscReg(MISCREG_TL, i);
612 printRegPair(outs, "Tpc",
613 thread->readMiscReg(MISCREG_TPC),
614 shared_data->tpc[i-1]);
615 printRegPair(outs, "Tnpc",
616 thread->readMiscReg(MISCREG_TNPC),
617 shared_data->tnpc[i-1]);
618 printRegPair(outs, "Tstate",
619 thread->readMiscReg(MISCREG_TSTATE),
620 shared_data->tstate[i-1]);
621 printRegPair(outs, "Tt",
622 thread->readMiscReg(MISCREG_TT),
623 shared_data->tt[i-1]);
624 printRegPair(outs, "Htstate",
625 thread->readMiscReg(MISCREG_HTSTATE),
626 shared_data->htstate[i-1]);
627 }
628 thread->setMiscReg(MISCREG_TL, oldTl);
629 outs << endl;
630
631 printSectionHeader(outs, "General Purpose Registers");
632 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
633 for(int y = 0; y < 4; y++) {
634 for(int x = 0; x < 8; x++) {
635 char label[8];
636 sprintf(label, "%s%d", regtypes[y], x);
637 printRegPair(outs, label,
638 thread->readIntReg(y*8+x),
639 shared_data->intregs[y*8+x]);
640 }
641 }
642 if (diffFpRegs) {
643 for (int x = 0; x < 32; x++) {
644 char label[8];
645 sprintf(label, "%%f%d", x);
646 printRegPair(outs, label,
647 thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth),
648 shared_data->fpregs[x]);
649 }
650 }
651 if (diffTlb) {
652 printColumnLabels(outs);
653 char label[8];
654 for (int x = 0; x < 64; x++) {
655 if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
656 thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
657 sprintf(label, "I-TLB:%02d", x);
658 printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
659 shared_data->itb[x]);
660 }
661 }
662 for (int x = 0; x < 64; x++) {
663 if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
664 thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
665 sprintf(label, "D-TLB:%02d", x);
666 printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
667 shared_data->dtb[x]);
668 }
669 }
670 thread->getITBPtr()->dumpAll();
671 thread->getDTBPtr()->dumpAll();
672 }
673
674 diffcount++;
675 if (diffcount > 3)
676 fatal("Differences found between Legion and M5\n");
677 } else
678 diffcount = 0;
679
680 compared = true;
681 shared_data->flags = OWN_LEGION;
682 }
683 } // while
684 } // if not microop
685 }
686#endif
687}
688
689
690vector<bool> Trace::InstRecord::flags(NUM_BITS);
691string Trace::InstRecord::trace_system;
692
693////////////////////////////////////////////////////////////////////////
694//
695// Parameter space for per-cycle execution address tracing options.
696// Derive from ParamContext so we can override checkParams() function.
697//
698class ExecutionTraceParamContext : public ParamContext
699{
700 public:
701 ExecutionTraceParamContext(const string &_iniSection)
702 : ParamContext(_iniSection)
703 {
704 }
705
706 void checkParams(); // defined at bottom of file
707};
708
709ExecutionTraceParamContext exeTraceParams("exetrace");
710
711Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
712 "capture speculative instructions", true);
713
714Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
715 "print cycle number", true);
716Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
717 "print op class", true);
718Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
719 "print thread number", true);
720Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
721 "print effective address", true);
722Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
723 "print result data", true);
724Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
725 "print all integer regs", false);
726Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
727 "print fetch sequence number", false);
728Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
729 "print correct-path sequence number", false);
730Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
731 "print which registers changed to what", false);
732Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
733 "Use symbols for the PC if available", true);
734Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
735 "print trace in intel compatible format", false);
736Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
737 "Compare sim state to legion state every cycle",
738 false);
739Param<string> exe_trace_system(&exeTraceParams, "trace_system",
740 "print trace of which system (client or server)",
741 "client");
742
743
744//
745// Helper function for ExecutionTraceParamContext::checkParams() just
746// to get us into the InstRecord namespace
747//
748void
749Trace::InstRecord::setParams()
750{
751 flags[TRACE_MISSPEC] = exe_trace_spec;
752
751 flags[PRINT_CYCLE] = exe_trace_print_cycle;
753 flags[PRINT_TICKS] = exe_trace_print_cycle;
752 flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
753 flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
754 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
755 flags[PRINT_EFF_ADDR] = exe_trace_print_data;
756 flags[PRINT_INT_REGS] = exe_trace_print_iregs;
757 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
758 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
759 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
760 flags[PC_SYMBOL] = exe_trace_pc_symbol;
761 flags[INTEL_FORMAT] = exe_trace_intel_format;
762 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
763 trace_system = exe_trace_system;
764
765 // If were going to be in lockstep with Legion
766 // Setup shared memory, and get otherwise ready
767 if (flags[LEGION_LOCKSTEP]) {
768 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
769 if (shmfd < 0)
770 fatal("Couldn't get shared memory fd. Is Legion running?");
771
772 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
773 if (shared_data == (SharedData*)-1)
774 fatal("Couldn't allocate shared memory");
775
776 if (shared_data->flags != OWN_M5)
777 fatal("Shared memory has invalid owner");
778
779 if (shared_data->version != VERSION)
780 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
781 shared_data->version);
782
783 // step legion forward one cycle so we can get register values
784 shared_data->flags = OWN_LEGION;
785 }
786}
787
788void
789ExecutionTraceParamContext::checkParams()
790{
791 Trace::InstRecord::setParams();
792}
793
754 flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
755 flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
756 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
757 flags[PRINT_EFF_ADDR] = exe_trace_print_data;
758 flags[PRINT_INT_REGS] = exe_trace_print_iregs;
759 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
760 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
761 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
762 flags[PC_SYMBOL] = exe_trace_pc_symbol;
763 flags[INTEL_FORMAT] = exe_trace_intel_format;
764 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
765 trace_system = exe_trace_system;
766
767 // If were going to be in lockstep with Legion
768 // Setup shared memory, and get otherwise ready
769 if (flags[LEGION_LOCKSTEP]) {
770 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
771 if (shmfd < 0)
772 fatal("Couldn't get shared memory fd. Is Legion running?");
773
774 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
775 if (shared_data == (SharedData*)-1)
776 fatal("Couldn't allocate shared memory");
777
778 if (shared_data->flags != OWN_M5)
779 fatal("Shared memory has invalid owner");
780
781 if (shared_data->version != VERSION)
782 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
783 shared_data->version);
784
785 // step legion forward one cycle so we can get register values
786 shared_data->flags = OWN_LEGION;
787 }
788}
789
790void
791ExecutionTraceParamContext::checkParams()
792{
793 Trace::InstRecord::setParams();
794}
795