Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_Tracer.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: SS_Tracer.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23
24#ifndef __SS_Tracer_h__
25#define __SS_Tracer_h__
26
27#include <string.h>
28#include "SS_Registers.h"
29#include "SS_Types.h"
30#include "SS_Trap.h"
31#include "SS_Instr.h"
32
33class SS_Tte;
34class SS_Tlb;
35
36class SS_Tracer
37{
38 public:
39 enum TrapMode
40 {
41 NO_TRAP,
42 TRAP,
43 INST_TRAP,
44 DATA_TRAP
45 };
46
47 enum MemAccess
48 {
49 LD_CODE = 0x01,
50 ST_DATA = 0x02,
51 LD_DATA = 0x03,
52 ST_PART = 0x04, // data[0] = rd, data[1] = bytemask
53 ST_SWAP = 0x05, // data[0] = rd
54 LD_SWAP = 0x07, // data[0] = rd
55 ST_CAS = 0x08, // data[0] = rd, data[1] = rs2
56 LD_CAS = 0x09, // data[0] = rd
57 ST_LDST = 0x0a, // data[0] = store value (ldstub stores 0xff)
58 LD_LDST = 0x0b, // data[0] = rd
59 FLUSH = 0x10, // data == 0 in mem_access call
60 PREFETCH = 0x11 // data == 0 in mem_access call
61 };
62
63 static int is_fetch( MemAccess ma ) { return ma == LD_CODE; }
64 static int is_load( MemAccess ma ) { return (ma & 1) == 1; }
65 static int is_store( MemAccess ma ) { return (ma & 1) == 0; }
66 static int is_cohere( MemAccess ma ) { return (ma & 0x10) == 0x10; }
67
68
69 SS_Tracer()
70 :
71 hook_exe_instr(0),
72 hook_reg_value(0),
73 hook_trap(0),
74 hook_mem_access(0),
75 hook_asi_access(0),
76 hook_tlb_update(0),
77 hook_hwop(0),
78 hook_end_instr(0),
79 trap_mode(NO_TRAP),
80 trap_addr(0),
81 next(0)
82 {
83 memset(state,0,sizeof(state));
84 }
85 virtual ~SS_Tracer() {}
86
87 void (*hook_exe_instr) ( SS_Tracer*, SS_Vaddr pc, SS_Tte* tte, SS_Instr* i );
88 void (*hook_reg_value) ( SS_Tracer*, SS_Registers::Index index, uint64_t value );
89 void (*hook_trap) ( SS_Tracer*, SS_Trap::Type tt, TrapMode mode, SS_Vaddr ea );
90 void (*hook_mem_access)( SS_Tracer*, MemAccess, SS_Vaddr, SS_Tte*, uint_t size, uint64_t* data );
91 void (*hook_asi_access)( SS_Tracer*, MemAccess, uint8_t asi, SS_Vaddr, uint64_t* data );
92 void (*hook_tlb_update)( SS_Tracer*, bool insert, SS_Tlb* tlb, uint_t index, SS_Tte* tte );
93 void (*hook_hwop) ( SS_Tracer*, MemAccess type, SS_Paddr addr, uint_t size, uint64_t *value );
94 void (*hook_end_instr) ( SS_Tracer* );
95
96 SS_Tracer* next; // There can be more then one tracer per strand
97
98 bool need_mem_trc()
99 {
100 if (hook_mem_access)
101 return true;
102 else if (next)
103 return next->need_mem_trc();
104 else
105 return false;
106 }
107
108 // exe_instr() is called for every instruction to trace its
109 // virtual pc, physical pc and the instruction word executed.
110 void exe_instr( SS_Vaddr pc, SS_Tte* tte, SS_Instr* i )
111 {
112 if (hook_exe_instr) (hook_exe_instr)(this,pc,tte,i);
113 if (next) next->exe_instr(pc,tte,i);
114 }
115
116 // reg_value() is called for each register that changed value as a
117 // result of executing an instruction. Note that this is a template
118 // function to allow for product spefic SS_Registers::Index extensions.
119 // The given index is casted to SS_Register::Index.
120 template<class Index>
121 void reg_value( Index index, uint64_t value )
122 {
123 if (hook_reg_value) (hook_reg_value)(this,SS_Registers::Index(index),value);
124 if (next) next->reg_value(SS_Registers::Index(index),value);
125 }
126
127 // trap() is called to trace trapping
128 void trap( SS_Trap::Type trap_type )
129 {
130 // in cosim mode, there are likely two (or more) SS_Tracer objects are
131 // registered (i.e., linked by 'next' field) for each strand. When a trap
132 // occurres, we have to traverse through all of them to perform each
133 // object's own trace function. If a trap is a mmu trap, then an
134 // inst_trap() or data_trap() will be called before the trap() is called,
135 // since inst_trap() and data_trap() may deposit more specific
136 // trap_mode and trap_addr information, we should not overwrite those
137 // fields in such case.
138 if (trap_mode == NO_TRAP)
139 {
140 trap_mode = TRAP;
141 trap_addr = 0;
142 }
143 if (hook_trap) (hook_trap)(this,trap_type,trap_mode,trap_addr);
144 if (next) next->trap(trap_type);
145 }
146
147 // mem_access() is called before memory is written and/or after
148 // memory is read. Note atomic instruction do both read and write.
149 void mem_access( MemAccess type, SS_Vaddr va, SS_Tte* tte, uint_t size, uint64_t* data )
150 {
151 if (hook_mem_access) (hook_mem_access)(this,type,va,tte,size,data);
152 if (next) next->mem_access(type,va,tte,size,data);
153 }
154
155 // asi_access is called after non translating asi is read/written
156 void asi_access( MemAccess type, uint8_t asi, SS_Vaddr va, uint64_t* data )
157 {
158 if (hook_asi_access) (hook_asi_access)(this,type,asi,va,data);
159 if (next) next->asi_access(type,asi,va,data);
160 }
161
162
163 // tlb_update() is called whenever a tte is inserted or removed from the
164 // tlb. The tte can not be cached. All values need need to be read in
165 // during the call tlb_update() call.
166 void tlb_update( bool insert, SS_Tlb* tlb, uint_t index, SS_Tte* tte )
167 {
168 if (hook_tlb_update) (hook_tlb_update)(this,insert,tlb,index,tte);
169 if (next) next->tlb_update(insert,tlb,index,tte);
170 }
171
172 // hwop() is called whenever a hw state machine access memory to
173 // to fetch tte from tsb.
174 void hwop( MemAccess type, SS_Paddr addr, uint_t size, uint64_t *value )
175 {
176 if (hook_hwop) (hook_hwop)(this,type, addr, size, value);
177 if (next) next->hwop(type, addr, size, value);
178 }
179
180
181
182 // end_instr() is called when all the above tracing interface calls
183 // have been made. Its can be used to for example the output trace record
184 // for an instruction.
185 void end_instr()
186 {
187 if (hook_end_instr) (hook_end_instr)(this);
188 if (next) next->end_instr();
189 }
190
191 void inst_trap( SS_Vaddr ea )
192 {
193 trap_mode = INST_TRAP;
194 trap_addr = ea;
195 if (next) next->inst_trap(ea);
196 }
197 void data_trap( SS_Vaddr ea )
198 {
199 trap_mode = DATA_TRAP;
200 trap_addr = ea;
201 if (next) next->data_trap(ea);
202 }
203
204 void cmp_state( SS_Registers::Index i, uint64_t v )
205 {
206 if (state[i] != v)
207 {
208 reg_value(i,v);
209 state[i] = v;
210 }
211 if (next) next->cmp_state(i,v);
212 }
213
214 TrapMode get_trap_mode() { return trap_mode; }
215
216 // ToDo: This state vector should really not be here.
217 uint64_t state[SS_Registers::INDEX_END - SS_Registers::INDEX_BEGIN];
218
219 protected:
220 TrapMode trap_mode;
221 SS_Vaddr trap_addr;
222};
223
224#endif