コード例 #1
0
ファイル: main.c プロジェクト: paultech/isiCPU
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(&LTUTime);
		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(&LTUTime);
				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, &ltv);
			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;
}
コード例 #2
0
ファイル: main.c プロジェクト: andyleap/isiCPU
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(&LTUTime);
	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(&LTUTime);
			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;
}