#include "config.h" #include "types.h" #include "lexer.h" #include "tokens.h" #include "mem.h" #include "reg.h" #include "stack.h" #include "ops.h" #include "context.h" #include "code.h" #include "event.h" #include "vm.h" #include "var.h" #include "printf.h" #include "ccall.h" #include "version.h" #include "unix.h" #include "debug.h" #include "cconst.h" #include "net.h" #include "run.h" #include "log.h" #include "shm.h" #include mem_t M; /* Primary (main foreground program) and secondary context (commands, temporary background programs) Each context has its own register set, data and function stacks, but sharing one heap segment (M). */ reg_t R0,R1; context_t C0,C1; stack_t DS0,FS0,DS1,FS1; int verbose = 0; int profile = 0; int nodeindex = 0; static int _millis(context_t *C) { number_t d=POP(C->DS); PUSH(C->DS,(number_t)(MILLIS()/(unsigned long)d)); return 0; // non-blocking } static int _status(context_t *C) { context_t *c=Context[0]; while(c) { vLog("[C%d] PC=%d DS=%d(%d) FS=%d(%d) ST=%x EV=%x TMO=%d M=[%d:%d](%d)\n", CONTEXTID(c),c->R->pc, c->DS->sp,c->DS->size, c->FS->sp,c->FS->size, c->R->state, c->evmask, c->R->timeout, c->M->bottom, c->M->top, c->M->size); c=c->next; } return 0; } static int _timer(context_t *C) { int millis=(int)POP(C->DS), timernum=(int)POP(C->DS); #if DEBUG>1 log(LOGDEBUG1,"timer(%d,%d)\n",timernum,millis); #endif if (millis==0) timer_stop(timernum); else timer_start(timernum, millis); return 0; } // must be sorted by name! ccall_t myccalls[]={ { "MILLIS", (int (*)())_millis, 1, 1, 0 }, { "STATUS", (int (*)())_status,0,0,0 }, { "TIMER", (int (*)())_timer,2,0,0 }, NULL }; cconst_t mycconst[]={ { "PORTALL", -1, NULL, 0}, { "PORT0", 0, NULL, 0}, { "PORT1", 1, NULL, 0}, { "PORT2", 2, NULL, 0}, { "PORT3", 3, NULL, 0}, NULL }; #if HAS_NET > 0 static int (*handlers[MSGMAXNUM])()= { NULL, // NOP (int (*)())MessageHandlerCode, // MSGCOMMAND (int (*)())MessageHandlerCode, // MSGPROGRAM (int (*)())MessageHandlerCode, // MSGPROGRAMPART NULL, // MSGDATA (int (*)())MessageHandlerEvent, // MSGEVENT (int (*)())MessageHandlerUser, // MSGUSER NULL, // MSGNET NULL // MSGMAXNUM }; #endif // Dummy routine for signal sending static int sendSignal(event_t *ev,index_t evindex) { printf("NOP: sendSignal (%d:%d)\n",evindex,ev->index); return 0; } int main(int argc, char *argv[]) { #if SHM>0 // SM segment starting address; must be incremented by a unique ´node number void *vaddr=(void *)0xa0000000; #endif lexer_t L; char compileOnly=0; char service=0; int maxrun=10; char *input=NULL; mem_t *mp=&M; int portindex; int progopn; if (argc>1) for(int i=1;i> PLX VM Ver. %s (c) Dr. Stefan Bosse<<\n",PLX_VERSION); // Primaray context, main program StackInit(&DS0,100,NULL); StackInit(&FS0,100,NULL); ContextInit(&C0,&M,&DS0,&FS0,&R0); // Secondary context, command line execution StackInit(&DS1,100,NULL); StackInit(&FS1,100,NULL); ContextInit(&C1,&M,&DS1,&FS1,&R1); IOINIT(); TIMEINIT(); #if HAS_NET>0 NetInit(handlers,NULL,NULL); #endif #if 0 { message_t *m1,*m2; m1=AllocateMessage(&Links[0],MSGRX|MSGPROGRAM); FinalizeMessage(m1); m2=AllocateMessage(&Links[0],MSGRX|MSGNORM); FinalizeMessage(m2); PrintLinkMessages(&Links[0]); FreeMessage(m1); PrintLinkMessages(&Links[0]); FreeMessage(m2); PrintLinkMessages(&Links[0]); } #endif timer_init(); //timer_start(0,500); //timer_start(1,800); CCallInit(myccalls); CConstInit(mycconst); // LexerInit(&L); MemInit(&M,2000,NULL); EventInit(0); // add two timer events (indeed event name is shortend to "time" // 4 chars) AddEvent("timer",0,EVTIMER); AddEvent("timer",1,EVTIMER); AddEvent("message",-1,EVMESSAGE); // user message event from all ports AddEvent("signal",0,EVSIGNAL); AddEventSender("signal",0,sendSignal); AddEvent("signal",1,EVSIGNAL); AddEventSender("signal",1,sendSignal); // int sendSignal(event_t *ev, int evindex) {} // AddEvent("signal",0,EVSIGNAL); // AddEventSender("signal",0, sendSignal); // //address_t a1=allocate(&M,&R,"a",MVAR,1); //print_format("$a1=%d\n",a1); //address_t b1=allocate(&M,&R,"b",MVAR,1); //print_format("$b1=%d\n",b1); RegInit(&R0); R0.debug=1; RegInit(&R1); R1.debug=1; if (argc>1) for(int i=1;i= argc) { exit(-1); } i++; nodeindex = atoi(argv[i]); continue; case 'm': if ((i+1) >= argc) { exit(-1); } i++; maxrun = atoi(argv[i]); continue; case 'l': if ((i+2) >= argc) { exit(-1); } i++; portindex = atoi(argv[i]); i++; portfilewr[portindex]=argv[i]; continue; case 'p': if ((i+2) >= argc) { exit(-1); } i++; portindex = atoi(argv[i]); i++; char *rdfile = (char*)malloc(strlen(argv[i])+10), *wrfile = (char*)malloc(strlen(argv[i])+10); sprintf(rdfile,"%s:%d:%d:rx",argv[i],nodeindex,portindex); sprintf(wrfile,"%s:%d:%d:tx",argv[i],nodeindex,portindex); portfilerd[portindex]=rdfile; portfilewr[portindex]=wrfile; continue; case 'P': profile++; continue; case 'S': service=1; continue; } } if (strlen(argv[i])>4 && strcmp(&argv[i][strlen(argv[i])-4],".plx")==0) { input=readFile(argv[i]); } else input=argv[i]; // LexerSetup(&L,input); #if HAS_FUNC > 0 // CODEADD1I(C0->M,SETSP,0); #endif if (profile>1) { int t0=MILLIS(); for(int i=0;i<10000;i++) { Compile(&L,input,&C0,PRUNNING); if (R0.error) { log(LOGERROR,"Compiler error %d(%s) in line %d\n",R0.error,Errors[R0.error],L.line); PrintLexerToken(&L); return -1; } ReleaseSegment(C0.M,C0.S); } int t1=MILLIS(); log(100,"Compiler statistics: %d tokens, compile %d ns, %d ns / token, %d kTPS\n", L.ntoken,(t1-t0)*100,(100*(t1-t0))/L.ntoken, 1000000/((100*(t1-t0))/L.ntoken) ); } if (input) Compile(&L,input,&C0,i==(argc-1)?PRUNNING:0); if (R0.error) { log(LOGERROR,"Compiler error %d(%s) in line %d\n",R0.error,Errors[R0.error],L.line); PrintLexerToken(&L); return -1; } } port_open(); if (verbose || profile) { progopn=PrintCode(&M); } if (compileOnly) return 0; int status; R0.state=input?PRUNNING:PIDLE; R0.steps=maxrun; int t0=MILLIS(); if (!profile) { if (service) { do { Loop(&C0,service); if (R0.error) { log(LOGERROR,"Run-time error %d(%s) at pc=%d\n",R0.error,Errors[R0.error],R0.pc); ContextResetAll(NULL); } R0.error=0; } while (service); } else Loop(&C0,0); } else { R0.steps=10000; do { status=Run(&C0); } while(!R0.error && status==1); } // TODO: Check all context if (R0.error) { log(LOGERROR,"Run-time error %d(%s) at pc=%d\n",R0.error,Errors[R0.error],R0.pc); return -1; } int t1=MILLIS(); if (verbose || profile) { log(100,"VM Op Count=%d, %d MOPS, Token Count=%d, Program Op Count=%d\n",R0.opcount,(t1-t0)>0?(R0.opcount/(t1-t0))/1000:0,L.ntoken,progopn); } if (verbose) { PrintCode(&M); PrintHeap(&M); PrintEvents(&events); context_t *c=Context[0]; while (c) { vLog("+++++++++ Context %d +++++++++\n",CONTEXTID(c)); PrintState(c->R); PrintStack("DS",c->DS); PrintStack("FS",c->FS); c=c->next; } } }