Bug fix: check if vm exists
[avr-sim.git] / Trace.cpp
blobc1552b692c157928b57fec3d0e99ff6654904aee
1 #include "Trace.h"
2 #include "Core.h"
3 #include "DebugInterface.h"
5 namespace avr {
7 Trace Trace::trace;
9 Trace::Trace() {
10 for (traceIndex = 0; traceIndex < traceBufferSize; traceIndex++)
11 traceBuffer[traceIndex] = NOTHING;
13 traceIndex = 0;
16 Trace::~Trace() {
17 if( fout.is_open() )
18 fout.close();
21 // type() - return the trace type at 'index'
22 unsigned int Trace::type(unsigned int index) const {
23 unsigned int traceType = get(index) & TYPE_MASK;
24 unsigned int cycleType = traceType & (CYCLE_COUNTER_LO
25 | CYCLE_COUNTER_HI);
26 return cycleType ? cycleType : traceType;
29 // When logging is enabled, the entire trace buffer will be copied to a file.
30 void Trace::enableLogging(char *fname) {
31 fout.open( fname, std::ios::out | std::ios::binary );
34 void Trace::disableLogging() {
35 fout.close();
38 int Trace::isCycleTrace(unsigned int index, lword *cycle) const {
39 if ( (get(index) & (CYCLE_COUNTER_LO | CYCLE_COUNTER_HI)) == 0)
40 return 0;
42 // Cycle counter
44 // A cycle counter occupies two consecutive trace buffer entries.
45 // We have to determine if the current entry (pointed to by index) is
46 // the high or low integer of the cycle counter.
48 // The upper two bits of the trace are used to decode the two 32-bit
49 // integers that comprise the cycle counter. The encoding algorithm is
50 // optimized for speed:
51 // CYCLE_COUNTER_LO is defined as 1<<31
52 // CYCLE_COUNTER_HI is defined as 1<<30
54 // trace[i] = low 32 bits of cycle counter | CYCLE_COUNTER_LO
55 // trace[i+1] = upper 32 bits of " " | CYCLE_COUNTER_HI | bit 31 of cycle counter
57 // The low 32-bits are always saved in the trace buffer with the msb (CYCLE_COUNTER_LO)
58 // set. However, notice that this bit may've already been set prior to calling trace().
59 // So we need to make sure that we don't lose it. This is done by copying it along
60 // with the high 32-bits of the cycle counter into the next trace buffer location. The
61 // upper 2 bits of the cycle counter are assumed to always be zero (if they're not, gpsim
62 // has been running for a loooonnnggg time!). Bit 30 (CYCLE_COUNTER_HIGH) is always
63 // set in the high 32 bit trace. While bit 31 gets the copy of bit 31 that was over
64 // written in the low 32 bit trace.
66 // Here are some examples:
67 // upper 2 bits
68 // cycle counter | trace[i] trace[i+1] [i] [i+1]
69 //---------------------+----------------------------------------
70 // 0x12345678 | 0x92345678 0x40000000 10 01
71 // 0x44445555 | 0xc4445555 0x40000000 11 01
72 // 0x1111222233334444 | 0xb3334444 0x51112222 10 01
73 // 0x9999aaaa | 0x9999aaaa 0xc0000000 10 11
74 // 0xccccdddd | 0xccccdddd 0xc0000000 11 11
75 // 0xccccddde | 0xccccddde 0xc0000000 11 11
77 // Looking at the upper two bits of trace buffer, we can make these
78 // observations:
80 // 00 - not a cycle counter trace
81 // 10 - current index points at the low int of a cycle counter
82 // 01 - current index points at the high int of a cycle counter
83 // 11 - if traces on either side of the current index are the same
84 // then the current index points to a low int else it points to a high int
86 int j = index; // Assume that the index is pointing to the low int.
87 int k = (j + 1) & traceBufferMask; // and that the next entry is the high int.
89 if ( ((get(j) & CYCLE_COUNTER_LO) != 0)&& ((get(k) & CYCLE_COUNTER_HI))
90 != 0) {
91 if ( (get(j) & CYCLE_COUNTER_HI) != 0) {
92 // The upper two bits of the current trace are set. This means that
93 // the trace is either the high 32 bits or the low 32 bits of the cycle
94 // counter. This ambiguity is resolved by examining the trace buffer on
95 // either side of the current index. If the entry immediately proceeding
96 // this one is not a cycle counter trace, then we know that we're pointing
97 // at the low 32 bits. If the proceeding entry IS a cycle counter trace then
98 // we have two consecutive cycle traces (we already know that the entry
99 // immediately following the current trace index is a cycle counter trace).
100 // Now we know that if have consecutive cycle traces, then they differ by one
101 // count. We only need to look at the low 32 bits of these consecutive
102 // traces to ascertain this.
103 int i = (index - 1) & traceBufferMask; // previous index
104 if ( (get(i) & (CYCLE_COUNTER_HI | CYCLE_COUNTER_LO) != 0)
105 &&( ((get(k) - get(i)) & 0x7fffffff) == 1))
106 return 1;
109 // The current index points to the low int and the next entry is
110 // the high int.
111 // extract the ~64bit cycle counter from the trace buffer.
112 if (cycle != 0) {
113 *cycle = get(k) & 0x3fffffff;
114 *cycle = (*cycle << 32) | ((get(j) & 0x7fffffff) | (get(k)
115 & 0x80000000));
118 return 2;
122 return 1;
125 #define hexchar(a) std::hex << int(a) << std::dec
126 void Trace::print(unsigned index, std::ostream & ostr,
127 DebugInterface & dbgi) const {
128 lword cycle;
129 if (isCycleTrace(index, &cycle) == 2)
130 return;
132 switch( type(index) ) {
133 case NOTHING:
134 ostr << "empty trace cycle"<< std::endl;
135 break;
137 case BREAKPOINT:
138 ostr << "Break: "<< (get(index) & 0xffffff)<< std::endl;
139 break;
141 case RESET: {
142 switch (get(index) & 0xff) {
143 case POR_RESET:
144 ostr << "Power-on reset"<< std::endl;
145 break;
147 case WDT_RESET:
148 ostr << "WDT reset"<< std::endl;
149 break;
151 case JTAG_RESET:
152 ostr << "JTAG reset"<< std::endl;
153 break;
155 case EXT_RESET:
156 ostr << "External reset"<< std::endl;
157 break;
159 case SOFT_RESET:
160 ostr << "Software initiated reset"<< std::endl;
161 break;
163 case BOD_RESET:
164 ostr << "Brown out detection reset"<< std::endl;
165 break;
167 case SIM_RESET:
168 ostr << "Simulation Reset"<< std::endl;
169 break;
171 default:
172 ostr << "unknown reset"<< std::endl;
175 break;
177 case OPCODE_WRITE: {
178 if (type(index-1) == OPCODE_WRITE )
179 ostr << "wrote opcode: " << std::hex << (get(index)&0xffff)
180 << "to pgm memory: "<< (get(index - 1) & 0xffffff)
181 << std::dec << std::endl;
183 break;
185 case REG_WRITE: {
186 byte reg = ((get(index)&0xffff00) >> 8);
187 ostr << "Registers write: address "
188 << dbgi.registerName( reg )
189 << " value = " << hexchar(get(index)&0xff)
190 << std::endl;
192 break;
194 case REG_READ: {
195 byte reg = ((get(index)&0xffff00) >> 8);
196 ostr << "Registers read: address "
197 << dbgi.registerName( reg )
198 << " value = " << hexchar(get(index)&0xff)
199 << std::endl;
201 break;
203 case PC_TRACE: {
204 dword addr = (get(index)&0xffffff);
205 ostr << "PC trace: address "
206 << std::hex << addr << std::dec << ": ";
207 dbgi.trace( ostr, addr );
208 ostr << std::endl;
210 break;
212 default:
217 void Trace::printFrom(unsigned index, std::ostream & ostr, Device & dev) const {
218 DebugInterface *dbgi = dev.debugInterface();
219 while( index < traceIndex ) {
220 print( index, ostr, *dbgi );
221 index++;
224 delete dbgi;
227 void Trace::print(std::ostream & ostr, Device & dev) const {
228 DebugInterface *dbgi = dev.debugInterface();
229 unsigned int i = tbi(traceIndex-2);
230 unsigned int k = tbi(traceIndex-1);
232 if( isCycleTrace(i, 0) != 2 )
233 return;
235 unsigned int frame_start = tbi(traceIndex-2);
236 unsigned int frame_end = traceIndex;
238 while( inRange(k,frame_end,frame_start) ) {
239 print(k, ostr, *dbgi);
240 k = tbi(k-1);
243 delete dbgi;
246 void Trace::list(const char *filename, std::ostream & ostr, Device & dev) {
247 std::ifstream f( filename, std::ios::in | std::ios::binary );
248 if( ! f.is_open() )
249 return;
251 DebugInterface *dbgi = dev.debugInterface();
252 traceIndex = traceBufferSize;
253 bool done = false;
254 while( !done ) {
255 f.read( (char*)traceBuffer, traceBufferSize * sizeof(unsigned int) );
256 if( ! f ) {
257 traceIndex = f.gcount() / sizeof(unsigned int);
258 done = true;
261 for(unsigned int index = 0; index < traceIndex; ++index)
262 print( index, ostr, *dbgi );
265 delete dbgi;