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