// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: py_interface.cc
// 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 ============================================
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2006 Sun Microsystems, Inc.
// implementation file for python user interface
/* standard C includes */
// must be before other includes
#include <sys/resource.h>
#include "blaze_globals.h"
#include "ui_cmd_struct.h"
// declarations from ui_cmds.cc
extern Ui_cmd ui_cmd_list
[];
extern void UI_register_cmd_2 (char * name
, char *help
, int (*efn
)(void *, int, char **), int (*hfn
)());
extern void UI_invalidate_cmd (char * name
);
extern int sstep_cmd (int vcpu_id
);
extern uint32_t BLAZE_restore_from_checkpoint();
extern int exec_cmd(char *s
);
// ui does not accept command which length exceeds
// max_cmd_length param defined in ui_cmds.cc
const int max_cmd_line_size
= 2048;
static void *py_lib_handle
= NULL
;
// map for new command registered from py module
std::map
<std::string
,PyObject
*> *py_cmd_map
= NULL
;
static PyObject
* pyCBdelfn
= 0;
static PyObject
* pyCBaddfn
= 0;
// the externally callable interface function from SAM UI
typedef void (*Py_Intf_fn
)(const char *);
extern Py_Intf_fn addPycmd
;
extern Py_Intf_fn delPycmd
;
void delPyUI(const char * n
){
PyObject
* args
= Py_BuildValue((char*)"(s)",n
);
rslt
= PyEval_CallObject(pyCBdelfn
,args
);
printf("ERROR: could not delete %s\n",n
);
void addPyUI(const char * n
){
Ui_cmd
* next
= &ui_cmd_list
[0];
if(!strcmp(n
,next
->name
))
PyObject
* arg
= Py_BuildValue((char*)"(ss)",next
->help
,n
);
rslt
= PyEval_CallObject(pyCBaddfn
,arg
);
printf("ERROR: could not add %s\n",n
);
// send command string to build-in ui interpreter
extern "C" PyObject
* sam_exec( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"s",&cmd
))
// Don't need to mutex exec_cmd() here as python can only be
// executed from the ui which means we should already hold
// the mutex ui_thread_lock (see ui_cmds.cc)
return Py_BuildValue("");
static inline char *stradd(char *s1
, char *s2
, int len
=0)
if (!len
) len
= strlen(s2
);
// send command to py interpreter
int exec_py_cmd(void * /* usrdata */, int argc
, char **argv
)
if (!IN_STOP_STATE (blaze_run_state
))
fprintf(stderr
, "ERROR: not in stop state, use stop command first\n");
// check if command was registered before
PyObject
*py_cmd_fn
= py_cmd_map
->find(argv
[0])->second
;
fprintf(stderr
, "unknown py command %s\n", argv
[0]);
PyObject
* arg
= PyTuple_New(argc
);
for (int i
=0; i
<argc
; i
++)
PyTuple_SetItem(arg
, i
, PyString_FromString(argv
[i
]));
PyObject
* rslt
= PyEval_CallObject(py_cmd_fn
,arg
);
// register a new py command with ui
extern "C" PyObject
* sam_register( PyObject
* self
, PyObject
* args
)
char *cmd_name
, *help_str
;
// get command name, help string and a pointer to py command routine
if (!PyArg_ParseTuple(args
,(char*)"ssO:sam_register",&cmd_name
, &help_str
,&py_command_fn
))
if (!PyCallable_Check(py_command_fn
))
PyErr_SetString(PyExc_TypeError
, "parameter must be callable");
Py_XINCREF(py_command_fn
);
if (!py_cmd_map
) // keep map for new py commands
py_cmd_map
= new std::map
<std::string
,PyObject
*>;
if (py_cmd_map
->find(cmd_name
) == py_cmd_map
->end())
py_cmd_map
->insert(std::pair
<std::string
,PyObject
*>(cmd_name
,py_command_fn
));
UI_register_cmd_2(cmd_name
, help_str
, exec_py_cmd
, NULL
);
fprintf(stderr
, "ERROR: cannot register a new command, %s command exist already \n",cmd_name
);
return Py_BuildValue("");
extern "C" PyObject
* sam_unregister( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"s",&cmd_name
))
if (py_cmd_map
&& cmd_name
) // check new py commands
if (py_cmd_map
->erase(cmd_name
))
// unregister the command
UI_invalidate_cmd (cmd_name
);
ui
->verbose("command %s, was removed\n", cmd_name
);
fprintf(stderr
, "ERROR: cannot unregister command %s \n", cmd_name
);
return Py_BuildValue("");
extern "C" uint_t
vcpu_get_sys_type();
extern "C" uint_t
vcpu_get_sys_size();
extern "C" void* vcpu_get_sys_pntr( uint_t i
);
extern "C" PyObject
* vcpu_sys_type( PyObject
* self
, PyObject
* args
)
type
= vcpu_get_sys_type();
return Py_BuildValue((char*)"i", type
);
extern "C" PyObject
* vcpu_sys_size( PyObject
* self
, PyObject
* args
)
size
= vcpu_get_sys_size();
return Py_BuildValue((char*)"i", size
);
extern "C" PyObject
* set_cmd_del_fn( PyObject
* self
, PyObject
* args
)
if(PyArg_ParseTuple(args
,"O:set_cmd_del_fn",&pyCBdelfn
)){
if (!PyCallable_Check(pyCBdelfn
)){
PyErr_SetString(PyExc_TypeError
, "parameter must be callable");
extern "C" PyObject
* set_cmd_add_fn( PyObject
* self
, PyObject
* args
)
if(PyArg_ParseTuple(args
,"O:set_cmd_add_fn",&pyCBaddfn
)){
if (!PyCallable_Check(pyCBaddfn
)){
PyErr_SetString(PyExc_TypeError
, "parameter must be callable");
extern "C" PyObject
* vcpu_sys_pntr( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"i",&i
))
sysp
= (uint64_t)vcpu_get_sys_pntr(i
);
return Py_BuildValue((char*)"l", sysp
);
extern "C" PyObject
* mem_ld64( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"l",&addr
))
addr
&= ~uint64_t(7); // align
return PyLong_FromUnsignedLong(data
);
extern "C" PyObject
* mem_st64( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"ll",&addr
,&data
))
addr
&= ~uint64_t(7); // align
return Py_BuildValue((char*)"");
extern "C" PyObject
* mem_ld32( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"l",&addr
))
addr
&= ~uint64_t(3); // align
return Py_BuildValue((char*)"l",data
);
extern "C" PyObject
* mem_st32( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"ll",&addr
,&data
))
addr
&= ~uint64_t(3); // align
return Py_BuildValue((char*)"");
extern "C" PyObject
* mem_ld16( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"l",&addr
))
addr
&= ~uint64_t(1); // align
return Py_BuildValue((char*)"l",data
);
extern "C" PyObject
* mem_st16( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"ll",&addr
,&data
))
addr
&= ~uint64_t(1); // align
return Py_BuildValue((char*)"");
extern "C" PyObject
* mem_ld8( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"l",&addr
))
return Py_BuildValue((char*)"l",data
);
extern "C" PyObject
* mem_st8( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"ll",&addr
,&data
))
return Py_BuildValue((char*)"");
extern "C" PyObject
* is_stopped( PyObject
* self
, PyObject
* args
)
bool_t stop
= SYSTEM_is_stopped();
if (!PyArg_ParseTuple(args
,(char*)""))
return Py_BuildValue((char*)"i",stop
);
extern "C" PyObject
* is_restored_simulation( PyObject
* self
, PyObject
* args
)
bool_t restore
= BLAZE_restore_from_checkpoint();
if (!PyArg_ParseTuple(args
,(char*)""))
return Py_BuildValue((char*)"i",restore
);
// methods used to run verification diags
extern "C" PyObject
* s_step( PyObject
* self
, PyObject
* args
)
if (!PyArg_ParseTuple(args
,(char*)"i",&vcpu_id
))
uint_t done
= sstep_cmd(vcpu_id
);
return Py_BuildValue((char*)"i",done
);
extern "C" PyObject
* get_cmd_dict( PyObject
* self
, PyObject
* args
)
const int bufSize
= 64 * 1024; // largest possible string - no error checks ahead!!!
// create a dictionary of {cmd_name:definition}
Ui_cmd
* next
= &ui_cmd_list
[0];
// build the python dictionary
PyObject
* pyDict
= Py_BuildValue((char*)"{s:s}","","");
// Force use of _ iso - or . for example
char * cmd_name
= strdup(next
->name
);
for(int i
= 0; i
< strlen(cmd_name
); i
++)
if(!isalnum(cmd_name
[i
]))
// special case the SAM break command as it is a python keyword
if(!strcmp(cmd_name
,"break")){
cmd_name
= strdup("brk");
sprintf(buf2
,"def sam_%s(args=\"\"):\n",cmd_name
);
sprintf(buf2
+ strlen(buf2
)," \"\"\"%s\n \"\"\"\n",next
->help
);
sprintf(buf2
+ strlen(buf2
)," sam.ui_exec(\"%s \" + args)\n\n",next
->name
);
PyObject
* pyStr
= Py_BuildValue((char*)"s",buf2
);
PyMapping_SetItemString(pyDict
,cmd_name
,pyStr
);
static PyMethodDef py_methods
[] =
{"ui_exec", sam_exec
, METH_VARARGS
, "ui_exec <cmd>\n"},
{"ui_register", sam_register
, METH_VARARGS
, "ui_register (cmd_name, help_str,cmd_func)\n"},
{"ui_unregister", sam_unregister
, METH_VARARGS
, "ui_unregister (cmd_name)\n"},
{"sys_type", vcpu_sys_type
, METH_VARARGS
, "vcpu_sys_type <>\n"},
{"sys_size", vcpu_sys_size
, METH_VARARGS
, "vcpu_sys_size <>\n"},
{"sys_pntr", vcpu_sys_pntr
, METH_VARARGS
, "vcpu_sys_pntr <i>\n"},
{"mem_ld64", mem_ld64
, METH_VARARGS
, "mem_ld64(addr)\n"},
{"mem_st64", mem_st64
, METH_VARARGS
, "mem_st64(addr,data)\n"},
{"mem_ld32", mem_ld32
, METH_VARARGS
, "mem_ld32(addr)\n"},
{"mem_st32", mem_st32
, METH_VARARGS
, "mem_st32(addr,data)\n"},
{"mem_ld16", mem_ld16
, METH_VARARGS
, "mem_ld16(addr)\n"},
{"mem_st16", mem_st16
, METH_VARARGS
, "mem_st16(addr,data)\n"},
{"mem_ld8", mem_ld8
, METH_VARARGS
, "mem_ld8(addr)\n"},
{"mem_st8", mem_st8
, METH_VARARGS
, "mem_st8(addr,data)\n"},
{"is_stopped", is_stopped
, METH_VARARGS
, "is_stopped()\n"},
{"is_restored_simulation", is_restored_simulation
, METH_VARARGS
, "is_restored_simulation()\n"},
{"sstep", s_step
, METH_VARARGS
, "sstep(vcpu_id)\n"},
{"get_cmd_dict", get_cmd_dict
, METH_VARARGS
, "get_cmd_dict()\n"},
{"set_cmd_del_fn", set_cmd_del_fn
, METH_VARARGS
, "set_cmd_del_fn(Fn)\n"},
{"set_cmd_add_fn", set_cmd_add_fn
, METH_VARARGS
, "set_cmd_add_fn(Fn)\n"},
{0, 0, 0, 0} // end of the list
////////////////////////////////////////////////////////////////
extern int (*py_source
)( int argc
, char** argv
);
int py_source_cmd( int argc
, char **argv
)
ui
->verbose("loading py module %s...\n", argv
[0]);
char cmd
[max_cmd_line_size
];
s
=stradd(s
,"execfile(\"");
char* filename
= argv
[0];
if (strncmp(filename
,"$SAM/",5) == 0)
// replace $SAM with dir path
s
=stradd(s
,&filename
[4]);
if (stat(filename
, &sfile
))
fprintf(stderr
, "ERROR: %s : No such file or directory\n", filename
);
if ((sfile
.st_mode
& (S_IRUSR
| S_IRGRP
| S_IROTH
)) == 0)
fprintf(stderr
, "ERROR: %s : file is not readable \n", filename
);
ui
->verbose("%s\n", cmd
);
// set pythons sys.argv to arguments of py_source
PySys_SetArgv(argc
,argv
);
/////////////////////////////////////////////////////////////////
// start py user interface
extern void setenv_pythonhome(); // Defined in pythonhome.cc
extern "C" int init_py_interface(char* fname
, char* modname
, void* lib_handle
)
if (py_lib_handle
!= NULL
)
ui
->error("py lib was loaded already. \n" );
py_lib_handle
= lib_handle
;
fprintf (stderr
, "cannot obtain py lib handle\n" );
// set PYTHONPATH to the known python directories in our
const char* env_var
= "PYTHONPATH=";
const char* pfe_dir
= "/pfe";
const char* sam
= getexecname();
// Do we expect getexecname() to fail ... geeesh that would be
// a disaster if $0 is blank. In case it is just assume sam.
// Expect that sam was executed from our release. So expect
// $sam_dir/bin/sam and grab $sam_dir. If not then things have
// been moved around ... well though.
char* origin
= dirname(strdup(sam
));
sam_dir
= dirname(strdup(origin
));
size_t len
= strlen(env_var
) + strlen(sam_dir
) + strlen(pfe_dir
);
// Before setting PYTHONPATH, check if one is set already and prepend
// our paths to it. Otherwise assume PYTHONPATH was '.'
char* pythonpath
= getenv(env_var
);
str
= (char*)malloc(len
+ strlen(pythonpath
) + 2);
sprintf(str
,"%s%s%s:%s",env_var
,sam_dir
,pfe_dir
,pythonpath
);
if ( !Py_IsInitialized() )
Py_InitModule((char*)"sam", py_methods
);
// The "run-python-file" ui command needs this py_source
py_source
= py_source_cmd
;
extern "C" int close_py_interface()
// when return back to sam ui don't call this method
// during the session otherwise sam ui hangs;
if ( Py_IsInitialized() )