Mon 16 Mar 11:09:06 CET 2026
This commit is contained in:
parent
57ef333953
commit
f2d7c2481f
346
src/main.c
Normal file
346
src/main.c
Normal file
|
|
@ -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 <sys/select.h>
|
||||
|
||||
|
||||
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<argc;i++) {
|
||||
if (argv[i][0]=='-') switch (argv[i][1]) {
|
||||
case 'v': verbose++; break;
|
||||
}
|
||||
}
|
||||
if (verbose==1) log_level=LOGINFO;
|
||||
if (verbose==2) log_level=LOGDEBUG1;
|
||||
if (verbose==3) log_level=LOGDEBUG2;
|
||||
if (verbose==4) log_level=LOGDEBUG3;
|
||||
|
||||
log(LOGINFO,">> 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;i++) {
|
||||
if (argv[i][0]=='-') {
|
||||
switch (argv[i][1]) {
|
||||
case 'c': compileOnly=1; continue;
|
||||
case 'v': continue;
|
||||
case 'h':
|
||||
printf("plx vm ver. %s (c) Dr. Stefan Bosse\n",PLX_VERSION);
|
||||
printf("usage: plx [-c(ompileonly)] [-S(ervice)] [-P(rofile)] [-v(erbose)] [-m(axrun) #] [-n(odeid) #id] [-l(inkto) srcportindex dstfifo] [-p(ort) portindex fifo]\n");
|
||||
exit(0);
|
||||
break;
|
||||
case 'n':
|
||||
if ((i+1) >= 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user