exetrace.cc (3743:2061715f68d1) exetrace.cc (3748:35d3c2e37b58)
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
60namespace Trace {
61SharedData *shared_data = NULL;
62}
63
64////////////////////////////////////////////////////////////////////////
65//
66// Methods for the InstRecord object
67//
68
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
60namespace Trace {
61SharedData *shared_data = NULL;
62}
63
64////////////////////////////////////////////////////////////////////////
65//
66// Methods for the InstRecord object
67//
68
69#if THE_ISA == SPARC_ISA
69
70
71inline char * genCenteredLabel(int length, char * buffer, char * label)
72{
73 int labelLength = strlen(label);
74 assert(labelLength <= length);
75 int leftPad = (length - labelLength) / 2;
76 int rightPad = length - leftPad - labelLength;
77 char format[64];
78 sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
79 sprintf(buffer, format, "", label, "");
80 return buffer;
81}
82
83inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
84{
85 ccprintf(os, " %16s | %#018x %s %#-018x \n",
86 title, a, (a == b) ? "|" : "X", b);
87}
88
89inline void printColumnLabels(ostream & os)
90{
91 static char * regLabel = genCenteredLabel(16, new char[17], "Register");
92 static char * m5Label = genCenteredLabel(18, new char[18], "M5");
93 static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
94 ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel);
95 ccprintf(os, "--------------------+-----------------------+-----------------------\n");
96}
97
98inline void printSectionHeader(ostream & os, char * name)
99{
100 char sectionString[70];
101 genCenteredLabel(69, sectionString, name);
102 ccprintf(os, "====================================================================\n");
103 ccprintf(os, "%69s\n", sectionString);
104 ccprintf(os, "====================================================================\n");
105}
106
107inline void printLevelHeader(ostream & os, int level)
108{
109 char sectionString[70];
110 char levelName[70];
111 sprintf(levelName, "Trap stack level %d", level);
112 genCenteredLabel(69, sectionString, levelName);
113 ccprintf(os, "====================================================================\n");
114 ccprintf(os, "%69s\n", sectionString);
115 ccprintf(os, "====================================================================\n");
116}
117
118#endif
119
70void
71Trace::InstRecord::dump(ostream &outs)
72{
73 if (flags[PRINT_REG_DELTA])
74 {
75#if THE_ISA == SPARC_ISA
76 //Don't print what happens for each micro-op, just print out
77 //once at the last op, and for regular instructions.
78 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
79 {
80 static uint64_t regs[32] = {
81 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0};
85 static uint64_t ccr = 0;
86 static uint64_t y = 0;
87 static uint64_t floats[32];
88 uint64_t newVal;
89 static const char * prefixes[4] = {"G", "O", "L", "I"};
90
91 outs << hex;
92 outs << "PC = " << thread->readNextPC();
93 outs << " NPC = " << thread->readNextNPC();
94 newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
95 if(newVal != ccr)
96 {
97 outs << " CCR = " << newVal;
98 ccr = newVal;
99 }
100 newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
101 if(newVal != y)
102 {
103 outs << " Y = " << newVal;
104 y = newVal;
105 }
106 for(int y = 0; y < 4; y++)
107 {
108 for(int x = 0; x < 8; x++)
109 {
110 int index = x + 8 * y;
111 newVal = thread->readIntReg(index);
112 if(regs[index] != newVal)
113 {
114 outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
115 regs[index] = newVal;
116 }
117 }
118 }
119 for(int y = 0; y < 32; y++)
120 {
121 newVal = thread->readFloatRegBits(2 * y, 64);
122 if(floats[y] != newVal)
123 {
124 outs << " F" << dec << (2 * y) << " = " << hex << newVal;
125 floats[y] = newVal;
126 }
127 }
128 outs << dec << endl;
129 }
130#endif
131 }
132 else if (flags[INTEL_FORMAT]) {
133#if FULL_SYSTEM
134 bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
135#else
136 bool is_trace_system = true;
137#endif
138 if (is_trace_system) {
139 ccprintf(outs, "%7d ) ", cycle);
140 outs << "0x" << hex << PC << ":\t";
141 if (staticInst->isLoad()) {
142 outs << "<RD 0x" << hex << addr;
143 outs << ">";
144 } else if (staticInst->isStore()) {
145 outs << "<WR 0x" << hex << addr;
146 outs << ">";
147 }
148 outs << endl;
149 }
150 } else {
151 if (flags[PRINT_CYCLE])
152 ccprintf(outs, "%7d: ", cycle);
153
154 outs << thread->getCpuPtr()->name() << " ";
155
156 if (flags[TRACE_MISSPEC])
157 outs << (misspeculating ? "-" : "+") << " ";
158
159 if (flags[PRINT_THREAD_NUM])
160 outs << "T" << thread->getThreadNum() << " : ";
161
162
163 std::string sym_str;
164 Addr sym_addr;
165 if (debugSymbolTable
166 && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
167 && flags[PC_SYMBOL]) {
168 if (PC != sym_addr)
169 sym_str += csprintf("+%d", PC - sym_addr);
170 outs << "@" << sym_str << " : ";
171 }
172 else {
173 outs << "0x" << hex << PC << " : ";
174 }
175
176 //
177 // Print decoded instruction
178 //
179
180#if defined(__GNUC__) && (__GNUC__ < 3)
181 // There's a bug in gcc 2.x library that prevents setw()
182 // from working properly on strings
183 string mc(staticInst->disassemble(PC, debugSymbolTable));
184 while (mc.length() < 26)
185 mc += " ";
186 outs << mc;
187#else
188 outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
189#endif
190
191 outs << " : ";
192
193 if (flags[PRINT_OP_CLASS]) {
194 outs << opClassStrings[staticInst->opClass()] << " : ";
195 }
196
197 if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
198 outs << " D=";
199#if 0
200 if (data_status == DataDouble)
201 ccprintf(outs, "%f", data.as_double);
202 else
203 ccprintf(outs, "%#018x", data.as_int);
204#else
205 ccprintf(outs, "%#018x", data.as_int);
206#endif
207 }
208
209 if (flags[PRINT_EFF_ADDR] && addr_valid)
210 outs << " A=0x" << hex << addr;
211
212 if (flags[PRINT_INT_REGS] && regs_valid) {
213 for (int i = 0; i < TheISA::NumIntRegs;)
214 for (int j = i + 1; i <= j; i++)
215 ccprintf(outs, "r%02d = %#018x%s", i,
216 iregs->regs.readReg(i),
217 ((i == j) ? "\n" : " "));
218 outs << "\n";
219 }
220
221 if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
222 outs << " FetchSeq=" << dec << fetch_seq;
223
224 if (flags[PRINT_CP_SEQ] && cp_seq_valid)
225 outs << " CPSeq=" << dec << cp_seq;
226
227 //
228 // End of line...
229 //
230 outs << endl;
231 }
232#if THE_ISA == SPARC_ISA
233 // Compare
234 if (flags[LEGION_LOCKSTEP])
235 {
236 bool compared = false;
237 bool diffPC = false;
238 bool diffInst = false;
239 bool diffRegs = false;
120void
121Trace::InstRecord::dump(ostream &outs)
122{
123 if (flags[PRINT_REG_DELTA])
124 {
125#if THE_ISA == SPARC_ISA
126 //Don't print what happens for each micro-op, just print out
127 //once at the last op, and for regular instructions.
128 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
129 {
130 static uint64_t regs[32] = {
131 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0};
135 static uint64_t ccr = 0;
136 static uint64_t y = 0;
137 static uint64_t floats[32];
138 uint64_t newVal;
139 static const char * prefixes[4] = {"G", "O", "L", "I"};
140
141 outs << hex;
142 outs << "PC = " << thread->readNextPC();
143 outs << " NPC = " << thread->readNextNPC();
144 newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
145 if(newVal != ccr)
146 {
147 outs << " CCR = " << newVal;
148 ccr = newVal;
149 }
150 newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
151 if(newVal != y)
152 {
153 outs << " Y = " << newVal;
154 y = newVal;
155 }
156 for(int y = 0; y < 4; y++)
157 {
158 for(int x = 0; x < 8; x++)
159 {
160 int index = x + 8 * y;
161 newVal = thread->readIntReg(index);
162 if(regs[index] != newVal)
163 {
164 outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
165 regs[index] = newVal;
166 }
167 }
168 }
169 for(int y = 0; y < 32; y++)
170 {
171 newVal = thread->readFloatRegBits(2 * y, 64);
172 if(floats[y] != newVal)
173 {
174 outs << " F" << dec << (2 * y) << " = " << hex << newVal;
175 floats[y] = newVal;
176 }
177 }
178 outs << dec << endl;
179 }
180#endif
181 }
182 else if (flags[INTEL_FORMAT]) {
183#if FULL_SYSTEM
184 bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
185#else
186 bool is_trace_system = true;
187#endif
188 if (is_trace_system) {
189 ccprintf(outs, "%7d ) ", cycle);
190 outs << "0x" << hex << PC << ":\t";
191 if (staticInst->isLoad()) {
192 outs << "<RD 0x" << hex << addr;
193 outs << ">";
194 } else if (staticInst->isStore()) {
195 outs << "<WR 0x" << hex << addr;
196 outs << ">";
197 }
198 outs << endl;
199 }
200 } else {
201 if (flags[PRINT_CYCLE])
202 ccprintf(outs, "%7d: ", cycle);
203
204 outs << thread->getCpuPtr()->name() << " ";
205
206 if (flags[TRACE_MISSPEC])
207 outs << (misspeculating ? "-" : "+") << " ";
208
209 if (flags[PRINT_THREAD_NUM])
210 outs << "T" << thread->getThreadNum() << " : ";
211
212
213 std::string sym_str;
214 Addr sym_addr;
215 if (debugSymbolTable
216 && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
217 && flags[PC_SYMBOL]) {
218 if (PC != sym_addr)
219 sym_str += csprintf("+%d", PC - sym_addr);
220 outs << "@" << sym_str << " : ";
221 }
222 else {
223 outs << "0x" << hex << PC << " : ";
224 }
225
226 //
227 // Print decoded instruction
228 //
229
230#if defined(__GNUC__) && (__GNUC__ < 3)
231 // There's a bug in gcc 2.x library that prevents setw()
232 // from working properly on strings
233 string mc(staticInst->disassemble(PC, debugSymbolTable));
234 while (mc.length() < 26)
235 mc += " ";
236 outs << mc;
237#else
238 outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
239#endif
240
241 outs << " : ";
242
243 if (flags[PRINT_OP_CLASS]) {
244 outs << opClassStrings[staticInst->opClass()] << " : ";
245 }
246
247 if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
248 outs << " D=";
249#if 0
250 if (data_status == DataDouble)
251 ccprintf(outs, "%f", data.as_double);
252 else
253 ccprintf(outs, "%#018x", data.as_int);
254#else
255 ccprintf(outs, "%#018x", data.as_int);
256#endif
257 }
258
259 if (flags[PRINT_EFF_ADDR] && addr_valid)
260 outs << " A=0x" << hex << addr;
261
262 if (flags[PRINT_INT_REGS] && regs_valid) {
263 for (int i = 0; i < TheISA::NumIntRegs;)
264 for (int j = i + 1; i <= j; i++)
265 ccprintf(outs, "r%02d = %#018x%s", i,
266 iregs->regs.readReg(i),
267 ((i == j) ? "\n" : " "));
268 outs << "\n";
269 }
270
271 if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
272 outs << " FetchSeq=" << dec << fetch_seq;
273
274 if (flags[PRINT_CP_SEQ] && cp_seq_valid)
275 outs << " CPSeq=" << dec << cp_seq;
276
277 //
278 // End of line...
279 //
280 outs << endl;
281 }
282#if THE_ISA == SPARC_ISA
283 // Compare
284 if (flags[LEGION_LOCKSTEP])
285 {
286 bool compared = false;
287 bool diffPC = false;
288 bool diffInst = false;
289 bool diffRegs = false;
290 bool diffTpc = false;
291 bool diffTnpc = false;
292 bool diffTstate = false;
293 bool diffTt = false;
294 bool diffTba = false;
295 bool diffHpstate = false;
296 bool diffHtstate = false;
297 bool diffHtba = false;
298 bool diffPstate = false;
299 bool diffY = false;
300 bool diffCcr = false;
301 bool diffTl = false;
302 bool diffGl = false;
303 bool diffAsi = false;
304 bool diffPil = false;
305 bool diffCwp = false;
306 bool diffCansave = false;
307 bool diffCanrestore = false;
308 bool diffOtherwin = false;
309 bool diffCleanwin = false;
240 Addr m5Pc, lgnPc;
241
242
243 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
244 while (!compared) {
310 Addr m5Pc, lgnPc;
311
312
313 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
314 while (!compared) {
245 m5Pc = PC & TheISA::PAddrImplMask;
246 lgnPc = shared_data->pc & TheISA::PAddrImplMask;
247 if (shared_data->flags == OWN_M5) {
315 if (shared_data->flags == OWN_M5) {
316 m5Pc = PC & TheISA::PAddrImplMask;
317 lgnPc = shared_data->pc & TheISA::PAddrImplMask;
248 if (lgnPc != m5Pc)
249 diffPC = true;
250 if (shared_data->instruction !=
251 (SparcISA::MachInst)staticInst->machInst) {
252 diffInst = true;
253 }
254 for (int i = 0; i < TheISA::NumRegularIntRegs; i++) {
255 if (thread->readIntReg(i) != shared_data->intregs[i]) {
256 diffRegs = true;
257 }
258 }
318 if (lgnPc != m5Pc)
319 diffPC = true;
320 if (shared_data->instruction !=
321 (SparcISA::MachInst)staticInst->machInst) {
322 diffInst = true;
323 }
324 for (int i = 0; i < TheISA::NumRegularIntRegs; i++) {
325 if (thread->readIntReg(i) != shared_data->intregs[i]) {
326 diffRegs = true;
327 }
328 }
329 uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
330 if (oldTl != shared_data->tl)
331 diffTl = true;
332 for (int i = 1; i <= MaxTL; i++) {
333 thread->setMiscReg(MISCREG_TL, i);
334 if (thread->readMiscReg(MISCREG_TPC) !=
335 shared_data->tpc[i])
336 diffTpc = true;
337 if (thread->readMiscReg(MISCREG_TNPC) !=
338 shared_data->tnpc[i])
339 diffTnpc = true;
340 if (thread->readMiscReg(MISCREG_TSTATE) !=
341 shared_data->tstate[i])
342 diffTstate = true;
343 if (thread->readMiscReg(MISCREG_TT) !=
344 shared_data->tt[i])
345 diffTt = true;
346 if (thread->readMiscReg(MISCREG_HTSTATE) !=
347 shared_data->htstate[i])
348 diffHtstate = true;
349 }
350 thread->setMiscReg(MISCREG_TL, oldTl);
259
351
260 if (diffPC || diffInst || diffRegs ) {
352 if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
353 diffTba = true;
354 //When the hpstate register is read by an instruction,
355 //legion has bit 11 set. When it's in storage, it doesn't.
356 //Since we don't directly support seperate interpretations
357 //of the registers like that, the bit is always set to 1 and
358 //we just don't compare it. It's not supposed to matter
359 //anyway.
360 if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
361 diffHpstate = true;
362 if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
363 diffHtba = true;
364 if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
365 diffPstate = true;
366 if(shared_data->y != thread->readMiscReg(MISCREG_Y))
367 diffY = true;
368 if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
369 diffCcr = true;
370 if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
371 diffGl = true;
372 if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
373 diffAsi = true;
374 if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
375 diffPil = true;
376 if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
377 diffCwp = true;
378 if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
379 diffCansave = true;
380 if(shared_data->canrestore !=
381 thread->readMiscReg(MISCREG_CANRESTORE))
382 diffCanrestore = true;
383 if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
384 diffOtherwin = true;
385 if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
386 diffCleanwin = true;
387
388 if (diffPC || diffInst || diffRegs || diffTpc || diffTnpc ||
389 diffTstate || diffTt || diffHpstate ||
390 diffHtstate || diffHtba || diffPstate || diffY ||
391 diffCcr || diffTl || diffGl || diffAsi || diffPil ||
392 diffCwp || diffCansave || diffCanrestore ||
393 diffOtherwin || diffCleanwin) {
261 outs << "Differences found between M5 and Legion:";
262 if (diffPC)
263 outs << " [PC]";
264 if (diffInst)
265 outs << " [Instruction]";
266 if (diffRegs)
267 outs << " [IntRegs]";
394 outs << "Differences found between M5 and Legion:";
395 if (diffPC)
396 outs << " [PC]";
397 if (diffInst)
398 outs << " [Instruction]";
399 if (diffRegs)
400 outs << " [IntRegs]";
401 if (diffTpc)
402 outs << " [Tpc]";
403 if (diffTnpc)
404 outs << " [Tnpc]";
405 if (diffTstate)
406 outs << " [Tstate]";
407 if (diffTt)
408 outs << " [Tt]";
409 if (diffHpstate)
410 outs << " [Hpstate]";
411 if (diffHtstate)
412 outs << " [Htstate]";
413 if (diffHtba)
414 outs << " [Htba]";
415 if (diffPstate)
416 outs << " [Pstate]";
417 if (diffY)
418 outs << " [Y]";
419 if (diffCcr)
420 outs << " [Ccr]";
421 if (diffTl)
422 outs << " [Tl]";
423 if (diffGl)
424 outs << " [Gl]";
425 if (diffAsi)
426 outs << " [Asi]";
427 if (diffPil)
428 outs << " [Pil]";
429 if (diffCwp)
430 outs << " [Cwp]";
431 if (diffCansave)
432 outs << " [Cansave]";
433 if (diffCanrestore)
434 outs << " [Canrestore]";
435 if (diffOtherwin)
436 outs << " [Otherwin]";
437 if (diffCleanwin)
438 outs << " [Cleanwin]";
268 outs << endl << endl;
269
270 outs << right << setfill(' ') << setw(15)
271 << "M5 PC: " << "0x"<< setw(16) << setfill('0')
272 << hex << m5Pc << endl;
273 outs << setfill(' ') << setw(15)
274 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
275 << lgnPc << endl << endl;
276
277 outs << setfill(' ') << setw(15)
278 << "M5 Inst: " << "0x"<< setw(8)
279 << setfill('0') << hex << staticInst->machInst
280 << staticInst->disassemble(m5Pc, debugSymbolTable)
281 << endl;
282
439 outs << endl << endl;
440
441 outs << right << setfill(' ') << setw(15)
442 << "M5 PC: " << "0x"<< setw(16) << setfill('0')
443 << hex << m5Pc << endl;
444 outs << setfill(' ') << setw(15)
445 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
446 << lgnPc << endl << endl;
447
448 outs << setfill(' ') << setw(15)
449 << "M5 Inst: " << "0x"<< setw(8)
450 << setfill('0') << hex << staticInst->machInst
451 << staticInst->disassemble(m5Pc, debugSymbolTable)
452 << endl;
453
283 StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread));
454 StaticInstPtr legionInst =
455 StaticInst::decode(makeExtMI(shared_data->instruction,
456 thread));
284 outs << setfill(' ') << setw(15)
285 << " Legion Inst: "
286 << "0x" << setw(8) << setfill('0') << hex
287 << shared_data->instruction
288 << legionInst->disassemble(lgnPc, debugSymbolTable)
457 outs << setfill(' ') << setw(15)
458 << " Legion Inst: "
459 << "0x" << setw(8) << setfill('0') << hex
460 << shared_data->instruction
461 << legionInst->disassemble(lgnPc, debugSymbolTable)
289 << endl;
462 << endl << endl;
290
463
464 printSectionHeader(outs, "General State");
465 printColumnLabels(outs);
466 printRegPair(outs, "HPstate",
467 thread->readMiscReg(MISCREG_HPSTATE),
468 shared_data->hpstate | (1 << 11));
469 printRegPair(outs, "Htba",
470 thread->readMiscReg(MISCREG_HTBA),
471 shared_data->htba);
472 printRegPair(outs, "Pstate",
473 thread->readMiscReg(MISCREG_PSTATE),
474 shared_data->pstate);
475 printRegPair(outs, "Y",
476 thread->readMiscReg(MISCREG_Y),
477 shared_data->y);
478 printRegPair(outs, "Ccr",
479 thread->readMiscReg(MISCREG_CCR),
480 shared_data->ccr);
481 printRegPair(outs, "Tl",
482 thread->readMiscReg(MISCREG_TL),
483 shared_data->tl);
484 printRegPair(outs, "Gl",
485 thread->readMiscReg(MISCREG_GL),
486 shared_data->gl);
487 printRegPair(outs, "Asi",
488 thread->readMiscReg(MISCREG_ASI),
489 shared_data->asi);
490 printRegPair(outs, "Pil",
491 thread->readMiscReg(MISCREG_PIL),
492 shared_data->pil);
493 printRegPair(outs, "Cwp",
494 thread->readMiscReg(MISCREG_CWP),
495 shared_data->cwp);
496 printRegPair(outs, "Cansave",
497 thread->readMiscReg(MISCREG_CANSAVE),
498 shared_data->cansave);
499 printRegPair(outs, "Canrestore",
500 thread->readMiscReg(MISCREG_CANRESTORE),
501 shared_data->canrestore);
502 printRegPair(outs, "Otherwin",
503 thread->readMiscReg(MISCREG_OTHERWIN),
504 shared_data->otherwin);
505 printRegPair(outs, "Cleanwin",
506 thread->readMiscReg(MISCREG_CLEANWIN),
507 shared_data->cleanwin);
291 outs << endl;
508 outs << endl;
509 for (int i = 1; i <= MaxTL; i++) {
510 printLevelHeader(outs, i);
511 printColumnLabels(outs);
512 thread->setMiscReg(MISCREG_TL, i);
513 printRegPair(outs, "Tpc",
514 thread->readMiscReg(MISCREG_TPC),
515 shared_data->tpc[i]);
516 printRegPair(outs, "Tnpc",
517 thread->readMiscReg(MISCREG_TNPC),
518 shared_data->tnpc[i]);
519 printRegPair(outs, "Tstate",
520 thread->readMiscReg(MISCREG_TSTATE),
521 shared_data->tstate[i]);
522 printRegPair(outs, "Tt",
523 thread->readMiscReg(MISCREG_TT),
524 shared_data->tt[i]);
525 printRegPair(outs, "Htstate",
526 thread->readMiscReg(MISCREG_HTSTATE),
527 shared_data->htstate[i]);
528 }
529 thread->setMiscReg(MISCREG_TL, oldTl);
530 outs << endl;
292
531
532 printSectionHeader(outs, "General Purpose Registers");
293 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
294 for(int y = 0; y < 4; y++)
295 {
296 for(int x = 0; x < 8; x++)
297 {
533 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
534 for(int y = 0; y < 4; y++)
535 {
536 for(int x = 0; x < 8; x++)
537 {
298 outs << regtypes[y] << x << " " ;
299 outs << "0x" << hex << setw(16) << thread->readIntReg(y*8+x);
300 if (thread->readIntReg(y*8 + x) != shared_data->intregs[y*8+x])
538 char label[8];
539 sprintf(label, "%s%d", regtypes[y], x);
540 printRegPair(outs, label,
541 thread->readIntReg(y*8+x),
542 shared_data->intregs[y*8+x]);
543 /*outs << regtypes[y] << x << " " ;
544 outs << "0x" << hex << setw(16)
545 << thread->readIntReg(y*8+x);
546 if (thread->readIntReg(y*8 + x)
547 != shared_data->intregs[y*8+x])
301 outs << " X ";
302 else
303 outs << " | ";
548 outs << " X ";
549 else
550 outs << " | ";
304 outs << "0x" << setw(16) << hex << shared_data->intregs[y*8+x]
305 << endl;
551 outs << "0x" << setw(16) << hex
552 << shared_data->intregs[y*8+x]
553 << endl;*/
306 }
307 }
308 fatal("Differences found between Legion and M5\n");
309 }
310
311 compared = true;
312 shared_data->flags = OWN_LEGION;
313 }
314 } // while
315 } // if not microop
316 }
317#endif
318}
319
320
321vector<bool> Trace::InstRecord::flags(NUM_BITS);
322string Trace::InstRecord::trace_system;
323
324////////////////////////////////////////////////////////////////////////
325//
326// Parameter space for per-cycle execution address tracing options.
327// Derive from ParamContext so we can override checkParams() function.
328//
329class ExecutionTraceParamContext : public ParamContext
330{
331 public:
332 ExecutionTraceParamContext(const string &_iniSection)
333 : ParamContext(_iniSection)
334 {
335 }
336
337 void checkParams(); // defined at bottom of file
338};
339
340ExecutionTraceParamContext exeTraceParams("exetrace");
341
342Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
343 "capture speculative instructions", true);
344
345Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
346 "print cycle number", true);
347Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
348 "print op class", true);
349Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
350 "print thread number", true);
351Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
352 "print effective address", true);
353Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
354 "print result data", true);
355Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
356 "print all integer regs", false);
357Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
358 "print fetch sequence number", false);
359Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
360 "print correct-path sequence number", false);
361Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
362 "print which registers changed to what", false);
363Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
364 "Use symbols for the PC if available", true);
365Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
366 "print trace in intel compatible format", false);
367Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
368 "Compare sim state to legion state every cycle",
369 false);
370Param<string> exe_trace_system(&exeTraceParams, "trace_system",
371 "print trace of which system (client or server)",
372 "client");
373
374
375//
376// Helper function for ExecutionTraceParamContext::checkParams() just
377// to get us into the InstRecord namespace
378//
379void
380Trace::InstRecord::setParams()
381{
382 flags[TRACE_MISSPEC] = exe_trace_spec;
383
384 flags[PRINT_CYCLE] = exe_trace_print_cycle;
385 flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
386 flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
387 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
388 flags[PRINT_EFF_ADDR] = exe_trace_print_data;
389 flags[PRINT_INT_REGS] = exe_trace_print_iregs;
390 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
391 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
392 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
393 flags[PC_SYMBOL] = exe_trace_pc_symbol;
394 flags[INTEL_FORMAT] = exe_trace_intel_format;
395 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
396 trace_system = exe_trace_system;
397
398 // If were going to be in lockstep with Legion
399 // Setup shared memory, and get otherwise ready
400 if (flags[LEGION_LOCKSTEP]) {
401 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
402 if (shmfd < 0)
403 fatal("Couldn't get shared memory fd. Is Legion running?");
404
405 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
406 if (shared_data == (SharedData*)-1)
407 fatal("Couldn't allocate shared memory");
408
409 if (shared_data->flags != OWN_M5)
410 fatal("Shared memory has invalid owner");
411
412 if (shared_data->version != VERSION)
413 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
414 shared_data->version);
415
416 // step legion forward one cycle so we can get register values
417 shared_data->flags = OWN_LEGION;
418 }
419}
420
421void
422ExecutionTraceParamContext::checkParams()
423{
424 Trace::InstRecord::setParams();
425}
426
554 }
555 }
556 fatal("Differences found between Legion and M5\n");
557 }
558
559 compared = true;
560 shared_data->flags = OWN_LEGION;
561 }
562 } // while
563 } // if not microop
564 }
565#endif
566}
567
568
569vector<bool> Trace::InstRecord::flags(NUM_BITS);
570string Trace::InstRecord::trace_system;
571
572////////////////////////////////////////////////////////////////////////
573//
574// Parameter space for per-cycle execution address tracing options.
575// Derive from ParamContext so we can override checkParams() function.
576//
577class ExecutionTraceParamContext : public ParamContext
578{
579 public:
580 ExecutionTraceParamContext(const string &_iniSection)
581 : ParamContext(_iniSection)
582 {
583 }
584
585 void checkParams(); // defined at bottom of file
586};
587
588ExecutionTraceParamContext exeTraceParams("exetrace");
589
590Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
591 "capture speculative instructions", true);
592
593Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
594 "print cycle number", true);
595Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
596 "print op class", true);
597Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
598 "print thread number", true);
599Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
600 "print effective address", true);
601Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
602 "print result data", true);
603Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
604 "print all integer regs", false);
605Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
606 "print fetch sequence number", false);
607Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
608 "print correct-path sequence number", false);
609Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
610 "print which registers changed to what", false);
611Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
612 "Use symbols for the PC if available", true);
613Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
614 "print trace in intel compatible format", false);
615Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
616 "Compare sim state to legion state every cycle",
617 false);
618Param<string> exe_trace_system(&exeTraceParams, "trace_system",
619 "print trace of which system (client or server)",
620 "client");
621
622
623//
624// Helper function for ExecutionTraceParamContext::checkParams() just
625// to get us into the InstRecord namespace
626//
627void
628Trace::InstRecord::setParams()
629{
630 flags[TRACE_MISSPEC] = exe_trace_spec;
631
632 flags[PRINT_CYCLE] = exe_trace_print_cycle;
633 flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
634 flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
635 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
636 flags[PRINT_EFF_ADDR] = exe_trace_print_data;
637 flags[PRINT_INT_REGS] = exe_trace_print_iregs;
638 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
639 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
640 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
641 flags[PC_SYMBOL] = exe_trace_pc_symbol;
642 flags[INTEL_FORMAT] = exe_trace_intel_format;
643 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep;
644 trace_system = exe_trace_system;
645
646 // If were going to be in lockstep with Legion
647 // Setup shared memory, and get otherwise ready
648 if (flags[LEGION_LOCKSTEP]) {
649 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
650 if (shmfd < 0)
651 fatal("Couldn't get shared memory fd. Is Legion running?");
652
653 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
654 if (shared_data == (SharedData*)-1)
655 fatal("Couldn't allocate shared memory");
656
657 if (shared_data->flags != OWN_M5)
658 fatal("Shared memory has invalid owner");
659
660 if (shared_data->version != VERSION)
661 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
662 shared_data->version);
663
664 // step legion forward one cycle so we can get register values
665 shared_data->flags = OWN_LEGION;
666 }
667}
668
669void
670ExecutionTraceParamContext::checkParams()
671{
672 Trace::InstRecord::setParams();
673}
674