Bug fix: check if vm exists
[avr-sim.git] / Trace.h
blobdf63e2cad842e34817f579518adbed99d30ebcfb
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;
13 * This class traces almost everything simulated: instructions executed,
14 * register reads/writes, clock cycles, break points, instruction skips,
15 * external modules, and a few other miscellaneous things.
17 * Details
18 * Each trace takes exactly one 32-bit word. The upper 8-bits define
19 * the trace type and the lower 24 are the trace value. For example,
20 * a register write will get traced with a 32 bit encoded like:
22 * TTAAAAVV
24 * TT - Register write trace type
25 * AAAA - 4-hexdigit address
26 * VV - 2-hexdigit (8-bit) value
28 * The cycle counter is treated slightly differently. Since it is a
29 * 64-bit object, it has to be split across at least two trace
30 * entries. The upper few bits of the cycle counter aren't
31 * traced.
33 * This class is based on the trace in gpsim.
35 class Trace {
36 public:
37 static Trace & instance() { return trace; }
39 public:
40 /**
41 * Trace raw allows any value to be written to the trace buffer.
42 * This is useful for modules that wish to trace things, but do
43 * not wish to modify the Trace class.
45 void raw(unsigned int ui);
47 void register_write(unsigned int address, unsigned char val);
48 void register_read(unsigned int address, unsigned char val);
49 void opcode_write(unsigned int address, unsigned int opcode);
50 void cycle_counter(lword cc);
51 void breakpoint(unsigned int bp);
52 void interrupt(unsigned int intr);
53 void reset(unsigned int type);
54 void pc_trace(unsigned int address);
56 public:
57 /**
58 * return the trace entry at 'index'
60 unsigned int operator [](unsigned int index) const;
62 /**
63 * return the trace entry at 'index'
65 unsigned int get(unsigned int index) const;
67 /**
68 * inRange - returns true if the trace index i is between the
69 * indices of low and high.
70 * It's assumed that the range does not exceed half of the trace buffer
72 bool inRange(unsigned int i, unsigned int low, unsigned int high) const;
74 //* type() - return the trace type at 'index'
75 unsigned int type(unsigned int index) const;
77 /**
78 * Given an index into the trace buffer, this function determines
79 * if the trace is a cycle counter trace.
81 * INPUT: index - index into the trace buffer
82 * *cycle - a pointer to where the cycle will be decoded
83 * if the trace entry is a cycle trace.
84 * RETURN: 0 - trace is not a cycle counter
85 * 1 - trace is the high integer of a cycle trace
86 * 2 - trace is the low integer of a cycle trace
88 int isCycleTrace(unsigned int index, lword *cycle) const;
90 public:
91 // When logging is enabled, the entire trace buffer will be copied to a file.
92 void enableLogging(char *fname);
93 void disableLogging();
95 void list(const char *filename, std::ostream & ostr, Device & dev);
96 void print(std::ostream & ostr, Device & dev) const;
97 void printFrom(unsigned index, std::ostream & ostr, Device & dev) const;
98 void print(unsigned index, std::ostream & ostr, DebugInterface & dbgi) const;
100 private:
101 //* tbi - trace buffer index masking.
102 unsigned int tbi(unsigned int index) const;
103 void log();
105 private:
106 enum eTraceTypes {
107 NOTHING = 0x3fffffff,
108 BREAKPOINT = (2<<24),
109 INTERRUPT = (3<<24),
110 RESET = (4<<24),
111 REG_WRITE = (5<<24),
112 REG_READ = (6<<24),
113 OPCODE_WRITE = (7<<24),
114 PC_TRACE = (8<<24),
115 LAST_TRACE_TYPE = (9<<24),
117 TYPE_MASK = (0xff<<24),
118 CYCLE_COUNTER_LO = (0x80<<24),
119 CYCLE_COUNTER_HI = (0x40<<24)
122 static const unsigned int traceBufferSize = 1<<12;
123 static const unsigned int traceBufferMask = traceBufferSize - 1;
125 unsigned int traceBuffer[traceBufferSize];
126 unsigned int traceIndex;
128 private:
129 std::ofstream fout;
130 static Trace trace;
132 private:
133 Trace();
134 ~Trace();
137 inline void Trace::raw(unsigned int ui) {
138 traceBuffer[traceIndex] = ui;
139 log();
140 traceIndex = (traceIndex + 1) & traceBufferMask;
143 inline void Trace::register_write(unsigned int address, unsigned char val) {
144 raw( REG_WRITE | ((address & 0xffff) << 8) | val );
147 inline void Trace::register_read(unsigned int address, unsigned char val) {
148 raw( REG_READ | ((address & 0xffff) << 8) | val );
151 inline void Trace::opcode_write(unsigned int address, unsigned int opcode) {
152 raw( OPCODE_WRITE | (address & 0xffffff) );
153 raw( OPCODE_WRITE | (opcode & 0xffff) );
156 inline void Trace::cycle_counter(lword cc) {
157 // The 64 bit cycle counter requires two 32 bit traces.
158 raw( (unsigned int)(CYCLE_COUNTER_LO | (cc & 0xffffffff)) );
159 raw( (unsigned int)(CYCLE_COUNTER_HI | (cc>>32)| (cc & CYCLE_COUNTER_LO)) );
161 inline void Trace::breakpoint(unsigned int bp) {
162 raw( BREAKPOINT | bp );
165 inline void Trace::interrupt(unsigned int intr) {
166 raw( INTERRUPT | intr & 0xffff );
169 inline void Trace::reset(unsigned int type) {
170 raw( RESET | type & 0xffff );
173 inline void Trace::pc_trace(unsigned int address) {
174 raw( PC_TRACE | address & 0xffffff );
177 // tbi - trace buffer index masking.
178 inline unsigned int Trace::tbi(unsigned int index) const {
179 return index & traceBufferMask;
182 // get() return the trace entry at 'index'
183 inline unsigned int Trace::operator [] (unsigned int index) const {
184 return traceBuffer[tbi(index)];
187 inline unsigned int Trace::get(unsigned int index) const {
188 return traceBuffer[tbi(index)];
191 inline void Trace::log() {
192 if( fout.is_open() )
193 fout.write( (const char*)&traceBuffer[traceIndex], sizeof(unsigned int) );
196 inline bool Trace::inRange(unsigned int i, unsigned int low, unsigned int high) const {
197 i = tbi(i);
199 if( low < high)
200 return (i >= low && i <= high);
202 // Looks like the range straddles the roll over boundary.
203 return (i >= low || i <= high);
208 #endif /*TRACE_H_*/