int main(int argc, char**argv, char**envp) { FILE* opfile; char * asmtxt; char * binf; int asmlen; int rqrun; int endian; int avcycl; int ssvr; int cux; long nsec_err; long long tcc; uintptr_t gccq = 0; uintptr_t glccq = 0; uintptr_t ccr = 0; uintptr_t lucycles = 0; uintptr_t lucpus = 0; int paddlimit = 0; int dbg; struct timeval ltv; fd_set fds; char cc; dbg = 0; rqrun = 0; avcycl = 0; endian = 0; ssvr = 0; haltnow= 0; binf = NULL; memset(mem, 0, sizeof(short)*0x10000); memset(allcpus, 0, sizeof(allcpus)); int i,k, j , rr; if( argc > 1 ) { for(i = 1; i < argc; i++) { switch(argv[i][0]) { case '-': for(k = 1; k > 0 && argv[i][k] > 31; k++) { switch(argv[i][k]) { case 'T': rqrun = 2; break; case 'r': rqrun = 1; break; case 'c': k = -1; // end search if(i+1 < argc) { opfile = fopen(argv[i+1], "r"); if(!opfile) { perror("Open File"); } else { fprintf(stderr, "Loading file\n"); loadtxtfile(opfile, &asmtxt, &asmlen); fclose(opfile); DCPUASM_asm(asmtxt, asmlen, mem[0]); i++; } } break; case 'e': endian = 2; break; case 's': ssvr = 1; break; case 'D': dbg = 1; break; case 'B': k = -1; if(i+1<argc) { binf = argv[++i]; } break; } } break; default: fprintf(stderr, "\"%s\" Ignored\n", argv[i]); break; } } } else { fprintf(stderr, gsc_usage, argv[0]); return 0; } struct sigaction hnler; hnler.sa_handler = sysfaulthdl; hnler.sa_flags = 0; if(rqrun == 1) { // normal operation ///////////////////////// for(cux = 0; cux < CPUSMAX; cux++) { allcpus[cux].archtype = ARCH_DCPU; allcpus[cux].memsize = 0x10000; allcpus[cux].cpustate = &cpl[cux]; allcpus[cux].memptr = mem[cux]; allcpus[cux].runrate = 10000; // Nano seconds per cycle (100kHz) //allcpus[cux].RunCycles = DCPU_run; // TODO: not used yet allcpus[cux].cyclequeue = 0; // Should always be reset DCPU_init(allcpus[cux].cpustate, allcpus[cux].memptr); HWM_InitLoadout(allcpus[cux].cpustate, 3); HWM_DeviceAdd(allcpus[cux].cpustate, 2); HWM_DeviceAdd(allcpus[cux].cpustate, 0); HWM_DeviceAdd(allcpus[cux].cpustate, 1); HWM_InitAll(allcpus[cux].cpustate); DCPU_sethwqcallback(allcpus[cux].cpustate, HWM_Query); DCPU_sethwicallback(allcpus[cux].cpustate, HWM_HWI); if(binf) { loadbinfile(binf, endian, (char*)allcpus[cux].memptr); } } if(ssvr) { makewaitserver(); sleep(3); } sigaction(SIGINT, &hnler, NULL); for(cux = 0; cux < numberofcpus; cux++) { fetchtime(&allcpus[cux].lrun); } fetchtime(<UTime); lucycles = 0; // how many cycles ran (debugging) cux = 0; // CPU index - currently never changes while(!haltnow) { if(((DCPU*)allcpus[cux].cpustate)->MODE != BURNING) { struct timespec *LRun = &allcpus[cux].lrun; LUTime.tv_sec = LRun->tv_sec; LUTime.tv_nsec = LRun->tv_nsec; fetchtime(LRun); DeltaTime.tv_sec = LRun->tv_sec - LUTime.tv_sec; DeltaTime.tv_nsec = LRun->tv_nsec - LUTime.tv_nsec; DeltaTime.tv_nsec += ccr; if(DeltaTime.tv_sec) { DeltaTime.tv_nsec += 1000000000; } nsec_err = 0; intptr_t ccq = 0; if(allcpus[cux].runrate > 0) { ccq = (DeltaTime.tv_nsec / allcpus[cux].runrate); ccr = (DeltaTime.tv_nsec % allcpus[cux].runrate); ccq += allcpus[cux].cyclequeue; } else { ccq = 0; } if(dbg) { if(lucycles) { DCPU_run(allcpus[cux].cpustate,allcpus[cux].memptr); ((DCPU*)allcpus[cux].cpustate)->cycl = 0; lucycles = 0; showdiag_dcpu((DCPU*)allcpus[cux].cpustate, 1); } } else { if(ccq) { for(j = 1000000000 / allcpus[cux].runrate; ccq && j; j--) { // limit calls //TODO dynamic / multiple CPUs: call the right one. // with memory and state. DCPU_run(allcpus[cux].cpustate,allcpus[cux].memptr); //TODO some hardware may need to work at the same time lucycles += ((DCPU*)allcpus[cux].cpustate)->cycl; ccq -= ((DCPU*)allcpus[cux].cpustate)->cycl; // each op uses cycles, can be negative ((DCPU*)allcpus[cux].cpustate)->cycl = 0; } } allcpus[cux].cyclequeue = ccq; // save when done gccq += ccq; } // If the queue has cycles left over then the server may be overloaded // some CPUs should be slowed or moved to a different server/thread HWM_TickAll(allcpus[cux].cpustate, fdserver,0); } double clkdelta; float clkrate; fetchtime(&TUTime); if(!dbg && TUTime.tv_sec > LTUTime.tv_sec) { // roughly one second between status output showdiag_dcpu((DCPU*)allcpus[0].cpustate, 0); clkdelta = ((double)(TUTime.tv_sec - LTUTime.tv_sec)) + (((double)TUTime.tv_nsec) * 0.000000001); clkdelta-=(((double)LTUTime.tv_nsec) * 0.000000001); if(!lucpus) lucpus = 1; clkrate = ((((double)lucycles) / clkdelta) * 0.001) / numberofcpus; fprintf(stderr, "DC: %.4f sec, %d at %.3f kHz (%d)\r", clkdelta, numberofcpus, clkrate, gccq); showdiag_up(4); fetchtime(<UTime); lucycles = 0; lucpus = 0; } ltv.tv_sec = 0; ltv.tv_usec = 0; FD_ZERO(&fds); FD_SET(0, &fds); // stdin i = select(1, &fds, NULL, NULL, <v); if(i > 0) { i = read(0, &cc, 1); if(i > 0) { switch(cc) { case 10: lucycles = 1; break; case 'l': HWM_TickAll(&cpl[0], fdserver,0x3400); break; case 'x': haltnow = 1; break; default: break; } } } if(!dbg) { cux++; if(cux > numberofcpus - 1) { if(gccq) { if(numberofcpus > CPUSMIN) { if(gccq > glccq) numberofcpus--; } paddlimit = 0; } else { if(numberofcpus < CPUSMAX && paddlimit > 0) { fetchtime(&allcpus[cux].lrun); allcpus[cux].cyclequeue = 0; numberofcpus++; paddlimit--; } else { if(paddlimit < CPUSMAX) paddlimit++; } } cux = 0; glccq = gccq; gccq = 0; } } else { numberofcpus = 1; cux = 0; } if(haltnow) { break; } } HWM_FreeAll(&cpl[0]); shutdown(fdserver, SHUT_RDWR); close(fdserver); } printf("\n"); return 0; }
int main(int argc, char**argv, char**envp) { uint32_t cux; uintptr_t gccq = 0; uintptr_t lucycles = 0; uintptr_t lucpus = 0; struct stats sts = {0, }; int paddlimit = 0; int premlimit = 0; isi_init_contable(); isi_register_objects(); isi_objtable_init(); isi_init_sestable(); isi_inittable(&alldev); isi_inittable(&allcpu); isi_synctable_init(); int i; uint32_t k; if( argc > 1 ) { i = parse_args(argc, argv); if(i) return i; } else { fprintf(stderr, gsc_usage, argv[0], argv[0]); return 0; } if(endf) { unsigned char * mflip; uint32_t rsize; loadbinfile(endf, 1, &mflip, &rsize); savebinfile(endf, 0, mflip, rsize); return 0; } struct sigaction hnler; hnler.sa_handler = sysfaulthdl; hnler.sa_flags = 0; if(redisaddr) { redis_make_session_lu(redisaddr); } if(!rqrun && !flagsvr) { fprintf(stderr, "At least -r or -s must be specified.\n"); return 0; } if(flagsvr) { if(!rqrun) enter_service(); makeserver(listenportnumber); } if(rqrun) { make_interactive(); isi_addcpu(); } sigaction(SIGINT, &hnler, NULL); sigaction(SIGTERM, &hnler, NULL); sigaction(SIGHUP, &hnler, NULL); sigaction(SIGPIPE, &hnler, NULL); fetchtime(<UTime); lucycles = 0; // how many cycles ran (debugging) cux = 0; // CPU index - currently never changes if(rqrun && allcpu.count && ((struct isiCPUInfo*)allcpu.table[cux])->ctl & ISICTL_DEBUG) { showdiag_dcpu(allcpu.table[cux], 1); } while(!haltnow) { struct isiCPUInfo * ccpu; struct isiInfo * ccpi; struct timespec CRun; ccpu = (struct isiCPUInfo*)(ccpi = allcpu.table[cux]); fetchtime(&CRun); if(!allcpu.count) { struct timespec stime = {0, 10000}; nanosleep(&stime, NULL); } else { int ccq = 0; int tcc = numberofcpus * 2; if(tcc < 20) tcc = 20; while(ccq < tcc && isi_time_lt(&ccpi->nrun, &CRun)) { sts.quanta++; ccpi->c->RunCycles(ccpi, CRun); //TODO some hardware may need to work at the same time lucycles += ccpu->cycl; if(rqrun && (ccpu->ctl & ISICTL_TRACE) && (ccpu->cycl)) { showdiag_dcpu(ccpi, 1); } ccpu->cycl = 0; fetchtime(&CRun); ccq++; } if(ccq >= tcc) gccq++; sts.cpusched++; fetchtime(&CRun); if(ccpi->updev.t && ccpi->updev.t->c->RunCycles) { ccpi->updev.t->c->RunCycles(ccpi->updev.t, CRun); } } fetchtime(&CRun); isi_run_sync(CRun); fetchtime(&CRun); if(CRun.tv_sec > LTUTime.tv_sec) { // roughly one second between status output if(rqrun && !flagdbg) { // interactive diag double clkdelta; float clkrate; if(allcpu.count) showdiag_dcpu(allcpu.table[0], 0); clkdelta = ((double)(CRun.tv_sec - LTUTime.tv_sec)) + (((double)CRun.tv_nsec) * 0.000000001); clkdelta-=(((double)LTUTime.tv_nsec) * 0.000000001); if(!lucpus) lucpus = 1; clkrate = ((((double)lucycles) * clkdelta) * 0.001) / numberofcpus; fprintf(stderr, "DC: %.4f sec, %d at % 9.3f kHz (% 8ld) [Q:% 8d, S:% 8d, SC:% 8d]\r", clkdelta, numberofcpus, clkrate, gccq, sts.quanta, sts.cpusched, sts.cpusched / numberofcpus ); if(allcpu.count) showdiag_up(4); } fetchtime(<UTime); if(gccq >= sts.cpusched / numberofcpus ) { if(numberofcpus > softcpumin) { numberofcpus--; if(rqrun) fprintf(stderr, "TODO: Offline a CPU\n"); premlimit--; paddlimit = 0; } } else { if(numberofcpus < softcpumax) { //fetchtime(&allcpus[numberofcpus].nrun); //isi_addtime(&allcpus[numberofcpus].nrun, quantum); numberofcpus++; if(rqrun) fprintf(stderr, "TODO: Online a CPU\n"); } } lucycles = 0; lucpus = 0; gccq = 0; memset(&sts, 0, sizeof(struct stats)); if(premlimit < 20) premlimit+=10; if(paddlimit < 20) paddlimit+=2; for(k = 0; k < allses.count; k++) { struct isiSession *ses = allses.table[k]; if(ses->LTick) ses->LTick(ses, CRun); } } if(allses.pcount != allses.count) { if(allses.ptable) { free(allses.ptable); allses.ptable = 0; } allses.pcount = allses.count; allses.ptable = (struct pollfd*)isi_alloc(sizeof(struct pollfd) * allses.pcount); if(!allses.ptable) { isilogerr("malloc poll table fails!"); } i = 0; for(k = 0; k < allses.count; k++) { allses.ptable[i].fd = allses.table[k]->sfd; allses.ptable[i].events = POLLIN; i++; } } if(allses.ptable) { i = poll(allses.ptable, allses.pcount, 0); } else { i = 0; } for(k = 0; k < allses.count; k++) { struct isiSession *ses = allses.table[k]; if(ses && ses->STick && (ses->cmdqstart != ses->cmdqend)) ses->STick(ses, CRun); } if(i > 0) { for(k = 0; k < allses.pcount; k++) { if(!allses.ptable[k].revents) continue; struct isiSession *ses = allses.table[k]; const char *etxt = 0; /* Here be dragons */ switch(allses.ptable[k].revents) { case POLLERR: etxt = "poll: FD error\n"; goto sessionerror; case POLLHUP: etxt = "poll: FD hangup\n"; goto sessionerror; case POLLNVAL: etxt = "poll: FD invalid\n"; goto sessionerror; default: if(allses.ptable[k].revents & POLLIN) { if(ses->sfd == allses.ptable[k].fd) { if(ses->Recv(ses, CRun)) goto sessionerror; } else { isilog(L_ERR, "netses: session ID error\n"); } } } continue; sessionerror: if(etxt) isilog(L_ERR, etxt); if(ses->sfd == allses.ptable[k].fd) { isi_delete_ses(ses); k = allses.pcount; } } } if(!flagdbg) { cux++; if(!(cux < allcpu.count)) { cux = 0; } } else { numberofcpus = 1; cux = 0; } if(haltnow) { break; } } if(flagsvr) { isilog(L_WARN, "closing connections\n"); while(allses.count) { isi_delete_ses(allses.table[0]); } } while(allobj.count) { isi_delete_object(allobj.table[0]); } if(rqrun) printf("\n\n\n\n"); return 0; }