shithub: gpufs

Download patch

ref: 747cddf7870c548043f44adec04b62440e5abd21
parent: d128c76aca17cf3b340c48175d8cdfaaeff40657
author: sirjofri <[email protected]>
date: Sun Feb 11 18:51:52 EST 2024

makes dasm more standalone, draft fs layout

- most code for spirvd is now in spirvd
- cops (compile-ops) and dops (disasm-ops) are now separate
- basic filesystem layout in gpufs

--- /dev/null
+++ b/cops.c
@@ -1,0 +1,100 @@
+#include <u.h>
+#include <libc.h>
+#include "vm.h"
+#include "ops.h"
+#include "names.h"
+
+extern int debug;
+extern int compile;
+
+void
+printresult(int should, uint varid)
+{
+	char *s;
+	
+	if (!should) {
+		print("%10s   ", " ");
+		return;
+	}
+	s = smprint("$%d", varid);
+	print("%10s = ", s);
+	free(s);
+}
+
+void
+OpTypeFloat(Frame *f, u32int)
+{
+	u32int varid = *(f->pc+1);
+	u32int tlen = *(f->pc+2);
+	
+	if (compile) {
+		printresult(1, varid);
+		print("OpTypeFloat %d\n", tlen);
+		return;
+	}
+}
+
+void
+OpTypeInt(Frame *f, u32int)
+{
+	u32int varid = *(f->pc+1);
+	u32int tlen = *(f->pc+2);
+	
+	if (compile) {
+		printresult(1, varid);
+		print("OpTypeInt %d\n", tlen);
+		return;
+	}
+}
+
+void
+OpName(Frame *f, u32int)
+{
+	u32int varid = *(f->pc+1);
+	char *varname = (char*)(f->pc+2);
+	
+	nameadd(varid, varname);
+	
+	if (compile) {
+		printresult(0, 0);
+		print("OpName $%d \"%s\"\n", varid, varname);
+		return;
+	}
+}
+
+void
+OpNop(Frame*, u32int)
+{
+	if (compile) {
+		printresult(0, 0);
+		print("OpNop\n");
+	}
+}
+
+Op oplist[] = {
+	{  5, OpName },
+	{ 21, OpTypeInt },
+	{ 22, OpTypeFloat },
+	{ nil, OpNop },
+};
+
+int
+oplookup(u32int code, void (**f)(Frame*,u32int))
+{
+	Op *o;
+	u32int c = code & 0x0000ffff;
+	if (c == 0) {
+		*f = OpNop;
+		return 1;
+	}
+	
+	for (o = oplist; o->opcode; o++) {
+		if (c == o->opcode) {
+			*f = o->f;
+			return 1;
+		}
+	}
+	
+	werrstr("operation (%d) not supported!", c);
+	return 0;
+}
--- /dev/null
+++ b/dops.c
@@ -1,0 +1,183 @@
+#include <u.h>
+#include <libc.h>
+#include "vm.h"
+#include "ops.h"
+#include "names.h"
+
+extern int debug;
+
+void
+printresult(int should, uint varid)
+{
+	char *s;
+	
+	if (!should) {
+		print("%10s   ", " ");
+		return;
+	}
+	s = smprint("$%d", varid);
+	print("%10s = ", s);
+	free(s);
+}
+
+void
+OpTypeVoid(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	
+	printresult(1, varid);
+	print("OpTypeVoid\n");
+}
+
+void
+OpTypeBool(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	
+	printresult(1, varid);
+	print("OpTypeBool\n");
+}
+
+void
+OpTypeInt(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	u32int tlen = f->pc[2];
+	
+	printresult(1, varid);
+	print("OpTypeInt %d\n", tlen);
+}
+
+void
+OpTypeFloat(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	u32int tlen = f->pc[2];
+	
+	printresult(1, varid);
+	print("OpTypeFloat %d\n", tlen);
+}
+
+void
+OpTypeVector(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	u32int ttype = f->pc[2];
+	u32int tlen = f->pc[3];
+	
+	printresult(1, varid);
+	print("OpTypeFloat $%d %d\n", ttype, tlen);
+}
+
+void
+OpTypeMatrix(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	u32int ctype = f->pc[2];
+	u32int tlen = f->pc[3];
+	
+	printresult(1, varid);
+	print("OpTypeFloat $%d %d\n", ctype, tlen);
+}
+
+void
+OpName(Frame *f, u32int)
+{
+	u32int varid = f->pc[1];
+	char *varname = (char*)&f->pc[2];
+	
+	nameadd(varid, varname);
+	
+	printresult(0, 0);
+	print("OpName $%d \"%s\"\n", varid, varname);
+}
+
+void
+OpNop(Frame*, u32int)
+{
+	printresult(0, 0);
+	print("OpNop\n");
+}
+
+void
+OpUndef(Frame*, u32int)
+{
+	printresult(0, 0);
+	print("OpUndef\n");
+}
+
+void
+OpSource(Frame* f, u32int len)
+{
+	u32int slang = f->pc[1];
+	u32int version = f->pc[2];
+	u32int file = 0;
+	short hasfile = 0;
+	char* filename;
+	
+	if (len > 3) {
+		hasfile = 1;
+		file = f->pc[3];
+	}
+	
+	printresult(0, 0);
+	print("OpSource %d %d", slang, version);
+	if (hasfile) {
+		filename = strlookup(file);
+		print(" %s", filename);
+	}
+	print("\n");
+}
+
+void
+OpTypeFunction(Frame *f, u32int len)
+{
+	u32int varid = f->pc[1];
+	u32int rettype = f->pc[2];
+	u32int* argv = &f->pc[3];
+	u32int argc = len - 2;
+	
+	printresult(1, varid);
+	print("OpTypeFunction $%d", rettype);
+	
+	for (int i = 0; i < argc; i++) {
+		u32int v = argv[i];
+		print(" $%d", v);
+	}
+	print("\n");
+}
+
+Op oplist[] = {
+	{  1, OpUndef },
+	{  3, OpSource },
+	{  5, OpName },
+	{ 19, OpTypeVoid },
+	{ 20, OpTypeBool },
+	{ 21, OpTypeInt },
+	{ 22, OpTypeFloat },
+	{ 23, OpTypeVector },
+	{ 24, OpTypeMatrix },
+	{ 33, OpTypeFunction },
+	{ nil, OpNop },
+};
+
+int
+oplookup(u32int code, void (**f)(Frame*,u32int))
+{
+	Op *o;
+	u32int c = code & 0x0000ffff;
+	if (c == 0) {
+		*f = OpNop;
+		return 1;
+	}
+	
+	for (o = oplist; o->opcode; o++) {
+		if (c == o->opcode) {
+			*f = o->f;
+			return 1;
+		}
+	}
+	
+	werrstr("operation (%d) not supported!", c);
+	return 0;
+}
--- a/gpufs.c
+++ b/gpufs.c
@@ -1,35 +1,411 @@
 #include <u.h>
 #include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
 #include "vm.h"
 
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-d]\n", argv0);
+	exits("usage");
+}
+
+void*
+emalloc(int n)
+{
+	void *v;
+	v = emalloc9p(n);
+	setmalloctag(v, getcallerpc(&n));
+	memset(v, 0, n);
+	return v;
+}
+
+char*
+estrdup(char *s)
+{
+	s = estrdup9p(s);
+	setmalloctag(s, getcallerpc(&s));
+	return s;
+}
+
+enum {
+	Qroot,
+		Qrctl,
+		Qobject,
+			Qctl,
+			Qbuffer,
+			Qshader,
+};
+
+static char *nametab[] = {
+	"/",
+		"ctl",
+		nil,
+			"ctl",
+			"buffer",
+			"shader",
+};
+
+typedef struct Gpuobject Gpuobject;
+struct Gpuobject {
+	Ref;
+	int type;
+};
+
+typedef struct Gpufid Gpufid;
+struct Gpufid {
+	int level;
+	Gpuobject *object;
+};
+
+static Gpuobject objects[256];
+static int nobjects = 0;
+
+#define OBJECTID(c) ((int)(((Gpuobject*)(c)) - objects))
+
 int debug = 0;
-int disassemble = 0;
+int compile = 0;
 
+static char *user;
+static long time0;
+
 u32int magic = 0x07230203;
 
-u32int testprog[2048];
+static void
+freeobject(Gpuobject *obj)
+{
+	if (obj == nil || decref(obj))
+		return;
+	
+	memset(obj, 0, sizeof(*obj));
+}
 
-void
-main(int argc, char **argv)
+static void*
+wfaux(Gpufid *f)
 {
-	int r = 0;
+	if (f->level < Qobject)
+		return nil;
+	return f->object;
+}
+
+static void
+fsmkqid(Qid *q, int level, void *aux)
+{
+	q->type = 0;
+	q->vers = 0;
 	
-	ARGBEGIN{
-	case 'd':
-		debug++;
+	switch (level) {
+	case Qroot:
+	case Qobject:
+		q->type = QTDIR;
+	default:
+		q->path = (level<<24) | (((uintptr)aux ^ time0) & 0x00ffffff);
+	}
+}
+
+static void
+fsmkdir(Dir *d, int level, void *aux)
+{
+	char buf[1024];
+	
+	memset(d, 0, sizeof(*d));
+	fsmkqid(&d->qid, level, aux);
+	d->mode = 0666;
+	d->atime = d->mtime = time0;
+	d->uid = estrdup(user);
+	d->gid = estrdup(user);
+	d->muid = estrdup(user);
+	if (d->qid.type & QTDIR)
+		d->mode |= DMDIR | 0111;
+	
+	switch (level) {
+	case Qobject:
+		snprint(buf, sizeof(buf), "%d", OBJECTID(aux));
+		d->name = estrdup(buf);
 		break;
-	}ARGEND;
+	case Qrctl:
+	case Qctl:
+	case Qbuffer:
+	case Qshader:
+		d->mode = 0666;
+	default:
+		d->name = estrdup(nametab[level]);
+	}
+}
+
+static int
+rootgen(int i, Dir *d, void*)
+{
+	i += Qroot + 1;
+	if (i < Qobject) {
+		fsmkdir(d, i, 0);
+		return 0;
+	}
+	i -= Qobject;
+	if (i < nobjects) {
+		fsmkdir(d, Qobject, &objects[i]);
+		return 0;
+	}
+	return -1;
+}
+
+static int
+objectgen(int i, Dir *d, void *aux)
+{
+	i += Qobject + 1;
+	fsmkdir(d, i, aux);
 	
-	if (argc) {
-		r = open(argv[0], OREAD);
+	// Qshader is last file in list
+	if (i == Qshader)
+		return -1;
+	return 0;
+}
+
+static void
+fsread(Req *r)
+{
+	//char buf[1024];
+	Gpufid *f;
+	
+	f = r->fid->aux;
+	switch (f->level) {
+	case Qroot:
+		dirread9p(r, rootgen, nil);
+		respond(r, nil);
+		return;
+	case Qobject:
+		dirread9p(r, objectgen, f->object);
+		respond(r, nil);
+		return;
+	case Qrctl:
+		respond(r, nil);
+		return;
 	}
+	respond(r, "not implemented");
+}
+
+static void
+fsstart(Srv*)
+{
+}
+
+static void
+fsend(Srv*)
+{
+	postnote(PNGROUP, getpid(), "shutdown");
+	exits(nil);
+}
+
+static void
+fsattach(Req *r)
+{
+	Gpufid *f;
 	
-	read(r, testprog, 2048);
+	if (r->ifcall.aname && r->ifcall.aname[0]) {
+		respond(r, "invalid attach specifier");
+		return;
+	}
 	
-	if (*testprog != magic) {
-		fprint(2, "bad magic! got: %x\n", *testprog);
+	f = emalloc(sizeof(*f));
+	f->level = Qroot;
+	fsmkqid(&r->fid->qid, f->level, wfaux(f));
+	r->ofcall.qid = r->fid->qid;
+	r->fid->aux = f;
+	respond(r, nil);
+}
+
+static void
+fsstat(Req *r)
+{
+	Gpufid *f;
+	
+	f = r->fid->aux;
+	fsmkdir(&r->d, f->level, wfaux(f));
+	respond(r, nil);
+}
+
+static char*
+fswalk1(Fid *fid, char *name, Qid *qid)
+{
+	Gpufid *f;
+	int i, j;
+	
+	if (!(fid->qid.type & QTDIR))
+		return "walk in non-directory";
+	
+	f = fid->aux;
+	if (strcmp(name, "..") == 0) {
+		switch (f->level) {
+		case Qroot:
+			break;
+		case Qobject:
+			freeobject(f->object);
+			break;
+		default:
+			f->level = Qobject;
+		}
+	} else {
+		for (i = f->level+1; i < nelem(nametab); i++) {
+			if (nametab[i]) {
+				if (strcmp(name, nametab[i]) == 0)
+					break;
+			}
+			if (i == Qobject) {
+				j = atoi(name);
+				if (j >= 0 && j < nobjects) {
+					f->object = &objects[j];
+					incref(f->object);
+					break;
+				}
+			}
+		}
+		if (i >= nelem(nametab))
+			return "directory entry not found";
+		f->level = i;
+	}
+	fsmkqid(qid, f->level, wfaux(f));
+	fid->qid = *qid;
+	return nil;
+}
+
+static void
+fsopen(Req *r)
+{
+	respond(r, nil);
+}
+
+static int
+newshader(void)
+{
+	Gpuobject *o = &objects[nobjects];
+	memset(o, 0, sizeof(*o));
+	o->type = Qshader;
+	return nobjects++;
+}
+
+static int
+newbuffer(void)
+{
+	Gpuobject *o = &objects[nobjects];
+	memset(o, 0, sizeof(*o));
+	o->type = Qbuffer;
+	return nobjects++;
+}
+
+static void
+procrootcommand(int argc, char **argv)
+{
+	// n(ew) s(hader)
+	// n(ew) b(uffer)
+	
+	if (argc == 2) {
+		if (strcmp(argv[0], "n") == 0) {
+			if (strcmp(argv[1], "s") == 0) {
+				newshader();
+				return;
+			}
+			if (strcmp(argv[1], "b") == 0) {
+				newbuffer();
+				return;
+			}
+		}
+	}
+}
+
+static void
+rootcommand(char *cmd)
+{
+	char *lines[10];
+	int linec;
+	
+	linec = getfields(cmd, lines, 10, 1, "\n");
+	
+	for (int i = 0; i < linec; i++) {
+		char *c[10];
+		int num = getfields(lines[i], c, 10, 1, " \t");
+		procrootcommand(num, c);
+	}
+}
+
+static void
+fswrite(Req *r)
+{
+	Gpufid *f;
+	int n;
+	char *s;
+	
+	f = r->fid->aux;
+	switch (f->level) {
+	case Qrctl:
+		n = r->ofcall.count = r->ifcall.count;
+		s = emalloc(n+1);
+		memmove(s, r->ifcall.data, n);
+		rootcommand(s);
+		respond(r, nil);
 		return;
 	}
+	respond(r, "not implemented");
+}
+
+static void
+fsdestroyfid(Fid *fid)
+{
+	Gpufid *f;
 	
-	vmrun(testprog+1);
+	if (f = fid->aux) {
+		fid->aux = nil;
+		freeobject(f->object);
+		free(f);
+	}
+}
+
+static char*
+fsclone(Fid *oldfid, Fid *newfid)
+{
+	Gpufid *f, *o;
+	
+	o = oldfid->aux;
+	if (o == nil)
+		return "bad fid";
+	f = emalloc(sizeof(*f));
+	memmove(f, o, sizeof(*f));
+	if (f->object)
+		incref(f->object);
+	newfid->aux = f;
+	return nil;
+}
+
+Srv fs = {
+	.start = fsstart,
+	.attach = fsattach,
+	.stat = fsstat,
+	.walk1 = fswalk1,
+	.clone = fsclone,
+	.open = fsopen,
+	.read = fsread,
+	.write = fswrite,
+	.destroyfid = fsdestroyfid,
+	.end = fsend,
+};
+
+void
+main(int argc, char **argv)
+{
+	char *mtpt = "/mnt/gpu";
+	char *service = nil;
+	time0 = time(0);
+	user = getuser();
+	
+	ARGBEGIN {
+	case 'd':
+		debug++;
+		break;
+	} ARGEND;
+	
+	rfork(RFNOTEG);
+	
+	postmountsrv(&fs, service, mtpt, MREPL);
+	exits(nil);
 }
--- a/mkfile
+++ b/mkfile
@@ -6,5 +6,5 @@
 
 </sys/src/cmd/mkmany
 
-$O.gpufs:	gpufs.$O vm.$O ops.$O names.$O
-$O.spirvd:	spirvd.$O vm.$O ops.$O names.$O
+$O.gpufs:	gpufs.$O vm.$O cops.$O names.$O
+$O.spirvd:	spirvd.$O dops.$O names.$O
--- a/names.c
+++ b/names.c
@@ -3,6 +3,7 @@
 #include "names.h"
 
 Name *names = nil;
+String *strings = nil;
 
 void
 nameadd(uint id, char *name)
@@ -16,6 +17,18 @@
 	names = n;
 }
 
+void
+stringadd(uint id, char *str)
+{
+	String *s;
+	
+	s = malloc(sizeof(String));
+	s->str = strdup(str);
+	s->id = id;
+	s->next = strings;
+	strings = s;
+}
+
 char*
 namelookup(uint id)
 {
@@ -24,6 +37,18 @@
 	for (n = names; n; n = n->next) {
 		if (n->id == id)
 			return n->name;
+	}
+	return nil;
+}
+
+char*
+strlookup(uint id)
+{
+	String *s;
+	
+	for (s = strings; s; s = s->next) {
+		if (s->id == id)
+			return s->str;
 	}
 	return nil;
 }
--- a/names.h
+++ b/names.h
@@ -5,5 +5,15 @@
 	Name *next;
 };
 
+typedef struct String String;
+struct String {
+	uint id;
+	char *str;
+	String *next;
+};
+
 void nameadd(uint id, char *name);
 char *namelookup(uint id);
+
+void stringadd(uint id, char *str);
+char *strlookup(uint id);
--- a/ops.c
+++ /dev/null
@@ -1,100 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "vm.h"
-#include "ops.h"
-#include "names.h"
-
-extern int debug;
-extern int disassemble;
-
-void
-printresult(int should, uint varid)
-{
-	char *s;
-	
-	if (!should) {
-		print("%10s   ", " ");
-		return;
-	}
-	s = smprint("$%d", varid);
-	print("%10s = ", s);
-	free(s);
-}
-
-void
-OpTypeFloat(Frame *f, u32int)
-{
-	u32int varid = *(f->pc+1);
-	u32int tlen = *(f->pc+2);
-	
-	if (disassemble) {
-		printresult(1, varid);
-		print("OpTypeFloat %d\n", tlen);
-		return;
-	}
-}
-
-void
-OpTypeInt(Frame *f, u32int)
-{
-	u32int varid = *(f->pc+1);
-	u32int tlen = *(f->pc+2);
-	
-	if (disassemble) {
-		printresult(1, varid);
-		print("OpTypeInt %d\n", tlen);
-		return;
-	}
-}
-
-void
-OpName(Frame *f, u32int)
-{
-	u32int varid = *(f->pc+1);
-	char *varname = (char*)(f->pc+2);
-	
-	nameadd(varid, varname);
-	
-	if (disassemble) {
-		printresult(0, 0);
-		print("OpName $%d \"%s\"\n", varid, varname);
-		return;
-	}
-}
-
-void
-OpNop(Frame*, u32int)
-{
-	if (disassemble) {
-		printresult(0, 0);
-		print("OpNop\n");
-	}
-}
-
-Op oplist[] = {
-	{  5, OpName },
-	{ 21, OpTypeInt },
-	{ 22, OpTypeFloat },
-	{ nil, OpNop },
-};
-
-int
-oplookup(u32int code, void (**f)(Frame*,u32int))
-{
-	Op *o;
-	u32int c = code & 0x0000ffff;
-	if (c == 0) {
-		*f = OpNop;
-		return 1;
-	}
-	
-	for (o = oplist; o->opcode; o++) {
-		if (c == o->opcode) {
-			*f = o->f;
-			return 1;
-		}
-	}
-	
-	werrstr("operation (%d) not supported!", c);
-	return 0;
-}
--- a/ops.h
+++ b/ops.h
@@ -1,3 +1,9 @@
+typedef struct Frame Frame;
+struct Frame {
+	u32int *pc;
+	Frame *next;
+};
+
 typedef struct Op Op;
 struct Op {
 	u32int opcode;
--- a/spirvd.c
+++ b/spirvd.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <libc.h>
 #include "vm.h"
+#include "ops.h"
 
 int debug = 0;
 int disassemble = 1;
@@ -9,7 +10,42 @@
 
 u32int testprog[2048];
 
+Frame stack;
+
+u32int
+runinst(u32int *ptr)
+{
+	u32int len, opcode;
+	void (*func)(Frame*,u32int);
+	
+	opcode = (*ptr) & 0x0000ffff;
+	len = ((*ptr) & 0xffff0000) >> 16;
+	
+	if (oplookup(opcode, &func)) {
+		func(&stack, len);
+		
+		// if (func) changes pc, ignore it
+		if (ptr == stack.pc) {
+			stack.pc += len;
+		}
+		return len;
+	}
+	fprint(2, "error: %r\n");
+	return 0;
+}
+
 void
+dasm(u32int *ptr)
+{
+	stack.pc = ptr;
+	stack.next = nil;
+	
+	while (runinst(stack.pc)) {
+		;
+	}
+}
+
+void
 main(int argc, char **argv)
 {
 	int r = 0;
@@ -31,5 +67,5 @@
 		return;
 	}
 	
-	vmrun(testprog+1);
+	dasm(testprog+1);
 }
--- a/vm.h
+++ b/vm.h
@@ -1,9 +1,3 @@
-typedef struct Frame Frame;
-struct Frame {
-	u32int *pc;
-	Frame *next;
-};
-
 void vmrun(u32int *ptr);
 void runstack(u32int *ptr);
 void retstack(void);