ref: 747cddf7870c548043f44adec04b62440e5abd21
parent: d128c76aca17cf3b340c48175d8cdfaaeff40657
author: sirjofri <sirjofri@sirjofri.de>
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);