From f2d7c2481f5e80f10ff99444029d5d1c07855ec5 Mon Sep 17 00:00:00 2001 From: sbosse Date: Mon, 16 Mar 2026 11:10:42 +0100 Subject: [PATCH] Mon 16 Mar 11:09:06 CET 2026 --- src/main.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 src/main.c diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..bcf9d0f --- /dev/null +++ b/src/main.c @@ -0,0 +1,346 @@ +#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; + } + } +} +