Timer8 now has a variable amount of output compare units.
[avr-sim.git] / src / Trace.h
blob6d8bce494e0fe981e95d50691bb1e3ee2ce396ac
1 #ifndef AVR_TRACE_H
2 #define AVR_TRACE_H
4 #include <iostream>
5 #include <fstream>
6 #include "Types.h"
8 namespace avr {
9 class Device;
10 class DebugInterface;
12 /**
13 * @author Tom Haber
14 * @date Apr 25, 2008
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.
21 * Details
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:
26 * TTAAAAVV
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
35 * traced.
37 * This class is based on the trace in gpsim.
39 * TODO integrate this further with TraceAnalyzer unless real-time tracing is required
41 class Trace {
42 public:
43 static Trace & instance() { return trace; }
45 public:
46 /**
47 * Trace raw allows any value to be written to the trace buffer.
48 * This is useful for modules that wish to trace things, but do
49 * not wish to modify the Trace class.
51 void raw(unsigned int ui);
53 void register_write(unsigned int address, unsigned char val);
54 void register_read(unsigned int address, unsigned char val);
55 void opcode_write(unsigned int address, unsigned int opcode);
56 void cycle_counter(lword cc);
57 void breakpoint(unsigned int bp);
58 void interrupt(unsigned int intr);
59 void reset(unsigned int type);
60 void pc_trace(unsigned int address);
62 public:
63 /**
64 * return the trace entry at 'index'
66 unsigned int operator [](unsigned int index) const;
68 /**
69 * return the trace entry at 'index'
71 unsigned int get(unsigned int index) const;
73 /**
74 * inRange - returns true if the trace index i is between the
75 * indices of low and high.
76 * It's assumed that the range does not exceed half of the trace buffer
78 bool inRange(unsigned int i, unsigned int low, unsigned int high) const;
80 //* type() - return the trace type at 'index'
81 unsigned int type(unsigned int index) const;
83 /**
84 * Given an index into the trace buffer, this function determines
85 * if the trace is a cycle counter trace.
87 * INPUT: index - index into the trace buffer
88 * *cycle - a pointer to where the cycle will be decoded
89 * if the trace entry is a cycle trace.
90 * RETURN: 0 - trace is not a cycle counter
91 * 1 - trace is the high integer of a cycle trace
92 * 2 - trace is the low integer of a cycle trace
94 int isCycleTrace(unsigned int index, lword *cycle) const;
96 public:
97 // When logging is enabled, the entire trace buffer will be copied to a file.
98 void enableLogging(const char *fname);
99 void disableLogging();
101 void list(const char *filename, std::ostream & ostr,
102 Device & dev, int verbose = 0);
103 void print(std::ostream & ostr, Device & dev, int verbose = 0) const;
104 void printFrom(unsigned index, std::ostream & ostr,
105 Device & dev, int verbose = 0) const;
106 void print(unsigned index, std::ostream & ostr,
107 DebugInterface & dbgi, int verbose) const;
109 private:
110 //* tbi - trace buffer index masking.
111 unsigned int tbi(unsigned int index) const;
112 void log();
114 private:
115 enum eTraceTypes {
116 NOTHING = 0x3fffffff,
117 INTERRUPT = (3<<24),
118 RESET = (4<<24),
119 REG_WRITE = (5<<24),
120 REG_READ = (6<<24),
121 OPCODE_WRITE = (7<<24),
122 PC_TRACE = (8<<24),
123 LAST_TRACE_TYPE = (9<<24),
125 TYPE_MASK = (0xff<<24),
126 CYCLE_COUNTER_LO = (0x80<<24),
127 CYCLE_COUNTER_HI = (0x40<<24)
130 static const unsigned int traceBufferSize = 1<<12;
131 static const unsigned int traceBufferMask = traceBufferSize - 1;
133 unsigned int traceBuffer[traceBufferSize];
134 unsigned int traceIndex;
136 private:
137 std::ofstream fout;
138 static Trace trace;
140 private:
141 Trace();
142 ~Trace();
145 inline void Trace::raw(unsigned int ui) {
146 traceBuffer[traceIndex] = ui;
147 log();
148 traceIndex = (traceIndex + 1) & traceBufferMask;
151 inline void Trace::register_write(unsigned int address, unsigned char val) {
152 raw( REG_WRITE | ((address & 0xffff) << 8) | val );
155 inline void Trace::register_read(unsigned int address, unsigned char val) {
156 raw( REG_READ | ((address & 0xffff) << 8) | val );
159 inline void Trace::opcode_write(unsigned int address, unsigned int opcode) {
160 raw( OPCODE_WRITE | (address & 0xffffff) );
161 raw( OPCODE_WRITE | (opcode & 0xffff) );
164 inline void Trace::cycle_counter(lword cc) {
165 // The 64 bit cycle counter requires two 32 bit traces.
166 raw( (unsigned int)(CYCLE_COUNTER_LO | (cc & 0xffffffff)) );
167 raw( (unsigned int)(CYCLE_COUNTER_HI | (cc>>32)| (cc & CYCLE_COUNTER_LO)) );
170 inline void Trace::interrupt(unsigned int intr) {
171 raw( INTERRUPT | intr & 0xffff );
174 inline void Trace::reset(unsigned int type) {
175 raw( RESET | type & 0xffff );
178 inline void Trace::pc_trace(unsigned int address) {
179 raw( PC_TRACE | address & 0xffffff );
182 // tbi - trace buffer index masking.
183 inline unsigned int Trace::tbi(unsigned int index) const {
184 return index & traceBufferMask;
187 // get() return the trace entry at 'index'
188 inline unsigned int Trace::operator [] (unsigned int index) const {
189 return traceBuffer[tbi(index)];
192 inline unsigned int Trace::get(unsigned int index) const {
193 return traceBuffer[tbi(index)];
196 inline void Trace::log() {
197 if( fout.is_open() )
198 fout.write( (const char*)&traceBuffer[traceIndex], sizeof(unsigned int) );
201 inline bool Trace::inRange(unsigned int i, unsigned int low, unsigned int high) const {
202 i = tbi(i);
204 if( low < high)
205 return (i >= low && i <= high);
207 // Looks like the range straddles the roll over boundary.
208 return (i >= low || i <= high);
213 #endif /*TRACE_H_*/