15 * @brief Traces almost everything simulated.
17 * This class traces almost everything simulated: instructions executed,
18 * register reads/writes, clock cycles, break points, instruction skips,
19 * external modules, and a few other miscellaneous things.
22 * Each trace takes exactly one 32-bit word. The upper 8-bits define
23 * the trace type and the lower 24 are the trace value. For example,
24 * a register write will get traced with a 32 bit encoded like:
28 * TT - Register write trace type
29 * AAAA - 4-hexdigit address
30 * VV - 2-hexdigit (8-bit) value
32 * The cycle counter is treated slightly differently. Since it is a
33 * 64-bit object, it has to be split across at least two trace
34 * entries. The upper few bits of the cycle counter aren't
37 * This class is based on the trace in gpsim.
39 * TODO integrate this further with TraceAnalyzer unless real-time tracing is required
48 * Trace raw allows any value to be written to the trace buffer.
49 * This is useful for modules that wish to trace things, but do
50 * not wish to modify the Trace class.
52 void raw(unsigned int ui
);
54 void register_write(unsigned int address
, unsigned char val
);
55 void register_read(unsigned int address
, unsigned char val
);
56 void opcode_write(unsigned int address
, unsigned int opcode
);
57 void cycle_counter(lword cc
);
58 void breakpoint(unsigned int bp
);
59 void interrupt(unsigned int intr
);
60 void reset(unsigned int type
);
61 void pc_trace(unsigned int address
);
65 * return the trace entry at 'index'
67 unsigned int operator [](unsigned int index
) const;
70 * return the trace entry at 'index'
72 unsigned int get(unsigned int index
) const;
75 * inRange - returns true if the trace index i is between the
76 * indices of low and high.
77 * It's assumed that the range does not exceed half of the trace buffer
79 bool inRange(unsigned int i
, unsigned int low
, unsigned int high
) const;
81 //* type() - return the trace type at 'index'
82 unsigned int type(unsigned int index
) const;
85 * Given an index into the trace buffer, this function determines
86 * if the trace is a cycle counter trace.
88 * INPUT: index - index into the trace buffer
89 * *cycle - a pointer to where the cycle will be decoded
90 * if the trace entry is a cycle trace.
91 * RETURN: 0 - trace is not a cycle counter
92 * 1 - trace is the high integer of a cycle trace
93 * 2 - trace is the low integer of a cycle trace
95 int isCycleTrace(unsigned int index
, lword
*cycle
) const;
98 // When logging is enabled, the entire trace buffer will be copied to a file.
99 void enableLogging(const char *fname
);
100 void disableLogging();
102 void list(const char *filename
, std::ostream
& ostr
,
103 Device
& dev
, int verbose
= 0);
104 void print(std::ostream
& ostr
, Device
& dev
, int verbose
= 0) const;
105 void printFrom(unsigned index
, std::ostream
& ostr
,
106 Device
& dev
, int verbose
= 0) const;
107 void print(unsigned index
, std::ostream
& ostr
,
108 DebugInterface
& dbgi
, int verbose
) const;
111 //* tbi - trace buffer index masking.
112 unsigned int tbi(unsigned int index
) const;
117 NOTHING
= 0x3fffffff,
122 OPCODE_WRITE
= (7<<24),
124 LAST_TRACE_TYPE
= (9<<24),
126 TYPE_MASK
= (0xff<<24),
127 CYCLE_COUNTER_LO
= (0x80<<24),
128 CYCLE_COUNTER_HI
= (0x40<<24)
131 static const unsigned int traceBufferSize
= 1<<12;
132 static const unsigned int traceBufferMask
= traceBufferSize
- 1;
134 unsigned int traceBuffer
[traceBufferSize
];
135 unsigned int traceIndex
;
141 inline void Trace::raw(unsigned int ui
) {
142 traceBuffer
[traceIndex
] = ui
;
144 traceIndex
= (traceIndex
+ 1) & traceBufferMask
;
147 inline void Trace::register_write(unsigned int address
, unsigned char val
) {
148 raw( REG_WRITE
| ((address
& 0xffff) << 8) | val
);
151 inline void Trace::register_read(unsigned int address
, unsigned char val
) {
152 raw( REG_READ
| ((address
& 0xffff) << 8) | val
);
155 inline void Trace::opcode_write(unsigned int address
, unsigned int opcode
) {
156 raw( OPCODE_WRITE
| (address
& 0xffffff) );
157 raw( OPCODE_WRITE
| (opcode
& 0xffff) );
160 inline void Trace::cycle_counter(lword cc
) {
161 // The 64 bit cycle counter requires two 32 bit traces.
162 raw( (unsigned int)(CYCLE_COUNTER_LO
| (cc
& 0xffffffff)) );
163 raw( (unsigned int)(CYCLE_COUNTER_HI
| (cc
>>32)| (cc
& CYCLE_COUNTER_LO
)) );
166 inline void Trace::interrupt(unsigned int intr
) {
167 raw( INTERRUPT
| (intr
& 0xffff) );
170 inline void Trace::reset(unsigned int type
) {
171 raw( RESET
| (type
& 0xffff) );
174 inline void Trace::pc_trace(unsigned int address
) {
175 raw( PC_TRACE
| (address
& 0xffffff) );
178 // tbi - trace buffer index masking.
179 inline unsigned int Trace::tbi(unsigned int index
) const {
180 return index
& traceBufferMask
;
183 // get() return the trace entry at 'index'
184 inline unsigned int Trace::operator [] (unsigned int index
) const {
185 return traceBuffer
[tbi(index
)];
188 inline unsigned int Trace::get(unsigned int index
) const {
189 return traceBuffer
[tbi(index
)];
192 inline void Trace::log() {
194 fout
.write( (const char*)&traceBuffer
[traceIndex
], sizeof(unsigned int) );
197 inline bool Trace::inRange(unsigned int i
, unsigned int low
, unsigned int high
) const {
201 return (i
>= low
&& i
<= high
);
203 // Looks like the range straddles the roll over boundary.
204 return (i
>= low
|| i
<= high
);