* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: SS_Tracer.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
#include "SS_Registers.h"
ST_PART
= 0x04, // data[0] = rd, data[1] = bytemask
ST_SWAP
= 0x05, // data[0] = rd
LD_SWAP
= 0x07, // data[0] = rd
ST_CAS
= 0x08, // data[0] = rd, data[1] = rs2
LD_CAS
= 0x09, // data[0] = rd
ST_LDST
= 0x0a, // data[0] = store value (ldstub stores 0xff)
LD_LDST
= 0x0b, // data[0] = rd
FLUSH
= 0x10, // data == 0 in mem_access call
PREFETCH
= 0x11 // data == 0 in mem_access call
static int is_fetch( MemAccess ma
) { return ma
== LD_CODE
; }
static int is_load( MemAccess ma
) { return (ma
& 1) == 1; }
static int is_store( MemAccess ma
) { return (ma
& 1) == 0; }
static int is_cohere( MemAccess ma
) { return (ma
& 0x10) == 0x10; }
memset(state
,0,sizeof(state
));
void (*hook_exe_instr
) ( SS_Tracer
*, SS_Vaddr pc
, SS_Tte
* tte
, SS_Instr
* i
);
void (*hook_reg_value
) ( SS_Tracer
*, SS_Registers::Index index
, uint64_t value
);
void (*hook_trap
) ( SS_Tracer
*, SS_Trap::Type tt
, TrapMode mode
, SS_Vaddr ea
);
void (*hook_mem_access
)( SS_Tracer
*, MemAccess
, SS_Vaddr
, SS_Tte
*, uint_t size
, uint64_t* data
);
void (*hook_asi_access
)( SS_Tracer
*, MemAccess
, uint8_t asi
, SS_Vaddr
, uint64_t* data
);
void (*hook_tlb_update
)( SS_Tracer
*, bool insert
, SS_Tlb
* tlb
, uint_t index
, SS_Tte
* tte
);
void (*hook_hwop
) ( SS_Tracer
*, MemAccess type
, SS_Paddr addr
, uint_t size
, uint64_t *value
);
void (*hook_end_instr
) ( SS_Tracer
* );
SS_Tracer
* next
; // There can be more then one tracer per strand
return next
->need_mem_trc();
// exe_instr() is called for every instruction to trace its
// virtual pc, physical pc and the instruction word executed.
void exe_instr( SS_Vaddr pc
, SS_Tte
* tte
, SS_Instr
* i
)
if (hook_exe_instr
) (hook_exe_instr
)(this,pc
,tte
,i
);
if (next
) next
->exe_instr(pc
,tte
,i
);
// reg_value() is called for each register that changed value as a
// result of executing an instruction. Note that this is a template
// function to allow for product spefic SS_Registers::Index extensions.
// The given index is casted to SS_Register::Index.
void reg_value( Index index
, uint64_t value
)
if (hook_reg_value
) (hook_reg_value
)(this,SS_Registers::Index(index
),value
);
if (next
) next
->reg_value(SS_Registers::Index(index
),value
);
// trap() is called to trace trapping
void trap( SS_Trap::Type trap_type
)
// in cosim mode, there are likely two (or more) SS_Tracer objects are
// registered (i.e., linked by 'next' field) for each strand. When a trap
// occurres, we have to traverse through all of them to perform each
// object's own trace function. If a trap is a mmu trap, then an
// inst_trap() or data_trap() will be called before the trap() is called,
// since inst_trap() and data_trap() may deposit more specific
// trap_mode and trap_addr information, we should not overwrite those
if (trap_mode
== NO_TRAP
)
if (hook_trap
) (hook_trap
)(this,trap_type
,trap_mode
,trap_addr
);
if (next
) next
->trap(trap_type
);
// mem_access() is called before memory is written and/or after
// memory is read. Note atomic instruction do both read and write.
void mem_access( MemAccess type
, SS_Vaddr va
, SS_Tte
* tte
, uint_t size
, uint64_t* data
)
if (hook_mem_access
) (hook_mem_access
)(this,type
,va
,tte
,size
,data
);
if (next
) next
->mem_access(type
,va
,tte
,size
,data
);
// asi_access is called after non translating asi is read/written
void asi_access( MemAccess type
, uint8_t asi
, SS_Vaddr va
, uint64_t* data
)
if (hook_asi_access
) (hook_asi_access
)(this,type
,asi
,va
,data
);
if (next
) next
->asi_access(type
,asi
,va
,data
);
// tlb_update() is called whenever a tte is inserted or removed from the
// tlb. The tte can not be cached. All values need need to be read in
// during the call tlb_update() call.
void tlb_update( bool insert
, SS_Tlb
* tlb
, uint_t index
, SS_Tte
* tte
)
if (hook_tlb_update
) (hook_tlb_update
)(this,insert
,tlb
,index
,tte
);
if (next
) next
->tlb_update(insert
,tlb
,index
,tte
);
// hwop() is called whenever a hw state machine access memory to
// to fetch tte from tsb.
void hwop( MemAccess type
, SS_Paddr addr
, uint_t size
, uint64_t *value
)
if (hook_hwop
) (hook_hwop
)(this,type
, addr
, size
, value
);
if (next
) next
->hwop(type
, addr
, size
, value
);
// end_instr() is called when all the above tracing interface calls
// have been made. Its can be used to for example the output trace record
if (hook_end_instr
) (hook_end_instr
)(this);
if (next
) next
->end_instr();
void inst_trap( SS_Vaddr ea
)
if (next
) next
->inst_trap(ea
);
void data_trap( SS_Vaddr ea
)
if (next
) next
->data_trap(ea
);
void cmp_state( SS_Registers::Index i
, uint64_t v
)
if (next
) next
->cmp_state(i
,v
);
TrapMode
get_trap_mode() { return trap_mode
; }
// ToDo: This state vector should really not be here.
uint64_t state
[SS_Registers::INDEX_END
- SS_Registers::INDEX_BEGIN
];