Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / py / py_interface.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: py_interface.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/////////////////////////////////////////////////////////////////////////
22//
23// Copyright (C) 2006 Sun Microsystems, Inc.
24// All rights reserved.
25//
26
27// py_interface.cc
28//
29// implementation file for python user interface
30
31/* standard C includes */
32
33
34// must be before other includes
35#include "Python.h"
36#include "abstract.h"
37
38#include <stdio.h>
39#include <thread.h>
40#include <stdlib.h>
41#include <string.h>
42#include <assert.h>
43#include <stdio.h>
44#include <unistd.h>
45#include <ctype.h>
46#include <libgen.h>
47
48/* solaris includes */
49#include <signal.h>
50#include <sys/types.h>
51#include <sys/exec.h>
52#include <sys/stat.h>
53#include <sys/time.h>
54#include <sys/resource.h>
55#include <sys/procfs.h>
56#include <sys/socket.h>
57#include <netinet/in.h>
58#include <arpa/inet.h>
59#include <fcntl.h>
60#include <netdb.h>
61#include <stropts.h>
62
63#include <dlfcn.h>
64#include <map>
65
66#include "types.h"
67#include "blaze_globals.h"
68#include "system.h"
69#include "mem.h"
70
71#include "ui.h"
72#include "ui_cmd_struct.h"
73
74
75// declarations from ui_cmds.cc
76extern Ui_cmd ui_cmd_list[];
77extern void UI_register_cmd_2 (char * name, char *help, int (*efn)(void *, int, char **), int (*hfn)());
78extern void UI_invalidate_cmd (char * name);
79extern int sstep_cmd (int vcpu_id);
80extern uint32_t BLAZE_restore_from_checkpoint();
81extern int exec_cmd(char *s);
82
83// ui does not accept command which length exceeds
84// max_cmd_length param defined in ui_cmds.cc
85const int max_cmd_line_size = 2048;
86
87
88// globals
89static void *py_lib_handle = NULL;
90char *sam_dir = NULL;
91
92// map for new command registered from py module
93std::map<std::string,PyObject*> *py_cmd_map = NULL;
94
95
96static PyObject * pyCBdelfn = 0;
97static PyObject * pyCBaddfn = 0;
98
99// the externally callable interface function from SAM UI
100typedef void (*Py_Intf_fn)(const char *);
101extern Py_Intf_fn addPycmd;
102extern Py_Intf_fn delPycmd;
103
104void delPyUI(const char * n){
105 PyObject * rslt;
106 PyObject * args = Py_BuildValue((char*)"(s)",n);
107 if(pyCBdelfn)
108 rslt = PyEval_CallObject(pyCBdelfn,args);
109 Py_DECREF(args);
110
111 if(rslt)
112 Py_DECREF(rslt);
113 else
114 printf("ERROR: could not delete %s\n",n);
115 return;
116}
117
118void addPyUI(const char * n){
119 Ui_cmd * next = &ui_cmd_list[0];
120
121 while(next){
122 if(!strcmp(n,next->name))
123 break;
124 next = next->next;
125 }
126
127 if(!next)
128 assert(0);
129
130 PyObject * arg = Py_BuildValue((char*)"(ss)",next->help,n);
131 PyObject * rslt = 0;
132 if(pyCBaddfn)
133 rslt = PyEval_CallObject(pyCBaddfn,arg);
134
135 Py_DECREF(arg);
136 if (rslt)
137 Py_DECREF(rslt);
138 else
139 printf("ERROR: could not add %s\n",n);
140
141 return;
142}
143
144// send command string to build-in ui interpreter
145extern "C" PyObject* sam_exec( PyObject* self, PyObject* args )
146{
147 char *cmd;
148 char rsp[2];
149
150 if (!PyArg_ParseTuple(args,(char*)"s",&cmd))
151 return 0;
152
153 // Don't need to mutex exec_cmd() here as python can only be
154 // executed from the ui which means we should already hold
155 // the mutex ui_thread_lock (see ui_cmds.cc)
156
157 exec_cmd( cmd );
158
159 return Py_BuildValue("");
160}
161
162// add string s2 to s1
163static inline char *stradd(char *s1, char *s2, int len=0)
164{
165 if (!len) len = strlen(s2);
166 strncpy(s1,s2,len);
167 return s1+len;
168}
169
170// send command to py interpreter
171int exec_py_cmd(void * /* usrdata */, int argc, char **argv)
172{
173 if (!IN_STOP_STATE (blaze_run_state))
174 {
175 fprintf(stderr, "ERROR: not in stop state, use stop command first\n");
176 return 0;
177 }
178
179 // check if command was registered before
180 PyObject *py_cmd_fn = py_cmd_map->find(argv[0])->second;
181
182 if(!py_cmd_fn)
183 {
184 fprintf(stderr, "unknown py command %s\n", argv[0]);
185 return 0;
186 }
187
188 // build arguments
189 PyObject * arg = PyTuple_New(argc);
190 for (int i=0; i<argc; i++)
191 PyTuple_SetItem(arg, i, PyString_FromString(argv[i]));
192
193 // call py routine
194 PyObject * rslt = PyEval_CallObject(py_cmd_fn,arg);
195
196 Py_DECREF(arg);
197 if (rslt)
198 Py_DECREF(rslt);
199
200 return 1;
201}
202
203// register a new py command with ui
204extern "C" PyObject* sam_register( PyObject* self, PyObject* args )
205{
206 char *cmd_name, *help_str;
207 PyObject *py_command_fn;
208
209 // get command name, help string and a pointer to py command routine
210 if (!PyArg_ParseTuple(args,(char*)"ssO:sam_register",&cmd_name, &help_str,&py_command_fn))
211 return 0;
212
213 if (!PyCallable_Check(py_command_fn))
214 {
215 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
216 return 0;
217 }
218
219 Py_XINCREF(py_command_fn);
220
221
222 // register new command
223 if (!py_cmd_map) // keep map for new py commands
224 {
225 py_cmd_map = new std::map<std::string,PyObject*>;
226 }
227 if (py_cmd_map->find(cmd_name) == py_cmd_map->end())
228 {
229 py_cmd_map->insert(std::pair<std::string,PyObject *>(cmd_name,py_command_fn));
230 UI_register_cmd_2(cmd_name, help_str, exec_py_cmd, NULL);
231 }
232 else
233 {
234 fprintf(stderr, "ERROR: cannot register a new command, %s command exist already \n",cmd_name);
235 }
236
237
238 return Py_BuildValue("");
239}
240
241
242// unregister ui command
243extern "C" PyObject* sam_unregister( PyObject* self, PyObject* args )
244{
245 char *cmd_name;
246
247 // get command name
248 if (!PyArg_ParseTuple(args,(char*)"s",&cmd_name))
249 return 0;
250
251 if (py_cmd_map && cmd_name) // check new py commands
252 {
253 if (py_cmd_map->erase(cmd_name))
254 {
255 // unregister the command
256 UI_invalidate_cmd (cmd_name);
257 ui->verbose("command %s, was removed\n", cmd_name);
258 }
259 else
260 {
261 fprintf(stderr, "ERROR: cannot unregister command %s \n", cmd_name);
262 }
263 }
264
265 return Py_BuildValue("");
266}
267
268
269extern "C" uint_t vcpu_get_sys_type();
270extern "C" uint_t vcpu_get_sys_size();
271extern "C" void* vcpu_get_sys_pntr( uint_t i );
272
273
274extern "C" PyObject* vcpu_sys_type( PyObject* self, PyObject* args )
275{
276 uint_t type;
277
278 type = vcpu_get_sys_type();
279
280 return Py_BuildValue((char*)"i", type);
281}
282
283
284extern "C" PyObject* vcpu_sys_size( PyObject* self, PyObject* args )
285{
286 uint_t size;
287
288 size = vcpu_get_sys_size();
289
290 return Py_BuildValue((char*)"i", size);
291}
292
293
294
295extern "C" PyObject* set_cmd_del_fn( PyObject* self, PyObject* args )
296{
297 PyObject *result = 0;
298 if(PyArg_ParseTuple(args,"O:set_cmd_del_fn",&pyCBdelfn)){
299 if (!PyCallable_Check(pyCBdelfn)){
300 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
301 return 0;
302 }
303 Py_XINCREF(pyCBdelfn);
304 Py_INCREF(Py_None);
305 result = Py_None;
306 delPycmd = delPyUI;
307 }
308
309 return result;
310}
311
312extern "C" PyObject* set_cmd_add_fn( PyObject* self, PyObject* args )
313{
314 PyObject *result = 0;
315 if(PyArg_ParseTuple(args,"O:set_cmd_add_fn",&pyCBaddfn)){
316 if (!PyCallable_Check(pyCBaddfn)){
317 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
318 return 0;
319 }
320 Py_XINCREF(pyCBaddfn);
321 Py_INCREF(Py_None);
322 result = Py_None;
323 addPycmd = addPyUI;
324 }
325 return result;
326}
327
328
329extern "C" PyObject* vcpu_sys_pntr( PyObject* self, PyObject* args )
330{
331 uint_t i;
332 uint64_t sysp;
333
334 if (!PyArg_ParseTuple(args,(char*)"i",&i))
335 return 0;
336
337 sysp = (uint64_t)vcpu_get_sys_pntr(i);
338
339 return Py_BuildValue((char*)"l", sysp);
340}
341
342extern "C" PyObject* mem_ld64( PyObject* self, PyObject* args )
343{
344 uint64_t addr, data;
345 if (!PyArg_ParseTuple(args,(char*)"l",&addr))
346 return 0;
347 addr &= ~uint64_t(7); // align
348 data = mm1->ld64(addr);
349 return PyLong_FromUnsignedLong(data);
350}
351
352
353extern "C" PyObject* mem_st64( PyObject* self, PyObject* args )
354{
355 uint64_t addr, data;
356 if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data))
357 return 0;
358 addr &= ~uint64_t(7); // align
359 mm1->st64(addr,data);
360 return Py_BuildValue((char*)"");
361}
362
363extern "C" PyObject* mem_ld32( PyObject* self, PyObject* args )
364{
365 uint64_t addr, data;
366 if (!PyArg_ParseTuple(args,(char*)"l",&addr))
367 return 0;
368 addr &= ~uint64_t(3); // align
369 data = mm1->ld32u(addr);
370 return Py_BuildValue((char*)"l",data);
371}
372
373
374extern "C" PyObject* mem_st32( PyObject* self, PyObject* args )
375{
376 uint64_t addr, data;
377 if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data))
378 return 0;
379 addr &= ~uint64_t(3); // align
380 mm1->st32(addr,data);
381 return Py_BuildValue((char*)"");
382}
383
384extern "C" PyObject* mem_ld16( PyObject* self, PyObject* args )
385{
386 uint64_t addr, data;
387 if (!PyArg_ParseTuple(args,(char*)"l",&addr))
388 return 0;
389 addr &= ~uint64_t(1); // align
390 data = mm1->ld16u(addr);
391 return Py_BuildValue((char*)"l",data);
392}
393
394
395extern "C" PyObject* mem_st16( PyObject* self, PyObject* args )
396{
397 uint64_t addr, data;
398 if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data))
399 return 0;
400 addr &= ~uint64_t(1); // align
401 mm1->st16(addr,data);
402 return Py_BuildValue((char*)"");
403}
404
405extern "C" PyObject* mem_ld8( PyObject* self, PyObject* args )
406{
407 uint64_t addr, data;
408 if (!PyArg_ParseTuple(args,(char*)"l",&addr))
409 return 0;
410 data = mm1->ld8u(addr);
411 return Py_BuildValue((char*)"l",data);
412}
413
414
415extern "C" PyObject* mem_st8( PyObject* self, PyObject* args )
416{
417 uint64_t addr, data;
418 if (!PyArg_ParseTuple(args,(char*)"ll",&addr,&data))
419 return 0;
420 mm1->st8(addr,data);
421 return Py_BuildValue((char*)"");
422}
423
424extern "C" PyObject* is_stopped( PyObject* self, PyObject* args )
425{
426 bool_t stop = SYSTEM_is_stopped();
427 if (!PyArg_ParseTuple(args,(char*)""))
428 return 0;
429 return Py_BuildValue((char*)"i",stop);
430}
431
432extern "C" PyObject* is_restored_simulation( PyObject* self, PyObject* args )
433{
434 bool_t restore = BLAZE_restore_from_checkpoint();
435 if (!PyArg_ParseTuple(args,(char*)""))
436 return 0;
437 return Py_BuildValue((char*)"i",restore);
438}
439
440
441
442// methods used to run verification diags
443extern "C" PyObject* s_step( PyObject* self, PyObject* args )
444{
445 uint_t vcpu_id;
446
447 if (!PyArg_ParseTuple(args,(char*)"i",&vcpu_id))
448 return 0;
449
450 uint_t done = sstep_cmd(vcpu_id);
451
452 return Py_BuildValue((char*)"i",done);
453}
454
455
456extern "C" PyObject* get_cmd_dict( PyObject* self, PyObject* args )
457{
458 const int bufSize = 64 * 1024; // largest possible string - no error checks ahead!!!
459 char buf2[bufSize];
460
461 buf2[0] = 0;
462
463 // create a dictionary of {cmd_name:definition}
464
465 Ui_cmd * next = &ui_cmd_list[0];
466 // build the python dictionary
467 PyObject* pyDict = Py_BuildValue((char*)"{s:s}","","");
468
469 while(next){
470 // Force use of _ iso - or . for example
471 char * cmd_name = strdup(next->name);
472 for(int i = 0; i < strlen(cmd_name); i++)
473 if(!isalnum(cmd_name[i]))
474 cmd_name[i]='_';
475
476 // special case the SAM break command as it is a python keyword
477 if(!strcmp(cmd_name,"break")){
478 free((void*)cmd_name);
479 cmd_name = strdup("brk");
480 }
481
482 sprintf(buf2,"def sam_%s(args=\"\"):\n",cmd_name);
483 sprintf(buf2 + strlen(buf2)," \"\"\"%s\n \"\"\"\n",next->help);
484 sprintf(buf2 + strlen(buf2)," sam.ui_exec(\"%s \" + args)\n\n",next->name);
485
486 PyObject* pyStr = Py_BuildValue((char*)"s",buf2);
487 PyMapping_SetItemString(pyDict,cmd_name,pyStr);
488
489 next = next->next;
490 free((void*)cmd_name);
491 }
492
493 return pyDict;
494}
495
496
497static PyMethodDef py_methods [] =
498{
499 {"ui_exec", sam_exec, METH_VARARGS, "ui_exec <cmd>\n"},
500 {"ui_register", sam_register, METH_VARARGS, "ui_register (cmd_name, help_str,cmd_func)\n"},
501 {"ui_unregister", sam_unregister, METH_VARARGS, "ui_unregister (cmd_name)\n"},
502 {"sys_type", vcpu_sys_type, METH_VARARGS, "vcpu_sys_type <>\n"},
503 {"sys_size", vcpu_sys_size, METH_VARARGS, "vcpu_sys_size <>\n"},
504 {"sys_pntr", vcpu_sys_pntr, METH_VARARGS, "vcpu_sys_pntr <i>\n"},
505 {"mem_ld64", mem_ld64, METH_VARARGS, "mem_ld64(addr)\n"},
506 {"mem_st64", mem_st64, METH_VARARGS, "mem_st64(addr,data)\n"},
507 {"mem_ld32", mem_ld32, METH_VARARGS, "mem_ld32(addr)\n"},
508 {"mem_st32", mem_st32, METH_VARARGS, "mem_st32(addr,data)\n"},
509 {"mem_ld16", mem_ld16, METH_VARARGS, "mem_ld16(addr)\n"},
510 {"mem_st16", mem_st16, METH_VARARGS, "mem_st16(addr,data)\n"},
511 {"mem_ld8", mem_ld8, METH_VARARGS, "mem_ld8(addr)\n"},
512 {"mem_st8", mem_st8, METH_VARARGS, "mem_st8(addr,data)\n"},
513 {"is_stopped", is_stopped, METH_VARARGS, "is_stopped()\n"},
514 {"is_restored_simulation", is_restored_simulation, METH_VARARGS, "is_restored_simulation()\n"},
515 {"sstep", s_step, METH_VARARGS, "sstep(vcpu_id)\n"},
516 {"get_cmd_dict", get_cmd_dict, METH_VARARGS, "get_cmd_dict()\n"},
517 {"set_cmd_del_fn", set_cmd_del_fn, METH_VARARGS, "set_cmd_del_fn(Fn)\n"},
518 {"set_cmd_add_fn", set_cmd_add_fn, METH_VARARGS, "set_cmd_add_fn(Fn)\n"},
519 {0, 0, 0, 0} // end of the list
520};
521
522
523////////////////////////////////////////////////////////////////
524//
525// py source command
526//
527
528extern int (*py_source)( int argc, char** argv );
529
530int py_source_cmd( int argc, char **argv )
531{
532 assert (argc > 0);
533
534 ui->verbose("loading py module %s...\n", argv[0]);
535 char cmd[max_cmd_line_size];
536 char *s=cmd;
537 s=stradd(s,"execfile(\"");
538 char* filename = argv[0];
539 if (strncmp(filename,"$SAM/",5) == 0)
540 {
541 // replace $SAM with dir path
542 char *fname = s;
543 s=stradd(s,sam_dir);
544 s=stradd(s,&filename[4]);
545 filename = fname;
546 }
547 else // file name
548 s=stradd(s,filename);
549
550 stradd(s,"\0",1);
551
552 // check if file exist
553 struct stat sfile;
554 if (stat(filename, &sfile))
555 {
556 fprintf(stderr, "ERROR: %s : No such file or directory\n", filename);
557 return 0;
558 }
559 if ((sfile.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0)
560 {
561 fprintf(stderr, "ERROR: %s : file is not readable \n", filename);
562 return 0;
563 }
564
565 stradd(s,"\")\0",3);
566
567 ui->verbose("%s\n", cmd);
568
569 // set pythons sys.argv to arguments of py_source
570 PySys_SetArgv(argc,argv);
571 PyRun_SimpleString(cmd);
572
573 return 1;
574}
575
576/////////////////////////////////////////////////////////////////
577//
578// start py user interface
579//
580
581extern void setenv_pythonhome(); // Defined in pythonhome.cc
582
583extern "C" int init_py_interface(char* fname, char* modname, void* lib_handle)
584{
585 if (py_lib_handle != NULL)
586 {
587 ui->error("py lib was loaded already. \n" );
588 return 0;
589 }
590
591 py_lib_handle = lib_handle;
592
593 if(py_lib_handle==NULL)
594 {
595 fprintf (stderr, "cannot obtain py lib handle\n" );
596 return 0;
597 }
598
599 extern bool python_UI;
600 python_UI = true;
601
602 setenv_pythonhome();
603
604 // set PYTHONPATH to the known python directories in our
605 // sam releases.
606
607 const char* env_var = "PYTHONPATH=";
608 const char* pfe_dir = "/pfe";
609 const char* sam = getexecname();
610
611 // Do we expect getexecname() to fail ... geeesh that would be
612 // a disaster if $0 is blank. In case it is just assume sam.
613
614 if (!sam) sam = "./sam";
615
616 // Expect that sam was executed from our release. So expect
617 // $sam_dir/bin/sam and grab $sam_dir. If not then things have
618 // been moved around ... well though.
619
620 char* origin = dirname(strdup(sam));
621 sam_dir = dirname(strdup(origin));
622
623 char* str;
624 size_t len = strlen(env_var) + strlen(sam_dir) + strlen(pfe_dir);
625
626 // Before setting PYTHONPATH, check if one is set already and prepend
627 // our paths to it. Otherwise assume PYTHONPATH was '.'
628
629 char* pythonpath = getenv(env_var);
630 if (pythonpath == 0)
631 pythonpath = ".";
632
633 str = (char*)malloc(len + strlen(pythonpath) + 2);
634 sprintf(str,"%s%s%s:%s",env_var,sam_dir,pfe_dir,pythonpath);
635
636 ui->verbose("%s\n",str);
637 putenv(str);
638
639 if ( !Py_IsInitialized() )
640 {
641 Py_Initialize();
642 Py_InitModule((char*)"sam", py_methods);
643 PyEval_InitThreads();
644 }
645
646 // The "run-python-file" ui command needs this py_source
647 py_source = py_source_cmd;
648
649 return 1;
650}
651
652extern "C" int close_py_interface()
653{
654 // when return back to sam ui don't call this method
655 // during the session otherwise sam ui hangs;
656 if ( Py_IsInitialized() )
657 {
658 Py_Finalize();
659 }
660
661 pyCBdelfn = 0;
662 pyCBaddfn = 0;
663
664 if(py_cmd_map)
665 {
666 delete py_cmd_map;
667 py_cmd_map = NULL;
668 }
669
670 return 0;
671}