Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / pfe / src / SS_Python.i
/*
* ========== 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<class Ptr>
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<SS_Instr>(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<SS_Tte>(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<SS_Tlb>(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 );
};