00001
00210 #include <signal.h>
00211 #include <ctype.h>
00212 #include <string.h>
00213
00214 #include "output.h"
00215 #include "exec.h"
00216 #include "class.h"
00217 #include "convert.h"
00218 #include "object.h"
00219 #include "index.h"
00220 #include "realtime.h"
00221 #include "module.h"
00222 #include "threadpool.h"
00223 #include "debug.h"
00224 #include "kill.h"
00225
00226 #ifndef _MAX_PATH
00227 #include <linux/limits.h>
00228 #define _MAX_PATH PATH_MAX
00229 #endif
00230
00231
00232 extern const PASSCONFIG passtype[];
00233 extern int iteration_counter;
00234
00235
00236 int siglist[] = {SIGINT, SIGFPE, SIGSEGV, SIGTERM};
00237
00238 static char *get_objname(OBJECT *obj)
00239 {
00240 static char buf[1024];
00241 if (obj->name) return obj->name;
00242 sprintf(buf,"%s:%d", obj->oclass->name, obj->id);
00243 return buf;
00244 }
00245
00246
00247 static int debug_active = 1;
00248 static int error_caught = 0;
00249 static int watch_sync = 0;
00250 int stop_now = 0;
00251 static int sigint_caught = 0;
00253 void debug_notify_error(void)
00254 {
00255 error_caught = 1;
00256 }
00257
00264 void exec_sighandler(int sig)
00265 {
00266 sigint_caught=1;
00267 output_debug("signal %s caught", strsignal(sig));
00268 if (sig==SIGTERM)
00269 {
00270 output_error("received SIGTERM; exiting now");
00271 exit(1);
00272 }
00273 else if (sig==SIGINT)
00274 {
00275 if (global_debug_mode)
00276 {
00277 if (debug_active==0)
00278 {
00279 output_debug("debugger activated");
00280 debug_active=1;
00281 }
00282 else
00283 {
00284 output_debug("debugger activation failed, signal processing disabled");
00285 signal(sig,NULL);
00286 }
00287 }
00288 }
00289 else
00290 {
00291 output_error("processing signal %d", sig);
00292 stop_now=1;
00293 }
00294 }
00295
00296 #ifdef WIN32
00297 char *strsignal(int sig)
00298 {
00299 switch(sig) {
00300 case SIGABRT: return "SIGABRT";
00301 case SIGFPE: return "SIGFPE";
00302 case SIGILL: return "SIGILL";
00303 case SIGINT: return "SIGINT";
00304 case SIGSEGV: return "SIGSEGV";
00305 case SIGTERM: return "SIGTERM";
00306 default: return "SIGUNKNOWN";
00307 }
00308 }
00309 #endif
00310
00311 typedef enum {DBG_QUIT,DBG_RUN,DBG_NEXT} DEBUGCMD;
00312 typedef enum {BP_MODULE, BP_CLASS, BP_OBJECT, BP_PASS, BP_RANK, BP_TIME, BP_CLOCK, BP_ERROR} BREAKPOINTTYPE;
00313 typedef struct s_breakpoint {
00314 BREAKPOINTTYPE type;
00315 int enabled;
00316 int num;
00317 union {
00318 MODULE *mod;
00319 CLASS *oclass;
00320 OBJECT *obj;
00321 int64 pass;
00322 int64 rank;
00323 TIMESTAMP ts;
00324 int64 data;
00325 };
00326 struct s_breakpoint *next;
00327 } BREAKPOINT;
00328 static BREAKPOINT *first_breakpoint=NULL,
00329 *last_breakpoint=NULL;
00330 static int breakpoint_count=0;
00334 static int exec_add_breakpoint(BREAKPOINTTYPE type,
00335 int64 data)
00336 {
00337 BREAKPOINT *bp = (BREAKPOINT*)malloc(sizeof(BREAKPOINT));
00338 if (bp==NULL)
00339 {
00340 output_error("memory allocation failed");
00341 return 0;
00342 }
00343 bp->type = type;
00344 bp->data = data;
00345 bp->enabled = 1;
00346 bp->num = breakpoint_count++;
00347 bp->next = NULL;
00348 if (last_breakpoint!=NULL)
00349 last_breakpoint->next=bp;
00350 else
00351 first_breakpoint=bp;
00352 last_breakpoint = bp;
00353 return 1;
00354 }
00355
00356 typedef struct s_watchpoint {
00357 int enabled;
00358 int num;
00359 OBJECT *obj;
00360 PROPERTY *prop;
00361 char buffer[4096];
00362 struct s_watchpoint *next;
00363 } WATCHPOINT;
00364 static WATCHPOINT *first_watchpoint=NULL,
00365 *last_watchpoint=NULL;
00366 static int watchpoint_count=0;
00370 static int exec_add_watchpoint(OBJECT *obj,
00371 PROPERTY *prop)
00372 {
00373 WATCHPOINT *wp = (WATCHPOINT*)malloc(sizeof(WATCHPOINT));
00374 if (wp==NULL)
00375 {
00376 output_error("memory allocation failed");
00377 return 0;
00378 }
00379 wp->enabled = 1;
00380 wp->num = watchpoint_count++;
00381 wp->obj = obj;
00382 wp->prop = prop;
00383 if (prop==NULL)
00384 object_dump(wp->buffer,sizeof(wp->buffer),obj);
00385 else
00386 strcpy(wp->buffer,object_property_to_string(obj,prop->name));
00387 wp->next = NULL;
00388 if (last_watchpoint!=NULL)
00389 last_watchpoint->next=wp;
00390 else
00391 first_watchpoint=wp;
00392 last_watchpoint = wp;
00393 return 1;
00394 }
00395
00396 FILE *load_fp;
00397 int load_from_file = 0;
00401 DEBUGCMD exec_debug_cmd(struct sync_data *data,
00402 int pass,
00403 int index,
00404 OBJECT *obj)
00405 {
00406 static DEBUGCMD last = DBG_NEXT;
00407 char tmp[64];
00408 char* read_val;
00409
00410 output_debug("time %s\r", convert_from_timestamp(global_clock,tmp,sizeof(tmp))?tmp:"(invalid)");
00411 output_debug("pass %s, rank %d, object %s, iteration %d",
00412 passtype[pass]==PC_PRETOPDOWN?"PRETOPDOWN":(passtype[pass]==PC_BOTTOMUP?"BOTTOMUP":(passtype[pass]==PC_POSTTOPDOWN?"POSTTOPDOWN":"(invalid)")),
00413 index, get_objname(obj),
00414 global_iteration_limit-iteration_counter+1);
00415 {
00416 extern void (*notify_error)(void);
00417 if (notify_error != NULL)
00418 output_debug("output errors are trapped");
00419 }
00420 while (1)
00421 {
00422 char cmd[32]="";
00423 char buffer[1024]="";
00424 int i;
00425 Retry:
00426
00427 for (i=0; i<sizeof(siglist)/sizeof(siglist[0]); i++)
00428 signal(siglist[i],exec_sighandler);
00429
00430 if(load_from_file == 0){
00431 fprintf(stdout,"GLD> ");
00432 sigint_caught=0;
00433 fflush(stdout);
00434
00435 gets(buffer);
00436 output_verbose("debug command '%s'", buffer);
00437 }
00438 else{
00439 char* nl;
00440 read_val = fgets(buffer,1024,load_fp);
00441
00442
00443 if(read_val == NULL)
00444 {
00445 load_from_file = 0;
00446 fclose(load_fp);
00447 goto Retry;
00448 }
00449
00450 nl = strrchr(buffer,'\r');
00451 if(nl)
00452 *nl = '\0';
00453 nl = strrchr(buffer,'\n');
00454 if(nl)
00455 *nl = '\0';
00456 }
00457 sscanf(buffer,"%s",cmd);
00458 if (sigint_caught==1)
00459 {
00460 fprintf(stdout,"<Ctrl-C>\n");
00461 goto Retry;
00462 }
00463 if (strncmp(cmd,"quit",max(1,strlen(cmd)))==0)
00464 return DBG_QUIT;
00465 else if (strncmp(cmd,"run",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_RUN))
00466 {
00467 output_debug("resuming simulation, Ctrl-C interrupts");
00468 debug_active=0;
00469 return last = DBG_RUN;
00470 }
00471 else if (strncmp(cmd,"next",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_NEXT))
00472 return last = DBG_NEXT;
00473 else if (strncmp(cmd,"list",max(1,strlen(cmd)))==0)
00474 {
00475 char lclass[256]="";
00476 OBJECT *obj = object_get_first();
00477 sscanf(buffer,"%*s %s", lclass);
00478
00479
00480
00481
00482 for (obj=object_get_first(); obj!=NULL; obj=obj->next)
00483 {
00484 if (lclass[0]=='\0' || strcmp(lclass,obj->oclass->name)==0)
00485 {
00486 char buf1[16],buf2[16],buf3[32];
00487 output_message("%1s%1s%1s%1s%1s%1s %4d %-24.24s %-16.16s %-16.16s",
00488 global_clock<obj->in_svc?"P":(global_clock<obj->out_svc?"A":"R"),
00489 (obj->oclass->passconfig&PC_PRETOPDOWN)?(pass<PC_PRETOPDOWN?"t":"T"):"-",
00490 (obj->oclass->passconfig&PC_BOTTOMUP)?(pass<PC_BOTTOMUP?"b":"B"):"-",
00491 (obj->oclass->passconfig&PC_POSTTOPDOWN)?(pass<PC_POSTTOPDOWN?"t":"T"):"-",
00492 (obj->flags&OF_LOCKED)==OF_LOCKED?"l":"-",
00493 (obj->flags&OF_HASPLC)==OF_HASPLC?"x":"-",
00494 obj->rank,
00495 obj->clock>0?(convert_from_timestamp(obj->clock,buf3,sizeof(buf3))?buf3:"(error)"):"INIT",
00496 obj->name?obj->name:convert_from_object(buf1,sizeof(buf1),&obj,NULL)?buf1:"(error)",
00497 obj->parent?(obj->parent->name?obj->parent->name:convert_from_object(buf2,sizeof(buf2),&(obj->parent),NULL)?buf2:"(error)"):"ROOT");
00498 }
00499 }
00500 }
00501 else if (strncmp(cmd,"script",max(1,strlen(cmd)))==0)
00502 {
00503 char load_filename[_MAX_PATH+32];
00504 if(sscanf(buffer,"%*s %[^\x20]",load_filename) <=0)
00505 {
00506 output_error("Missing file name for script command");
00507 }
00508 load_fp = fopen(load_filename,"r");
00509 if(load_fp == NULL)
00510 {
00511 output_error("Unable to open file %s for reading",load_filename);
00512 }
00513 load_from_file = 1;
00514 }
00515 else if (strncmp(cmd,"system",max(2,strlen(cmd)))==0)
00516 {
00517 char cmd[1024];
00518 if (sscanf(buffer,"%*s %[^\0]", cmd)==1)
00519 system(cmd);
00520 #ifdef WIN32
00521 else if (getenv("COMSPEC")!=NULL)
00522 system(getenv("COMSPEC"));
00523 else
00524 system("cmd");
00525 #else
00526 else if (getenv("SHELL")!=NULL)
00527 system(getenv("SHELL"));
00528 else
00529 system("/bin/sh");
00530 #endif
00531 }
00532 else if (strncmp(cmd,"break",max(1,strlen(cmd)))==0)
00533 {
00534 char bptype[256]="";
00535 char bpval[256]="";
00536 if (sscanf(buffer,"%*s %s %[^\0]", bptype, bpval)==0)
00537 {
00538
00539 BREAKPOINT *bp;
00540 if (last_breakpoint==NULL)
00541 output_debug("no breakpoints");
00542 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00543 {
00544 char tmp[64];
00545 switch (bp->type) {
00546 case BP_MODULE:
00547 output_debug("breakpoint %2d - module %s %s", bp->num, bp->mod->name, bp->enabled?"":"(disabled)");
00548 break;
00549 case BP_CLASS:
00550 output_debug("breakpoint %2d - class %s %s", bp->num, bp->oclass->name, bp->enabled?"":"(disabled)");
00551 break;
00552 case BP_OBJECT:
00553 output_debug("breakpoint %2d object %s %s", bp->num, get_objname(bp->obj), bp->enabled?"":"(disabled)");
00554 break;
00555 case BP_PASS:
00556 output_debug("breakpoint %2d pass %s %s", bp->num, (int)bp->pass==PC_PRETOPDOWN?"pretopdown":((int)bp->pass==PC_BOTTOMUP?"bottomup":((int)bp->pass==PC_POSTTOPDOWN?"posttopdown":"(invalid)")), bp->enabled?"":"(disabled)");
00557 break;
00558 case BP_RANK:
00559 output_debug("breakpoint %2d rank %d %s", bp->num, (int)bp->rank, bp->enabled?"":"(disabled)");
00560 break;
00561 case BP_TIME:
00562 output_debug("breakpoint %2d time %s (%"FMT_INT64"d) %s", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts, bp->enabled?"":"(disabled)");
00563 break;
00564 case BP_CLOCK:
00565 output_debug("breakpoint %2d clock %s", bp->num, bp->enabled?"":"(disabled)");
00566 break;
00567 case BP_ERROR:
00568 output_debug("breakpoint %2d on error", bp->num, bp->enabled?"":"(disabled)");
00569 break;
00570 default:
00571 break;
00572 }
00573 }
00574 }
00575 else if (strncmp(bptype,"error",strlen(bptype))==0)
00576 {
00577 if (!exec_add_breakpoint(BP_ERROR,0))
00578 output_error("unable to add error breakpoint");
00579 error_caught = 0;
00580 output_notify_error(debug_notify_error);
00581 }
00582 else if (strncmp(bptype,"clock",strlen(bptype))==0)
00583 {
00584 if (!exec_add_breakpoint(BP_CLOCK,global_clock))
00585 output_error("unable to add clock breakpoint");
00586 }
00587 else if (strncmp(bptype,"object",strlen(bptype))==0)
00588 {
00589 OBJECT *obj = object_find_name(bpval);
00590 if (obj!=NULL || convert_to_object(bpval,&obj,NULL))
00591 {
00592 if (!exec_add_breakpoint(BP_OBJECT,(int64)obj))
00593 output_error("unable to add object breakpoint");
00594 }
00595 else
00596 output_error("object %s does not exist",bpval);
00597 }
00598 else if (strncmp(bptype,"module",strlen(bptype))==0)
00599 {
00600 MODULE *mod = module_find(bpval);
00601 if (mod!=NULL)
00602 {
00603 if (!exec_add_breakpoint(BP_MODULE,(int64)mod))
00604 output_error("unable to add module breakpoint");
00605 }
00606 else
00607 output_error("module %s does not exist",bpval);
00608 }
00609 else if (strncmp(bptype,"class",strlen(bptype))==0)
00610 {
00611 CLASS *oclass = class_get_class_from_classname(bpval);
00612 if (oclass!=NULL)
00613 {
00614 if (!exec_add_breakpoint(BP_CLASS,(int64)oclass))
00615 output_error("unable to add class breakpoint");
00616 }
00617 else
00618 output_debug("class %s does not exist",bpval);
00619 }
00620 else if (strncmp(bptype,"pass",strlen(bptype))==0)
00621 {
00622 int pass;
00623 if (strnicmp(bpval,"pretopdown",max(2,strlen(bpval)))==0) pass=PC_PRETOPDOWN;
00624 else if (strnicmp(bpval,"bottomup",strlen(bpval))==0) pass=PC_BOTTOMUP;
00625 else if (strnicmp(bpval,"posttopdown",max(2,strlen(bpval)))==0) pass=PC_POSTTOPDOWN;
00626 else
00627 {
00628 output_error("undefined pass type");
00629 continue;
00630 }
00631 if (!exec_add_breakpoint(BP_PASS,(int64)pass))
00632 output_error("unable to add pass breakpoint");
00633 }
00634 else if (strncmp(bptype,"rank",strlen(bptype))==0)
00635 {
00636 if (!exec_add_breakpoint(BP_RANK,(int64)atoi(bpval)))
00637 output_error("unable to add rank breakpoint");
00638 }
00639 else if (strncmp(bptype,"time",strlen(bptype))==0)
00640 {
00641 TIMESTAMP ts = convert_to_timestamp(bpval);
00642 if (ts==TS_NEVER)
00643 output_error("invalid time");
00644 else if (!exec_add_breakpoint(BP_TIME,(int64)ts))
00645 output_error("unable to add timestamp breakpoint");
00646 }
00647 else if (strncmp(bptype,"disable",strlen(bptype))==0)
00648 {
00649 int n=-1;
00650 BREAKPOINT *bp;
00651 if (strcmp(bpval,"")!=0)
00652 {
00653 if (isdigit(bpval[0]))
00654 n=atoi(bpval);
00655 else
00656 {
00657 output_error("invalid breakpoint number");
00658 continue;
00659 }
00660 }
00661 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00662 {
00663 if (bp->num==n || n==-1)
00664 bp->enabled = 0;
00665 }
00666 }
00667 else if (strncmp(bptype,"enable",strlen(bptype))==0)
00668 {
00669 int n=-1;
00670 BREAKPOINT *bp;
00671 if (strcmp(bpval,"")!=0)
00672 {
00673 if (isdigit(bpval[0]))
00674 n=atoi(bpval);
00675 else
00676 {
00677 output_error("invalid breakpoint number");
00678 continue;
00679 }
00680 }
00681 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00682 {
00683 if (bp->num==n || n==-1)
00684 bp->enabled = 1;
00685 }
00686 }
00687 else
00688 output_error("%s is not recognized", bptype);
00689 }
00690 else if (strncmp(cmd,"watch",max(2,strlen(cmd)))==0)
00691 {
00692 char wptype[256]="";
00693 char wpval[256]="";
00694 OBJECT *obj;
00695 if (sscanf(buffer,"%*s %s %[^\0]", wptype, wpval)==0)
00696 {
00697
00698 WATCHPOINT *wp;
00699 if (last_watchpoint==NULL)
00700 output_debug("no watchpoints");
00701 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00702 output_debug("watchpoint %d - object %s %s", wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)");
00703 }
00704 else if (isdigit(wptype[0]))
00705 {
00706 int n=atoi(wptype);
00707 WATCHPOINT *wp;
00708 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00709 {
00710 if (wp->num==n)
00711 output_debug("watchpoint %d - object %s %s\n%s",
00712 wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)",wp->buffer);
00713 }
00714 }
00715 else if (strcmp(wptype,"sync")==0)
00716 {
00717 watch_sync = !watch_sync;
00718 output_debug("sync watch is %s",watch_sync?"enabled":"disabled");
00719 }
00720 else if (strncmp(wptype,"disable",strlen(wptype))==0)
00721 {
00722 int n=-1;
00723 WATCHPOINT *wp;
00724 if (strcmp(wpval,"")!=0)
00725 {
00726 if (isdigit(wpval[0]))
00727 n=atoi(wpval);
00728 else
00729 {
00730 output_error("invalid watchpoint number");
00731 continue;
00732 }
00733 }
00734 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00735 {
00736 if (wp->num==n || n==-1)
00737 wp->enabled = 0;
00738 }
00739 }
00740 else if (strncmp(wptype,"enable",strlen(wptype))==0)
00741 {
00742 int n=-1;
00743 WATCHPOINT *wp;
00744 if (strcmp(wpval,"")!=0)
00745 {
00746 if (isdigit(wpval[0]))
00747 n=atoi(wpval);
00748 else
00749 {
00750 output_error("invalid watchpoint number");
00751 continue;
00752 }
00753 }
00754 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00755 {
00756 if (wp->num==n || n==-1)
00757 wp->enabled = 1;
00758 }
00759 }
00760 else if ((obj=object_find_name(wptype)) || convert_to_object(wptype,&obj,NULL))
00761 {
00762 if (strcmp(wpval,"")!=0)
00763 {
00764 PROPERTY *prop = object_get_property(obj,wpval);
00765 if (prop==NULL)
00766 output_error("object %s does not have a property named '%s'", wptype,wpval);
00767 else if (!exec_add_watchpoint(obj,prop))
00768 output_error("unable to add object watchpoint");
00769 }
00770 else if (!exec_add_watchpoint(obj,NULL))
00771 output_error("unable to add object watchpoint");
00772 }
00773 else
00774 output_error("%s is not recognized", wptype);
00775 }
00776 else if (strncmp(cmd,"where",max(1,strlen(cmd)))==0)
00777 {
00778 char ts[64];
00779 output_debug("Global clock... %s (%" FMT_INT64 "d)", convert_from_timestamp(global_clock,ts,sizeof(ts))?ts:"(invalid)",global_clock);
00780 output_debug("Hard events.... %d", data->hard_event);
00781 output_debug("Sync status.... %s", data->status==FAILED?"FAILED":"SUCCESS");
00782 output_debug("Step to time... %s (%" FMT_INT64 "d)", convert_from_timestamp(data->step_to,ts,sizeof(ts))?ts:"(invalid)",data->step_to);
00783 output_debug("Pass........... %d", pass);
00784 output_debug("Rank........... %d", index);
00785 output_debug("Object......... %s",get_objname(obj));
00786 }
00787 else if (strncmp(cmd,"print",max(1,strlen(cmd)))==0)
00788 {
00789 char tmp[4096];
00790 if (sscanf(buffer,"%*s %s",tmp)==0)
00791 {
00792 if (object_dump(tmp,sizeof(tmp),obj))
00793 output_debug("%s",tmp);
00794 else
00795 output_error("object dump failed");
00796 }
00797 else
00798 {
00799 OBJECT *obj = object_find_name(tmp);
00800 if (obj!=NULL || convert_to_object(tmp,&obj,NULL))
00801 {
00802 if (object_dump(tmp,sizeof(tmp),obj))
00803 output_debug("%s",tmp);
00804 else
00805 output_error("object dump failed");
00806 }
00807 else
00808 output_error("object %s undefined", tmp);
00809 }
00810 }
00811 else if (strncmp(cmd,"globals",max(1,strlen(cmd)))==0)
00812 {
00813 GLOBALVAR *var;
00814 for (var=global_getnext(NULL); var!=NULL; var=global_getnext(var))
00815 {
00816 char *val = global_getvar(var->name, NULL, 0);
00817 if (val!=NULL && strlen(val)>64)
00818 strcpy(val+28,"...");
00819 output_message("%-32.32s: \"%s\"", var->name, val==NULL?"(error)":val);
00820 }
00821 }
00822 else if (strncmp(cmd,"set",max(1,strlen(cmd)))==0)
00823 {
00824 char256 objname;
00825 char256 propname;
00826 char256 value;
00827 int scanct = 0;
00828 value[0] = '\0';
00829 if ((scanct=sscanf(buffer,"%*s %s %s %s",objname,propname,value))>=2)
00830 {
00831 OBJECT *obj;
00832 if (strcmp(objname,"global")==0)
00833 {
00834 if (global_setvar(propname,value)==FAILED)
00835 output_error("unable to set global value %s", propname);
00836 }
00837 else if ((obj=object_find_name(objname)) || convert_to_object(objname,&obj,NULL))
00838 {
00839 if (!object_set_value_by_name(obj,propname,value))
00840 output_error("unable to set value of object %s property %s", objname,propname);
00841 else if (!object_get_property(obj,propname))
00842 output_error("invalid property for object %s",objname);
00843 }
00844 else
00845 output_error("invalid object");
00846 }
00847 else{
00848 output_error("set syntax error (%i items)", scanct);
00849 }
00850 }
00851 else if (strncmp(cmd,"find ",max(1,strlen(cmd)))==0)
00852 {
00853 FINDLIST *fl = NULL;
00854 OBJECT *obj = NULL;
00855 output_debug("running search with \"%s\"", buffer+5);
00856 fl = find_objects(FL_GROUP, buffer+5);
00857 obj = find_first(fl);
00858
00859
00860
00861 for (obj=find_first(fl); obj!=NULL; obj=find_next(fl, obj))
00862 {
00863 char buf1[16],buf2[16],buf3[32];
00864 output_message("%1s%1s%1s%1s%1s%1s %4d %-24.24s %-16.16s %-16.16s",
00865 global_clock<obj->in_svc?"P":(global_clock<obj->out_svc?"A":"R"),
00866 (obj->oclass->passconfig&PC_PRETOPDOWN)?(pass<PC_PRETOPDOWN?"t":"T"):"-",
00867 (obj->oclass->passconfig&PC_BOTTOMUP)?(pass<PC_BOTTOMUP?"b":"B"):"-",
00868 (obj->oclass->passconfig&PC_POSTTOPDOWN)?(pass<PC_POSTTOPDOWN?"t":"T"):"-",
00869 (obj->flags&OF_LOCKED)==OF_LOCKED?"l":"-",
00870 (obj->flags&OF_HASPLC)==OF_HASPLC?"x":"-",
00871 obj->rank,
00872 obj->clock>0?(convert_from_timestamp(obj->clock,buf3,sizeof(buf3))?buf3:"(error)"):"INIT",
00873 obj->name?obj->name:convert_from_object(buf1,sizeof(buf1),&obj,NULL)?buf1:"(error)",
00874 obj->parent?(obj->parent->name?obj->parent->name:convert_from_object(buf2,sizeof(buf2),&(obj->parent),NULL)?buf2:"(error)"):"ROOT");
00875 }
00876 }
00877 else if (strncmp(cmd,"help",max(1,strlen(cmd)))==0)
00878 {
00879 output_debug("Summary of debug commands\n"
00880 " break prints all breakpoints\n"
00881 " clock stop the simulator on clock advance\n"
00882 " error stop the simulator is an error occurs\n"
00883 " object <X> stop the simulator on sync of object X\n"
00884 " module <X> stop the simulator on sync of module X\n"
00885 " class <X> stop the simulator on sync of class X\n"
00886 " pass <X> stop the simulator on the start of pass X\n"
00887 " rank <X> stop the simulation on the start of rank X\n"
00888 " time <X> stop the simulation at the time time X\n"
00889 " disable disables all breakpoints\n"
00890 " enable enables all breakpoints\n"
00891 " disable <#> disables breakpoint #\n"
00892 " enable <#> enables breakpoint #\n"
00893 " globals print global variables\n"
00894 " list list objects\n"
00895 " <X> list objects of class X\n"
00896 " next advances to the next object sync\n"
00897 " print <X> prints object X\n"
00898 " quit quits the simulator\n"
00899 " run runs the simulator until the next break point\n"
00900 " set <X> <Y> <val> set object X property Y to <val>\n"
00901 " script <filename> read a script file containing debugger commands\n"
00902 " system opens a shell on the current OS\n"
00903 " <command> executes the command on the current OS\n"
00904 " watch prints all watchpoints\n"
00905 " <#> prints watchpoint #\n"
00906 " <X> stop the simulation if object X changes\n"
00907 " <X> <Y> stop the simulation if object X property Y changes\n"
00908 " disable disables all watchpoints #\n"
00909 " disable <#> disables watchpoint #\n"
00910 " enable enables all watchpoint #\n"
00911 " enable <#> enables watchpoint #\n"
00912 " sync toggles sync watch\n"
00913 " where displays the current context\n"
00914 );
00915 }
00916 else if (strcmp(buffer,"")!=0)
00917 output_error("invalid debug command, try 'help'");
00918 else
00919 return last;
00920 }
00921 }
00922
00925 int exec_debug(struct sync_data *data,
00926 int pass,
00927 int index,
00928 OBJECT *obj)
00929 {
00930 TIMESTAMP this_t;
00931 #ifdef WIN32
00932 static int firstcall=1;
00933 if (firstcall)
00934 {
00935 kill_starthandler();
00936 atexit(kill_stophandler);
00937 firstcall=0;
00938 }
00939 #endif
00940
00941 if (debug_active==0)
00942 {
00943 BREAKPOINT *bp;
00944 WATCHPOINT *wp;
00945 static char timebuf[64]="";
00946 char buffer[64];
00947
00948
00949 if (convert_from_timestamp(global_clock,buffer,sizeof(buffer)) && strcmp(buffer,timebuf)!=0)
00950 {
00951 output_raw("DEBUG: global_clock = '%s' (%"FMT_INT64"d)\r", buffer,global_clock);
00952 strcpy(timebuf,buffer);
00953 }
00954
00955
00956 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00957 {
00958 if (wp->enabled==0)
00959 continue;
00960 if (obj==wp->obj)
00961 {
00962 if (wp->prop==NULL)
00963 {
00964 char tmp[4096];
00965 if (object_dump(tmp,sizeof(tmp),obj) && strcmp(tmp,wp->buffer)!=0)
00966 {
00967 output_debug("watchpoint %d stopped on object %s", wp->num, get_objname(obj));
00968 output_debug("%s",tmp);
00969 strcpy(wp->buffer,tmp);
00970 debug_active=1;
00971 }
00972 }
00973 else
00974 {
00975 char *tmp = object_property_to_string(obj,wp->prop->name);
00976 if (tmp!=NULL && strcmp(tmp,wp->buffer)!=0)
00977 {
00978 output_debug("watchpoint %d stopped on object %s property %s", wp->num, get_objname(obj), wp->prop->name);
00979 output_debug("from... %s",wp->buffer);
00980 output_debug("to..... %s",tmp);
00981 strcpy(wp->buffer,tmp);
00982 debug_active=1;
00983 }
00984 }
00985 }
00986 }
00987
00988
00989 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00990 {
00991 if (bp->enabled==0)
00992 continue;
00993 if (bp->type==BP_ERROR && error_caught)
00994 {
00995 output_debug("breakpoint %d (error) stopped on object %s", bp->num, get_objname(obj));
00996 error_caught=0;
00997 debug_active=1;
00998 }
00999 if (bp->type==BP_MODULE && bp->mod==obj->oclass->module)
01000 {
01001 output_debug("breakpoint %d (module %s) stopped on object %s", bp->num, bp->mod->name, get_objname(obj));
01002 debug_active=1;
01003 }
01004 else if (bp->type==BP_CLASS && bp->oclass==obj->oclass)
01005 {
01006 output_debug("breakpoint %d (class %s) stopped on object %s", bp->num, bp->oclass->name, get_objname(obj));
01007 debug_active=1;
01008 }
01009 else if (bp->type==BP_OBJECT && bp->obj==obj)
01010 {
01011 char buf1[1024];
01012 strcpy(buf1,get_objname(bp->obj));
01013 output_debug("breakpoint %d (object %s) stopped on object %s", bp->num, buf1, get_objname(obj));
01014 debug_active=1;
01015 }
01016 else if (bp->type==BP_RANK && bp->rank==(int64)obj->rank)
01017 {
01018 output_debug("breakpoint %d (rank %d) stopped on object %s", bp->num, (int)bp->rank, get_objname(obj));
01019 debug_active=1;
01020 }
01021 else if (bp->type==BP_PASS && bp->pass==(int64)pass)
01022 {
01023 output_debug("breakpoint %d (pass %d) stopped on object %s", bp->num, (int)bp->pass, get_objname(obj));
01024 debug_active=1;
01025 }
01026 else if (bp->type==BP_TIME && global_clock>=bp->ts)
01027 {
01028 char tmp[64];
01029 output_debug("breakpoint %d (time %s (%d)) stopped on object %s:%" FMT_INT64 "d", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts, obj->oclass->name, obj->id);
01030 debug_active=1;
01031 }
01032 else if (bp->type==BP_CLOCK && global_clock!=bp->ts)
01033 {
01034 char tmp[64];
01035 output_debug("breakpoint %d (clock %s (%d)) stopped on clock update", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts);
01036 bp->ts = global_clock;
01037 debug_active=1;
01038 }
01039 }
01040 }
01041 if (debug_active==1)
01042 {
01043 DEBUGCMD dbgcmd = exec_debug_cmd(data,pass,index,obj);
01044 switch (dbgcmd) {
01045 case DBG_QUIT: return FAILED;
01046 case DBG_RUN: break;
01047 case DBG_NEXT: break;
01048 default:
01049 output_error("invalid debug state");
01050 return FAILED;
01051 break;
01052 }
01053 }
01054
01055
01056 if (global_clock<obj->in_svc)
01057 {
01058 if (debug_active) output_debug("%s not in service yet", get_objname(obj));
01059 this_t = obj->in_svc;
01060 }
01061 else if (global_clock<=obj->out_svc)
01062 {
01063 char buffer[64]="(error)";
01064 this_t = object_sync(obj, global_clock, passtype[pass]);
01065 convert_from_timestamp(this_t<0?-this_t:this_t,buffer,sizeof(buffer));
01066 if (debug_active || watch_sync) output_debug("%s next sync %s %s", get_objname(obj),buffer,this_t<0?"(soft sync)":"");
01067 }
01068 else
01069 {
01070 if (debug_active) output_debug("%s out of service", get_objname(obj));
01071 this_t = TS_NEVER;
01072 }
01073
01074
01075 if (this_t < -1)
01076 this_t = -this_t;
01077 else if (this_t != TS_NEVER)
01078 data->hard_event++;
01079
01080
01081 if (this_t < global_clock) {
01082 output_error("%s: object %s stopped its clock!", simtime(), object_name(obj));
01083 if (error_caught)
01084 data->status = SUCCESS;
01085 else
01086 data->status = FAILED;
01087 } else {
01088
01089 if (iteration_counter == 2 && this_t == global_clock) {
01090 output_verbose("%s: object %s iteration limit imminent",
01091 simtime(), object_name(obj));
01092 }
01093 else if (iteration_counter == 1 && this_t == global_clock) {
01094 output_error("convergence iteration limit reached for object %s", get_objname(obj));
01095 }
01096
01097
01098 if (data->step_to > this_t)
01099 data->step_to = this_t;
01100 data->status = SUCCESS;
01101 }
01102 return data->status;
01103 }
01104