2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "VerboseInfo.h"
22 #include "DebugInterface.h"
27 for (traceIndex
= 0; traceIndex
< traceBufferSize
; traceIndex
++)
28 traceBuffer
[traceIndex
] = NOTHING
;
38 // type() - return the trace type at 'index'
39 unsigned int Trace::type(unsigned int index
) const {
40 unsigned int traceType
= get(index
) & TYPE_MASK
;
41 unsigned int cycleType
= traceType
& (CYCLE_COUNTER_LO
43 return cycleType
? cycleType
: traceType
;
46 // When logging is enabled, the entire trace buffer will be copied to a file.
47 void Trace::enableLogging(const char *fname
) {
48 fout
.open( fname
, std::ios::out
| std::ios::binary
);
51 void Trace::disableLogging() {
55 int Trace::isCycleTrace(unsigned int index
, lword
*cycle
) const {
56 if ( (get(index
) & (CYCLE_COUNTER_LO
| CYCLE_COUNTER_HI
)) == 0)
61 // A cycle counter occupies two consecutive trace buffer entries.
62 // We have to determine if the current entry (pointed to by index) is
63 // the high or low integer of the cycle counter.
65 // The upper two bits of the trace are used to decode the two 32-bit
66 // integers that comprise the cycle counter. The encoding algorithm is
67 // optimized for speed:
68 // CYCLE_COUNTER_LO is defined as 1<<31
69 // CYCLE_COUNTER_HI is defined as 1<<30
71 // trace[i] = low 32 bits of cycle counter | CYCLE_COUNTER_LO
72 // trace[i+1] = upper 32 bits of " " | CYCLE_COUNTER_HI | bit 31 of cycle counter
74 // The low 32-bits are always saved in the trace buffer with the msb (CYCLE_COUNTER_LO)
75 // set. However, notice that this bit may've already been set prior to calling trace().
76 // So we need to make sure that we don't lose it. This is done by copying it along
77 // with the high 32-bits of the cycle counter into the next trace buffer location. The
78 // upper 2 bits of the cycle counter are assumed to always be zero (if they're not, gpsim
79 // has been running for a loooonnnggg time!). Bit 30 (CYCLE_COUNTER_HIGH) is always
80 // set in the high 32 bit trace. While bit 31 gets the copy of bit 31 that was over
81 // written in the low 32 bit trace.
83 // Here are some examples:
85 // cycle counter | trace[i] trace[i+1] [i] [i+1]
86 //---------------------+----------------------------------------
87 // 0x12345678 | 0x92345678 0x40000000 10 01
88 // 0x44445555 | 0xc4445555 0x40000000 11 01
89 // 0x1111222233334444 | 0xb3334444 0x51112222 10 01
90 // 0x9999aaaa | 0x9999aaaa 0xc0000000 10 11
91 // 0xccccdddd | 0xccccdddd 0xc0000000 11 11
92 // 0xccccddde | 0xccccddde 0xc0000000 11 11
94 // Looking at the upper two bits of trace buffer, we can make these
97 // 00 - not a cycle counter trace
98 // 10 - current index points at the low int of a cycle counter
99 // 01 - current index points at the high int of a cycle counter
100 // 11 - if traces on either side of the current index are the same
101 // then the current index points to a low int else it points to a high int
103 int j
= index
; // Assume that the index is pointing to the low int.
104 int k
= (j
+ 1) & traceBufferMask
; // and that the next entry is the high int.
106 if ( ((get(j
) & CYCLE_COUNTER_LO
) != 0)&& ((get(k
) & CYCLE_COUNTER_HI
))
108 if ( (get(j
) & CYCLE_COUNTER_HI
) != 0) {
109 // The upper two bits of the current trace are set. This means that
110 // the trace is either the high 32 bits or the low 32 bits of the cycle
111 // counter. This ambiguity is resolved by examining the trace buffer on
112 // either side of the current index. If the entry immediately proceeding
113 // this one is not a cycle counter trace, then we know that we're pointing
114 // at the low 32 bits. If the proceeding entry IS a cycle counter trace then
115 // we have two consecutive cycle traces (we already know that the entry
116 // immediately following the current trace index is a cycle counter trace).
117 // Now we know that if have consecutive cycle traces, then they differ by one
118 // count. We only need to look at the low 32 bits of these consecutive
119 // traces to ascertain this.
120 int i
= (index
- 1) & traceBufferMask
; // previous index
121 if ( ((get(i
) & (CYCLE_COUNTER_HI
| CYCLE_COUNTER_LO
)) != 0)
122 &&( ((get(k
) - get(i
)) & 0x7fffffff) == 1))
126 // The current index points to the low int and the next entry is
128 // extract the ~64bit cycle counter from the trace buffer.
130 *cycle
= get(k
) & 0x3fffffff;
131 *cycle
= (*cycle
<< 32) | ((get(j
) & 0x7fffffff) | (get(k
)
142 #define hexchar(a) std::hex << int(a) << std::dec
143 void Trace::print(unsigned index
, std::ostream
& ostr
,
144 DebugInterface
& dbgi
, int /*verbose*/) const {
146 if( isCycleTrace(index
, &cycle
) == 2 )
149 switch( type(index
) ) {
151 ostr
<< "empty trace cycle"<< std::endl
;
154 case CYCLE_COUNTER_HI
:
155 info(DBG
, ostr
) << "Cycle: " << cycle
<< std::endl
;
159 switch (get(index
) & 0xff) {
161 ostr
<< "Power-on reset"<< std::endl
;
165 ostr
<< "WDT reset"<< std::endl
;
169 ostr
<< "JTAG reset"<< std::endl
;
173 ostr
<< "External reset"<< std::endl
;
177 ostr
<< "Software initiated reset"<< std::endl
;
181 ostr
<< "Brown out detection reset"<< std::endl
;
185 ostr
<< "Simulation Reset"<< std::endl
;
189 ostr
<< "unknown reset"<< std::endl
;
195 if (type(index
-1) == OPCODE_WRITE
)
196 ostr
<< "wrote opcode: " << std::hex
<< (get(index
)&0xffff)
197 << "to pgm memory: "<< (get(index
- 1) & 0xffffff)
198 << std::dec
<< std::endl
;
203 byte reg
= ((get(index
)&0xffff00) >> 8);
204 ostr
<< "Registers write: address "
205 << dbgi
.registerName( reg
)
206 << " value = " << hexchar(get(index
)&0xff)
212 byte reg
= ((get(index
)&0xffff00) >> 8);
213 ostr
<< "Registers read: address "
214 << dbgi
.registerName( reg
)
215 << " value = " << hexchar(get(index
)&0xff)
221 dword addr
= (get(index
)&0xffffff);
222 ostr
<< "PC trace: address "
223 << std::hex
<< addr
<< std::dec
<< ": ";
224 dbgi
.trace( ostr
, addr
);
234 void Trace::printFrom(unsigned index
, std::ostream
& ostr
, Device
& dev
, int verbose
) const {
235 DebugInterface
*dbgi
= dev
.debugInterface();
236 while( index
< traceIndex
) {
237 print( index
, ostr
, *dbgi
, verbose
);
244 void Trace::print(std::ostream
& ostr
, Device
& dev
, int verbose
) const {
245 DebugInterface
*dbgi
= dev
.debugInterface();
246 unsigned int i
= tbi(traceIndex
-2);
247 unsigned int k
= tbi(traceIndex
-1);
249 if( isCycleTrace(i
, 0) != 2 )
252 unsigned int frame_start
= tbi(traceIndex
-2);
253 unsigned int frame_end
= traceIndex
;
255 while( inRange(k
,frame_end
,frame_start
) ) {
256 print(k
, ostr
, *dbgi
, verbose
);
263 void Trace::list(const char *filename
, std::ostream
& ostr
, Device
& dev
, int verbose
) {
264 std::ifstream
f( filename
, std::ios::in
| std::ios::binary
);
268 DebugInterface
*dbgi
= dev
.debugInterface();
269 traceIndex
= traceBufferSize
;
272 f
.read( (char*)traceBuffer
, traceBufferSize
* sizeof(unsigned int) );
274 traceIndex
= f
.gcount() / sizeof(unsigned int);
278 for(unsigned int index
= 0; index
< traceIndex
; ++index
)
279 print( index
, ostr
, *dbgi
, verbose
);