/* * ========== Copyright Header Begin ========================================== * * OpenSPARC T2 Processor File: SS_Python.i * 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_Node.h" #include "SS_Model.h" #include "SS_Registers.h" #include "SS_Strand.h" #include "SS_Io.h" #include "SS_Tte.h" #include "SS_SnapShot.h" #include "SS_PythonTracer.h" #include "SS_PythonAsiReg.h" #include "SS_AddressMap.h" #include "spix_sparc.h" /* val2ptr() converts an integer value back to proper pointer *\ \* that within the swig framework will get the right type. */ template Ptr* val2ptr( int64_t val ) { union { Ptr* ptr; #if defined(ARCH_V8) int32_t val; #elif (defined(ARCH_V9) || defined(ARCH_X64)) int64_t val; #else #error "Define ARCH=v9 or ARCH=v8plus or ARCH=amd64" #endif } u; u.val = val; return u.ptr; } %} typedef unsigned char uint8_t; typedef signed char int8_t; typedef unsigned short uint16_t; typedef signed short int16_t; typedef unsigned int uint32_t; typedef unsigned int uint_t; typedef signed int int32_t; #if (defined(ARCH_V9) || defined(ARCH_X64)) typedef unsigned long uint64_t; typedef signed long int64_t; #else #ifdef ARCH_V8 typedef unsigned long long uint64_t; typedef signed long long int64_t; #else #error "Define ARCH=v9 or ARCH=v8plus or ARCH=amd64" #endif #endif typedef int64_t SS_Vaddr; typedef uint64_t SS_Paddr; %typemap(python,in) PyObject *func { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "Need a callable object!"); return NULL; } $1 = $input; } /*============================================================================*\ * dis * \*============================================================================*/ %inline %{ /* ha144505: we need to stay away from having the uint32_t; it confuses SWIG */ char* dis( int64_t opc, uint64_t pc ) { uint32_t _opc = uint32_t(opc); static char buffer[256]; size_t n = spix_sparc_dis(buffer,256,spix_sparc_iop(SPIX_SPARC_V9,&_opc),&_opc,pc); buffer[n] = 0; return buffer; } %} /*============================================================================*\ * SS_Node * \*============================================================================*/ class SS_Node { public: const char* get_node_name(); }; /*============================================================================*\ * SS_Registers * \*============================================================================*/ class SS_Registers { public: enum Error { OK, NOT_AVAILABLE }; enum Index { INDEX_BEGIN, INDEX_END, ALIAS_BEGIN, ALIAS_END, PR_TT, PR_TPC, PR_TNPC, PR_TSTATE, HPR_HTSTATE }; static const char* get_name( Index ); }; /*============================================================================*\ * SS_BreakPoint * \*============================================================================*/ class SS_BreakPoint { public: typedef uint_t Ident; enum Error { OK, ID_UNKNOWN }; enum Break { ON_INST_VA, ON_INST_PA, ON_INST_WORD, ON_DATA_VA, ON_DATA_PA, ON_DATA_LOAD, ON_DATA_STORE, ON_TRAP, ON_RED_MODE }; %immutable; Break type; Ident id; bool enabled; SS_BreakPoint* next; uint64_t va; uint64_t pa; uint_t tt; %mutable; }; /*============================================================================*\ * SS_TrapInfo * \*============================================================================*/ class SS_TrapInfo { public: %immutable; uint_t trap_type; char* name; uint_t priority; %mutable; }; %inline %{ SS_TrapInfo* get_trap_info( uint_t tt ) { return &SS_Trap::table[tt]; } %} /*============================================================================*\ * SS_AsiMap * \*============================================================================*/ class SS_AsiMap { public: %extend { SS_AsiSpace* get( uint8_t asi ) { return &(self->operator[](asi)); } } }; /*============================================================================*\ * SS_AsiCtrReg * \*============================================================================*/ class SS_AsiCtrReg { public: SS_AsiCtrReg( const char* __name, uint64_t __mask_ro, uint64_t __mask_r1c, uint64_t __mask_rw, uint64_t __mask_w1c, uint64_t __init ); const char* name(); uint64_t get(); void set( uint64_t v ); void set_unmasked( uint64_t v ); static SS_AsiSpace::Error ld64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* data ); static SS_AsiSpace::Error st64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t data ); static SS_AsiSpace::Error rd64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* data ); static SS_AsiSpace::Error wr64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t data ); }; class SS_SharedAsiCtrReg : public SS_AsiCtrReg { public: SS_SharedAsiCtrReg( const char* __name, uint64_t __mask_ro, uint64_t __mask_r1c, uint64_t __mask_rw, uint64_t __mask_w1c, uint64_t __init ); int lock(); int unlock(); int trylock(); static SS_AsiSpace::Error ld64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* data ); static SS_AsiSpace::Error st64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t data ); static SS_AsiSpace::Error rd64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* data ); static SS_AsiSpace::Error wr64( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t data ); }; class SS_PythonAsiReg : public SS_AsiCtrReg { public: SS_PythonAsiReg(); void set_ld64( PyObject* func ); void clr_ld64(); void set_st64( PyObject* func ); void clr_st64(); void set_rd64( PyObject* func ); void clr_rd64(); void set_wr64( PyObject* func ); void clr_wr64(); }; /*============================================================================*\ * SS_AsiSpace * \*============================================================================*/ class SS_AsiSpace { public: enum Error { OK, NO_ASI, NO_READ, NO_WRITE }; typedef Error (*Read) ( SS_Node* obj, void* reg, SS_Strand* s, SS_Vaddr, uint64_t* data ); typedef Error (*Write)( SS_Node* obj, void* reg, SS_Strand* s, SS_Vaddr, uint64_t data ); %extend { void add( uint64_t lo, uint64_t hi, SS_Node* obj, void* reg, Read ld, Write st, Read rd, Write wr ) { self->add((SS_Vaddr)lo,(SS_Vaddr)hi,obj,reg,ld,st,rd,wr); } void add_state( SS_PythonAsiReg* reg, uint64_t va ) { self->add((SS_Vaddr)va,(SS_Vaddr)va,(SS_Node*)0,reg, &SS_PythonAsiReg::ld64,&SS_PythonAsiReg::st64, &SS_PythonAsiReg::rd64,&SS_PythonAsiReg::st64); } void add_space( SS_PythonAsiReg* reg, uint64_t lo, uint64_t hi ) { self->add((SS_Vaddr)lo,(SS_Vaddr)hi,(SS_Node*)0,reg, &SS_PythonAsiReg::ld64,&SS_PythonAsiReg::st64, &SS_PythonAsiReg::rd64,&SS_PythonAsiReg::st64); } } }; /*============================================================================*\ * SS_Access * \*============================================================================*/ class SS_Access { public: enum Type { LOAD, STORE, STP, SWAP, CAS, LDST }; }; /*============================================================================*\ * SS_Tracer * \*============================================================================*/ class SS_Tracer { public: enum TrapMode { TRAP, INST_TRAP, DATA_TRAP }; enum MemAccess { LD_CODE, ST_DATA, LD_DATA, ST_PART, ST_SWAP, LD_SWAP, ST_CAS, LD_CAS, ST_LDST, LD_LDST, FLUSH, PREFETCH }; }; /*============================================================================*\ * SS_PythonTracer * \*============================================================================*/ class SS_PythonTracer : public SS_Tracer { public: SS_PythonTracer(); void clr_exe_instr(); void set_exe_instr( PyObject* func ); void clr_reg_value(); void set_reg_value( PyObject* func ); void clr_trap(); void set_trap( PyObject* func ); void clr_mem_access(); void set_mem_access( PyObject* func ); void clr_tlb_update(); void set_tlb_update( PyObject* func ); void clr_end_instr(); void set_end_instr( PyObject* func ); }; /*============================================================================*\ * SS_Instr * \*============================================================================*/ %inline %{ /* ss_instr() is used when get an uint64_t value but need a proper SS_Tte python object pointer type */ SS_Instr* ss_instr( int64_t p ) { return val2ptr(p); } %} class SS_Instr { public: %extend { uint32_t get_opc() { return self->opc.get(); } } }; /*============================================================================*\ * SS_Strand * \*============================================================================*/ class SS_Strand { public: const char* get_node_name(); char* icache_info(uint64_t pa); char* icache_set(uint_t set); char* dcache_set(uint_t set); char* l2cache_set(uint_t set); char* l2cache_set(uint_t bank, uint_t set); %immutable; SS_Registers::Error reg_error; SS_AsiSpace::Error asi_error; %mutable; %extend { const char* get_state_name( SS_Registers::Index index ) { return (self->get_state_name)(self,index); } uint64_t get_reg( SS_Registers::Index index ) { uint64_t value; self->reg_error = (self->get_state)(self,index,&value); return value; } void set_reg( SS_Registers::Index index, uint64_t value ) { self->reg_error = (self->set_state)(self,index,value); } uint64_t get_reg_tl( uint64_t tl, SS_Registers::Index index ) { uint64_t value, save_tl; (self->get_state)(self,SS_Registers::PR_TL,&save_tl); (self->set_state)(self,SS_Registers::PR_TL,tl); self->reg_error = (self->get_state)(self,index,&value); (self->set_state)(self,SS_Registers::PR_TL,save_tl); return value; } void set_reg_tl( uint64_t tl, SS_Registers::Index index, uint64_t value ) { uint64_t save_tl; (self->get_state)(self,SS_Registers::PR_TL,&save_tl); (self->set_state)(self,SS_Registers::PR_TL,tl); self->reg_error = (self->set_state)(self,index,value); (self->set_state)(self,SS_Registers::PR_TL,save_tl); } uint64_t get_reg_gl( uint64_t gl, SS_Registers::Index index ) { uint64_t value, save_gl; (self->get_state)(self,SS_Registers::PR_GL,&save_gl); (self->set_state)(self,SS_Registers::PR_GL,gl); self->reg_error = (self->get_state)(self,index,&value); (self->set_state)(self,SS_Registers::PR_GL,save_gl); return value; } void set_reg_gl( uint64_t gl, SS_Registers::Index index, uint64_t value ) { uint64_t save_gl; (self->get_state)(self,SS_Registers::PR_GL,&save_gl); (self->set_state)(self,SS_Registers::PR_GL,gl); self->reg_error = (self->set_state)(self,index,value); (self->set_state)(self,SS_Registers::PR_GL,save_gl); } uint64_t get_reg_wp( uint64_t wp, SS_Registers::Index index ) { uint64_t value, save_wp; (self->get_state)(self,SS_Registers::PR_CWP,&save_wp); (self->set_state)(self,SS_Registers::PR_CWP,wp); self->reg_error = (self->get_state)(self,index,&value); (self->set_state)(self,SS_Registers::PR_CWP,save_wp); return value; } void set_reg_wp( uint64_t wp, SS_Registers::Index index, uint64_t value ) { uint64_t save_wp; (self->get_state)(self,SS_Registers::PR_CWP,&save_wp); (self->set_state)(self,SS_Registers::PR_CWP,wp); self->reg_error = (self->set_state)(self,index,value); (self->set_state)(self,SS_Registers::PR_CWP,save_wp); } uint64_t get_asi( uint8_t asi, uint64_t addr ) { uint64_t data; self->asi_error = self->asi_map.rd64(self,asi,SS_Vaddr(addr),&data); return data; } void set_asi( uint8_t asi, uint64_t addr, uint64_t data ) { self->asi_error = self->asi_map.wr64(self,asi,SS_Vaddr(addr),data); } } uint64_t run_step( uint64_t n ); uint64_t trc_step( uint64_t n ); void add_tracer( SS_Tracer* ); void del_tracer( SS_Tracer* ); %immutable; SS_BreakPoint* break_points; SS_BreakPoint* break_hit; %mutable; SS_BreakPoint::Ident break_on_trap( uint_t tt ); SS_BreakPoint::Ident break_on_red_mode(); SS_BreakPoint::Error break_enable( SS_BreakPoint::Ident id ); SS_BreakPoint::Error break_disable( SS_BreakPoint::Ident id ); SS_BreakPoint::Error break_delete( SS_BreakPoint::Ident id ); SS_AsiMap asi_map; // Wrap to avoid swig issues with int64_t %extend { SS_BreakPoint::Ident break_on_inst_va( uint64_t va ) { return self->break_on_inst_va(SS_Vaddr(va)); } SS_Paddr va2pa( uint64_t va ) { return self->va2pa(SS_Vaddr(va)); } SS_Paddr va2pa( uint64_t va, uint_t ctx ) { return self->va2pa(SS_Vaddr(va),ctx); } SS_Paddr va2pa( uint64_t va, uint_t ctx, uint_t pid ) { return self->va2pa(SS_Vaddr(va),ctx,pid); } SS_Paddr ra2pa( uint64_t ra ) { return self->ra2pa(SS_Vaddr(ra)); } SS_Paddr ra2pa( uint64_t ra, uint_t pid ) { return self->ra2pa(SS_Vaddr(ra),pid); } } }; /*============================================================================*\ * SS_Tte * \*============================================================================*/ %inline %{ /* ss_tte() is used when get an uint64_t value but need a proper SS_Tte python object pointer type */ SS_Tte* ss_tte( int64_t p ) { return val2ptr(p); } %} class SS_Tte { public: SS_Tte(); int p(); int x(); int w(); int nfo(); int ie(); int cp(); int cv(); int e(); int tag_parity_error(); int data_parity_error(); int valid_bit(); int real_bit(); uint8_t pid(); uint16_t context(); uint8_t page_size(); SS_Vaddr tag(); SS_Paddr taddr(); void p( int f ); void x( int f ); void w( int f ); void nfo( int f ); void ie( int f ); void cp( int f ); void cv( int f); void e( int f); void tag_parity_error( int f ); void data_parity_error( int f ); void valid_bit( int f ); void real_bit( int f ); void pid( uint8_t p ); void context( uint16_t c ); void page_size( uint8_t p ); void taddr( SS_Paddr t ); // Wrap to avoid swig issues with int64_t %extend { void tag( uint64_t t ) { self->tag(SS_Vaddr(t)); } SS_Paddr trans( uint64_t va ) { return self->trans(SS_Vaddr(va)); } bool match_real( uint64_t ra, uint_t pid ) { return self->match_real(SS_Vaddr(ra),pid); } bool match_virt( uint64_t va, uint64_t ctxt, uint_t pid ) { return self->match_virt(SS_Vaddr(va),ctxt,pid); } bool match_virt( uint64_t va, uint64_t ctxt0, uint64_t ctxt1, uint_t pid ) { return self->match_virt(SS_Vaddr(va),ctxt0,ctxt1,pid); } void insert_tsb_tte( uint16_t pid, uint64_t tag, uint64_t data, uint64_t addr ) { self->insert_tsb_tte(pid,tag,data,SS_Vaddr(addr)); } } }; /*============================================================================*\ * SS_Tlb * \*============================================================================*/ %inline %{ /* ss_tlb() is used when get an uint64_t value but need a proper SS_Tlb python object pointer type */ SS_Tlb* ss_tlb( uint64_t p ) { return val2ptr(p); } %} class SS_Tlb { public: uint_t tlb_id(); bool is_inst_tlb(); bool is_data_tlb(); uint_t size(); SS_Tte* get( uint_t index ); void set( uint_t index, SS_Tte* tte ); void flush( SS_Tte* tte ); int next_valid_index( int ); }; /*============================================================================*\ * SS_SnapShot * \*============================================================================*/ class SS_SnapShot { public: SS_SnapShot( FILE* f, bool _load ); }; /*============================================================================*\ * SS_AddressMap * \*============================================================================*/ class SS_AddressMap { public: }; %inline %{ SS_Io* get_io() { return &SS_Io::io; } %} class SS_Io : public SS_AddressMap { public: void poke8( uint_t sid,uint64_t addr, uint8_t data ); void poke16( uint_t sid,uint64_t addr, uint16_t data ); %extend { /* python 2.4 became pedantic about int values with signbit set, this avoids the nagging */ void poke32( uint_t sid, int64_t addr, uint64_t data ) { self->poke32(sid,addr,uint32_t(data)); } } void poke64( uint_t sid, uint64_t addr, uint64_t data ); uint8_t peek8u ( uint_t sid, uint64_t addr ); int8_t peek8s ( uint_t sid, uint64_t addr ); uint16_t peek16u( uint_t sid, uint64_t addr ); int16_t peek16s( uint_t sid, uint64_t addr ); uint32_t peek32u( uint_t sid, uint64_t addr ); int32_t peek32s( uint_t sid, uint64_t addr ); uint64_t peek64 ( uint_t sid, uint64_t addr ); }; class SS_Model { public: uint_t cpu_cnt(); void flush( SS_Paddr pa ); void snapshot( SS_SnapShot& ss ); %extend { void ras_enable( ) { self->ras_enable(0); } } void ras_enable( char* cmd ); };