libFPVM eval, complete, untested
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Tue, 30 Mar 2010 12:10:32 +0000 (14:10 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Tue, 30 Mar 2010 12:10:32 +0000 (14:10 +0200)
presets/Aderrasi - Candy Avian.milk
software/demo/Makefile
software/demo/apipe.c
software/demo/eval.c
software/demo/eval.h
software/demo/renderer.c
software/include/fpvm/fpvm.h
software/libfpvm/Makefile
software/libfpvm/fpvm.c
software/libfpvm/gfpus.c
software/libfpvm/x86-linux/test.c

index 88082ba..f8108fd 100644 (file)
@@ -67,13 +67,10 @@ per_frame_3=wave_g = wave_g + 0.4*sin(1.34*time) + 0.25*sin(2.34*time);
 per_frame_4=ib_r = 4;\r
 per_frame_5=ib_g = 0;\r
 per_frame_6=ib_b = 0;\r
-per_frame_7=wave_x = wave_x +\r
-per_frame_8=if(above(wave_y,0.75),0.40*sin(time), 0.15*sin(time));\r
+per_frame_7=wave_x = wave_x + if(above(wave_y,0.75),0.40*sin(time), 0.15*sin(time));\r
 per_frame_9=wave_y = wave_y + 0.30*cos(0.9*time);\r
-per_frame_10=cx = cx +\r
-per_frame_11=if(above(wave_x,0.5), +0.0*sin(7*treb_att), -0.0*sin(7*mid_att));\r
-per_frame_12=cy = cy +\r
-per_frame_13=if(above(wave_x,0.5), +0.0*cos(7*bass_att), -0.0*cos(7*mid_att));\r
+per_frame_10=cx = cx + if(above(wave_x,0.5), 0.001*sin(7*treb_att), -0.001*sin(7*mid_att));\r
+per_frame_12=cy = cy + if(above(wave_x,0.5), 0.001*cos(7*bass_att), -0.001*cos(7*mid_att));\r
 per_frame_14=ob_r = 0.5*sin(treb)*time;\r
 per_frame_15=ob_b = 0.5*sin(mid)*0.9*time;\r
 per_frame_16=ob_g = 0.5*sin(bass)*0.8*time;\r
index 17bfca5..1efe030 100644 (file)
@@ -52,7 +52,9 @@ eval.o: ../../software/include/base/stdio.h
 eval.o: ../../software/include/base/stdlib.h
 eval.o: ../../software/include/base/string.h ../../software/include/hw/pfpu.h
 eval.o: ../../software/include/hw/common.h ../../software/include/hw/tmu.h
-eval.o: ../../software/include/hal/pfpu.h eval.h
+eval.o: ../../software/include/hal/pfpu.h ../../software/include/fpvm/fpvm.h
+eval.o: ../../software/include/fpvm/is.h ../../software/include/fpvm/gfpus.h
+eval.o: eval.h renderer.h
 isr.o: ../../software/include/hw/interrupts.h
 isr.o: ../../software/include/base/irq.h ../../software/include/base/uart.h
 isr.o: ../../software/include/hal/time.h ../../software/include/hal/slowout.h
@@ -83,6 +85,7 @@ memstats.o: ../../software/include/hw/fmlmeter.h
 memstats.o: ../../software/include/hw/common.h
 renderer.o: ../../software/include/base/stdio.h
 renderer.o: ../../software/include/base/stdlib.h
+renderer.o: ../../software/include/base/string.h
 renderer.o: ../../software/include/base/math.h
 renderer.o: ../../software/include/base/system.h
 renderer.o: ../../software/include/hal/pfpu.h
index 33a724c..dd1eb9f 100644 (file)
@@ -198,7 +198,7 @@ static void pfv_callback(struct pfpu_td *td)
 
        rpipe_frame->tex_wrap = eval_read_pfv(pfv_tex_wrap) != 0.0;
 
-       eval_pfv_to_pvv();
+       eval_transfer_pvv_regs();
        eval_pvv_fill_td(&pfpu_td, &rpipe_frame->vertices[0][0], pvv_callback, rpipe_frame);
        pfpu_submit_task(&pfpu_td);
 }
index 355f854..be7b605 100644 (file)
 
 #include <hal/pfpu.h>
 #include <fpvm/fpvm.h>
+#include <fpvm/gfpus.h>
+#include <fpvm/pfpu.h>
 
 #include "eval.h"
 #include "renderer.h"
 
-//#define EVAL_DEBUG
+#define EVAL_DEBUG
 
 /****************************************************************/
 /* GENERAL                                                      */
 /****************************************************************/
 
-static float pfv_initial[EVAL_PFV_COUNT];              /* < preset initial conditions */
-static int pfv_allocation[EVAL_PFV_COUNT];             /* < where per-frame variables are mapped in PFPU regf, -1 if unmapped */
-static int perframe_prog_length;                       /* < how many instructions in perframe_prog */
-static pfpu_instruction perframe_prog[PFPU_PROGSIZE];  /* < PFPU per-frame microcode */
-static float perframe_regs_init[PFPU_REG_COUNT];       /* < PFPU regf according to initial conditions and constants */
-static float perframe_regs_current[PFPU_REG_COUNT];    /* < PFPU regf local copy (keeps data when PFPU is reloaded) */
-
-static int pvv_allocation[EVAL_PVV_COUNT];             /* < where per-vertex variables are mapped in PFPU regf, -1 if unmapped */
-static int pervertex_prog_length;                      /* < how many instructions in pervertex_prog */
-static pfpu_instruction pervertex_prog[PFPU_PROGSIZE]; /* < PFPU per-vertex microcode */
-static float pervertex_regs[PFPU_REG_COUNT];           /* < PFPU regf according to per-frame variables, initial conditions and constants */
-
-static void eval_load_defaults();
+static void load_defaults();
+static int init_pfv();
+static int finalize_pfv();
+static int schedule_pfv();
+static int init_pvv();
+static int finalize_pvv();
+static int schedule_pvv();
 
-void eval_init()
+int eval_init()
 {
-       eval_load_defaults();
+       load_defaults();
+       if(!init_pfv()) return 0;
+       if(!init_pvv()) return 0;
+       return 1;
 }
 
 int eval_schedule()
 {
-       return 1;
+       if(!finalize_pfv()) return 0;
+       if(!schedule_pfv()) return 0;
+       
+       if(!finalize_pvv()) return 0;
+       if(!schedule_pvv()) return 0;
+       
+       return 0;
 }
 
 /****************************************************************/
 /* PER-FRAME VARIABLES                                          */
 /****************************************************************/
 
+static struct fpvm_fragment pfv_fragment;
+static float pfv_initial[EVAL_PFV_COUNT];              /* < preset initial conditions */
+static int pfv_preallocation[EVAL_PFV_COUNT];          /* < where per-frame variables can be mapped in PFPU regf */
+static int pfv_allocation[EVAL_PFV_COUNT];             /* < where per-frame variables are mapped in PFPU regf, -1 if unmapped */
+static int perframe_prog_length;                       /* < how many instructions in perframe_prog */
+static unsigned int perframe_prog[PFPU_PROGSIZE];      /* < PFPU per-frame microcode */
+static float perframe_regs[PFPU_REG_COUNT];            /* < PFPU regf local copy */
+
 static const char pfv_names[EVAL_PFV_COUNT][FPVM_MAXSYMLEN] = {
        "cx",
        "cy",
@@ -128,7 +141,7 @@ int eval_pfv_from_name(const char *name)
        return -1;
 }
 
-static void eval_load_defaults()
+static void load_defaults()
 {
        int i;
 
@@ -155,70 +168,21 @@ void eval_set_initial(int pfv, float x)
        pfv_initial[pfv] = x;
 }
 
-void eval_reset_pfv()
-{
-       int i;
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               perframe_regs_current[i] = perframe_regs_init[i];
-}
-
 int eval_reinit_pfv(int pfv)
 {
        int r;
 
        r = pfv_allocation[pfv];
        if(r < 0) return 0;
-       perframe_regs_current[r] = perframe_regs_init[r];
+       perframe_regs[r] = pfv_initial[pfv];
        return 1;
 }
 
 void eval_reinit_all_pfv()
 {
-       eval_reinit_pfv(pfv_cx);
-       eval_reinit_pfv(pfv_cy);
-       eval_reinit_pfv(pfv_rot);
-       eval_reinit_pfv(pfv_dx);
-       eval_reinit_pfv(pfv_dy);
-       eval_reinit_pfv(pfv_zoom);
-       eval_reinit_pfv(pfv_decay);
-       
-       eval_reinit_pfv(pfv_wave_mode);
-       eval_reinit_pfv(pfv_wave_scale);
-       eval_reinit_pfv(pfv_wave_additive);
-       eval_reinit_pfv(pfv_wave_usedots);
-       eval_reinit_pfv(pfv_wave_maximize_color);
-       eval_reinit_pfv(pfv_wave_thick);
-       
-       eval_reinit_pfv(pfv_wave_x);
-       eval_reinit_pfv(pfv_wave_y);
-       eval_reinit_pfv(pfv_wave_r);
-       eval_reinit_pfv(pfv_wave_g);
-       eval_reinit_pfv(pfv_wave_b);
-       eval_reinit_pfv(pfv_wave_a);
-
-       eval_reinit_pfv(pfv_ob_size);
-       eval_reinit_pfv(pfv_ob_r);
-       eval_reinit_pfv(pfv_ob_g);
-       eval_reinit_pfv(pfv_ob_b);
-       eval_reinit_pfv(pfv_ob_a);
-
-       eval_reinit_pfv(pfv_ib_size);
-       eval_reinit_pfv(pfv_ib_r);
-       eval_reinit_pfv(pfv_ib_g);
-       eval_reinit_pfv(pfv_ib_b);
-       eval_reinit_pfv(pfv_ib_a);
-
-       eval_reinit_pfv(pfv_mv_x);
-       eval_reinit_pfv(pfv_mv_y);
-       eval_reinit_pfv(pfv_mv_dx);
-       eval_reinit_pfv(pfv_mv_dy);
-       eval_reinit_pfv(pfv_mv_l);
-       eval_reinit_pfv(pfv_mv_r);
-       eval_reinit_pfv(pfv_mv_g);
-       eval_reinit_pfv(pfv_mv_b);
-       eval_reinit_pfv(pfv_mv_a);
-       
-       eval_reinit_pfv(pfv_tex_wrap);
+       int i;
+       for(i=0;i<EVAL_PFV_COUNT;i++)
+               eval_reinit_pfv(i);
 }
 
 float eval_read_pfv(int pfv)
@@ -226,17 +190,81 @@ float eval_read_pfv(int pfv)
        if(pfv_allocation[pfv] < 0)
                return pfv_initial[pfv];
        else
-               return perframe_regs_current[pfv_allocation[pfv]];
+               return perframe_regs[pfv_allocation[pfv]];
 }
 
 void eval_write_pfv(int pfv, float x)
 {
        if(pfv_allocation[pfv] >= 0)
-               perframe_regs_current[pfv_allocation[pfv]] = x;
+               perframe_regs[pfv_allocation[pfv]] = x;
+}
+
+static int init_pfv()
+{
+       int i;
+       
+       fpvm_init(&pfv_fragment, 0);
+       pfv_fragment.bind_mode = 1; /* < keep user-defined variables from frame to frame */
+       for(i=0;i<EVAL_PFV_COUNT;i++) {
+               pfv_preallocation[i] = fpvm_bind(&pfv_fragment, pfv_names[i]);
+               if(pfv_preallocation[i] == FPVM_INVALID_REG) {
+                       printf("EVL: failed to bind per-frame variable %s: %s\n", pfv_names[i], pfv_fragment.last_error);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static int finalize_pfv()
+{
+       int i;
+       int references[FPVM_MAXBINDINGS];
+
+       /* assign dummy values for output */
+       if(!fpvm_assign(&pfv_fragment, "_Xo", "_Xi")) goto fail_fpvm;
+       if(!fpvm_assign(&pfv_fragment, "_Yo", "_Yi")) goto fail_fpvm;
+       if(!fpvm_finalize(&pfv_fragment)) goto fail_fpvm;
+       #ifdef EVAL_DEBUG
+       printf("EVL: per-frame FPVM fragment:\n");
+       fpvm_dump(&pfv_fragment);
+       #endif
+
+       /* Build variable allocation table */
+       fpvm_get_references(&pfv_fragment, references);
+       for(i=0;i<EVAL_PFV_COUNT;i++)
+               if(references[pfv_preallocation[i]])
+                       pfv_allocation[i] = pfv_preallocation[i];
+               else
+                       pfv_allocation[i] = -1;
+       
+       return 1;
+fail_fpvm:
+       printf("EVL: failed to finalize per-frame variables: %s\n", pfv_fragment.last_error);
+       return 0;
+}
+
+static int schedule_pfv()
+{
+       perframe_prog_length = gfpus_schedule(&pfv_fragment, (unsigned int *)perframe_prog, (unsigned int *)perframe_regs);
+       eval_reinit_all_pfv();
+       if(perframe_prog_length < 0) {
+               printf("EVL: per-frame VLIW scheduling failed\n");
+               return 0;
+       }
+       #ifdef EVAL_DEBUG
+       printf("EVL: per-frame PFPU fragment:\n");
+       pfpu_dump(perframe_prog, perframe_prog_length);
+       #endif
+       
+       return 1;
 }
 
-int eval_add_per_frame(char *dest, char *val)
+int eval_add_per_frame(int linenr, char *dest, char *val)
 {
+       if(!fpvm_assign(&pfv_fragment, dest, val)) {
+               printf("EVL: failed to add per-frame equation l. %d: %s\n", linenr, pfv_fragment.last_error);
+               return 0;
+       }
        return 1;
 }
 
@@ -247,9 +275,9 @@ void eval_pfv_fill_td(struct pfpu_td *td, pfpu_callback callback, void *user)
        td->output = &dummy[0];
        td->hmeshlast = 0;
        td->vmeshlast = 0;
-       td->program = perframe_prog;
+       td->program = (pfpu_instruction *)perframe_prog;
        td->progsize = perframe_prog_length;
-       td->registers = perframe_regs_current;
+       td->registers = perframe_regs;
        td->update = 1;
        td->invalidate = 0; /* < we don't care if our dummy variable has coherency problems */
        td->callback = callback;
@@ -260,18 +288,129 @@ void eval_pfv_fill_td(struct pfpu_td *td, pfpu_callback callback, void *user)
 /* PER-VERTEX VARIABLES                                         */
 /****************************************************************/
 
-void eval_pfv_to_pvv()
+static struct fpvm_fragment pvv_fragment;
+static int pvv_allocation[EVAL_PVV_COUNT];             /* < where per-vertex variables are mapped in PFPU regf, -1 if unmapped */
+static int pervertex_prog_length;                      /* < how many instructions in pervertex_prog */
+static unsigned int pervertex_prog[PFPU_PROGSIZE];     /* < PFPU per-vertex microcode */
+static float pervertex_regs[PFPU_REG_COUNT];           /* < PFPU regf according to per-frame variables, initial conditions and constants */
+
+static const char pvv_names[EVAL_PVV_COUNT][FPVM_MAXSYMLEN] = {
+       /* System */
+       "_texsize",
+       "_hmeshsize",
+       "_vmeshsize",
+
+       /* MilkDrop */
+       "cx",
+       "cy",
+       "rot",
+       "dx",
+       "dy",
+       "zoom"
+};
+
+void eval_transfer_pvv_regs()
 {
+       pervertex_regs[pvv_allocation[pvv_texsize]] = renderer_texsize;
+       pervertex_regs[pvv_allocation[pvv_hmeshsize]] = 1.0/(float)renderer_hmeshlast;
+       pervertex_regs[pvv_allocation[pvv_vmeshsize]] = 1.0/(float)renderer_vmeshlast;
+       
        pervertex_regs[pvv_allocation[pvv_cx]] = eval_read_pfv(pfv_cx);
        pervertex_regs[pvv_allocation[pvv_cy]] = eval_read_pfv(pfv_cy);
-       pervertex_regs[pvv_allocation[pvv_rot]] = -eval_read_pfv(pfv_rot);
-       pervertex_regs[pvv_allocation[pvv_dx]] = -eval_read_pfv(pfv_dx);
-       pervertex_regs[pvv_allocation[pvv_dy]] = -eval_read_pfv(pfv_dy);
-       pervertex_regs[pvv_allocation[pvv_zoom]] = 1.0/eval_read_pfv(pfv_zoom);
+       pervertex_regs[pvv_allocation[pvv_rot]] = eval_read_pfv(pfv_rot);
+       pervertex_regs[pvv_allocation[pvv_dx]] = eval_read_pfv(pfv_dx);
+       pervertex_regs[pvv_allocation[pvv_dy]] = eval_read_pfv(pfv_dy);
+       pervertex_regs[pvv_allocation[pvv_zoom]] = 1.0/eval_read_pfv(pfv_zoom); /* HACK */
+}
+
+static int init_pvv()
+{
+       int i;
+       
+       fpvm_init(&pvv_fragment, 1);
+       
+       for(i=0;i<EVAL_PVV_COUNT;i++) {
+               pvv_allocation[i] = fpvm_bind(&pvv_fragment, pvv_names[i]);
+               if(pvv_allocation[i] == FPVM_INVALID_REG) {
+                       printf("EVL: failed to bind per-vertex variable %s: %s\n", pvv_names[i], pvv_fragment.last_error);
+                       return 0;
+               }
+       }
+
+       #define A(dest, val) if(!fpvm_assign(&pvv_fragment, dest, val)) goto fail_assign
+       A("_x", "i2f(_Xi)*_hmeshsize");
+       A("_y", "i2f(_Yi)*_vmeshsize");
+       /* TODO: generate ang and rad */
+       #undef A
+       
+       return 1;
+
+fail_assign:
+       printf("EVL: failed to add equation to per-vertex header: %s\n", pvv_fragment.last_error);
+       return 0;
+}
+
+static int finalize_pvv()
+{
+       #define A(dest, val) if(!fpvm_assign(&pvv_fragment, dest, val)) goto fail_assign
+
+       /* Zoom */
+       A("_xz", "zoom*(_x-cx)+cx");
+       A("_yz", "zoom*(_y-cy)+cy");
+
+       /* Rotation */
+       A("_cosr", "cos(0-rot)");
+       A("_sinr", "sin(0-rot)");
+       A("_u", "_xz-cx");
+       A("_v", "_yz-cy");
+       A("_xr", "_u*_cosr-_v*_sinr+cx");
+       A("_yr", "_u*_sinr+_v*_cosr+cy");
+
+       /* Displacement */
+       A("_xd", "_xr-dx");
+       A("_yd", "_yr-dy");
+
+       /* Convert to framebuffer coordinates */
+       A("_Xo", "f2i(_xr*_texsize)");
+       A("_Yo", "f2i(_yr*_texsize)");
+
+       #undef A
+       
+       if(!fpvm_finalize(&pvv_fragment)) goto fail_finalize;
+       #ifdef EVAL_DEBUG
+       printf("EVL: per-vertex FPVM fragment:\n");
+       fpvm_dump(&pvv_fragment);
+       #endif
+       return 1;
+fail_assign:
+       printf("EVL: failed to add equation to per-vertex footer: %s\n", pvv_fragment.last_error);
+       return 0;
+fail_finalize:
+       printf("EVL: failed to finalize per-vertex variables: %s\n", pvv_fragment.last_error);
+       return 0;
+}
+
+static int schedule_pvv()
+{
+       pervertex_prog_length = gfpus_schedule(&pvv_fragment, (unsigned int *)pervertex_prog, (unsigned int *)pervertex_regs);
+       if(pervertex_prog_length < 0) {
+               printf("EVL: per-vertex VLIW scheduling failed\n");
+               return 0;
+       }
+       #ifdef EVAL_DEBUG
+       printf("EVL: per-vertex PFPU fragment:\n");
+       pfpu_dump(pervertex_prog, pervertex_prog_length);
+       #endif
+
+       return 1;
 }
 
-int eval_add_per_vertex(char *dest, char *val)
+int eval_add_per_vertex(int linenr, char *dest, char *val)
 {
+       if(!fpvm_assign(&pvv_fragment, dest, val)) {
+               printf("EVL: failed to add per-vertex equation l. %d: %s\n", linenr, pvv_fragment.last_error);
+               return 0;
+       }
        return 1;
 }
 
@@ -280,7 +419,7 @@ void eval_pvv_fill_td(struct pfpu_td *td, struct tmu_vertex *vertices, pfpu_call
        td->output = (unsigned int *)vertices;
        td->hmeshlast = renderer_hmeshlast;
        td->vmeshlast = renderer_hmeshlast;
-       td->program = pervertex_prog;
+       td->program = (pfpu_instruction *)pervertex_prog;
        td->progsize = pervertex_prog_length;
        td->registers = pervertex_regs;
        td->update = 0; /* <┬áno transfer of data in per-vertex equations between frames */
index 250bdaa..29f735d 100644 (file)
@@ -27,7 +27,9 @@
 /* GENERAL                                                      */
 /****************************************************************/
 
-void eval_init();
+int eval_init();
+
+/* generate all PFPU microcodes, must be called once before *_fill_td */
 int eval_schedule();
 
 /****************************************************************/
@@ -92,15 +94,13 @@ enum {
 /* convert a variable name to its pfv_xxx number, -1 in case of failure */
 int eval_pfv_from_name(const char *name);
 
+/* set an initial value for a per frame variable or parameter */
 void eval_set_initial(int pfv, float x);
 
-/* restores preset's initial conditions (and reset user variables) */
-void eval_reset_pfv();
-
 /* restore a variable's initial condition */
 int eval_reinit_pfv(int pfv);
 
-/* restore all variable's initial conditions (and keep user variables) */
+/* restore all variable's initial conditions */
 void eval_reinit_all_pfv();
 
 /* reads the value of a per-frame variable
@@ -117,7 +117,7 @@ float eval_read_pfv(int pfv);
 void eval_write_pfv(int pfv, float x);
 
 /* add a per frame equation in textual form */
-int eval_add_per_frame(char *dest, char *val);
+int eval_add_per_frame(int linenr, char *dest, char *val);
 
 /* fills in a task descriptor to evaluate per-frame equations */
 void eval_pfv_fill_td(struct pfpu_td *td, pfpu_callback callback, void *user);
@@ -129,11 +129,10 @@ void eval_pfv_fill_td(struct pfpu_td *td, pfpu_callback callback, void *user);
 
 enum {
        /* System */
-       pvv_hmeshsize = 0,
+       pvv_texsize,
+       pvv_hmeshsize,
        pvv_vmeshsize,
-       pvv_hres,
-       pvv_vres,
-
+       
        /* MilkDrop */
        pvv_cx,
        pvv_cy,
@@ -145,11 +144,11 @@ enum {
        EVAL_PVV_COUNT /* must be last */
 };
 
-/* transfer relevant per-frame variables to the per-vertex variable pool */
-void eval_pfv_to_pvv();
+/* initialize per-vertex registers (some from the previously computed per-frame values) */
+void eval_transfer_pvv_regs();
 
 /* add a per vertex equation in textual form */
-int eval_add_per_vertex(char *dest, char *val);
+int eval_add_per_vertex(int linenr, char *dest, char *val);
 
 /* fills in a task descriptor to evaluate per-vertex equations */
 void eval_pvv_fill_td(struct pfpu_td *td, struct tmu_vertex *vertices, pfpu_callback callback, void *user);
index faade37..8ee4aa3 100644 (file)
@@ -39,7 +39,7 @@ void renderer_init()
        printf("RDR: renderer ready (mesh:%dx%d, texsize:%d)\n", renderer_hmeshlast, renderer_vmeshlast, renderer_texsize);
 }
 
-static unsigned int linenr;
+static int linenr;
 
 static int process_equation(char *equation, int per_vertex)
 {
@@ -47,31 +47,34 @@ static int process_equation(char *equation, int per_vertex)
 
        c = strchr(equation, '=');
        if(!c) {
-               printf("RDR: error l.%d: malformed equation\n");
+               printf("RDR: error l.%d: malformed equation (%s)\n", linenr, equation);
                return 0;
        }
        *c = 0;
-       
-       c2 = c;
-       while((c2 > equation) && (*c2 == ' ')) c2--;
-       *c2 = 0;
+
+       if(*equation == 0) {
+               printf("RDR: error l.%d: missing lvalue\n", linenr);
+               return 0;
+       }
+       c2 = c - 1;
+       while((c2 > equation) && (*c2 == ' ')) *c2-- = 0;
        
        c++;
        while(*c == ' ') c++;
 
        if(*equation == 0) {
-               printf("RDR: error l.%d: missing lvalue\n");
+               printf("RDR: error l.%d: missing lvalue\n", linenr);
                return 0;
        }
        if(*c == 0) {
-               printf("RDR: error l.%d: missing rvalue\n");
+               printf("RDR: error l.%d: missing rvalue\n", linenr);
                return 0;
        }
 
        if(per_vertex)
-               return eval_add_per_vertex(equation, c);
+               return eval_add_per_vertex(linenr, equation, c);
        else
-               return eval_add_per_frame(equation, c);
+               return eval_add_per_frame(linenr, equation, c);
 }
 
 static int process_equations(char *equations, int per_vertex)
@@ -128,8 +131,7 @@ static int process_line(char *line)
        if(c) *c = 0;
        
        c = line + strlen(line);
-       while((c > line) && (*c == ' ')) c--;
-       *c = 0;
+       while((c > line) && (*c == ' ')) *c-- = 0;
        if(*line == 0) return 1;
 
        c = strchr(line, '=');
@@ -167,7 +169,7 @@ int renderer_start(char *preset_code)
 {
        eval_init();
        if(!load_preset(preset_code)) return 0;
-       eval_schedule();
+       if(!eval_schedule()) return 0;
        apipe_start();
        return 1;
 }
index fb007c2..038f008 100644 (file)
@@ -70,11 +70,20 @@ struct fpvm_fragment {
        
        int ninstructions;
        struct fpvm_instruction code[FPVM_MAXCODELEN];
+
+       int bind_mode;
+
+       /* internal use, to return an error with equations
+        * such as foo = ... foo ...
+        * when bind_mode = 0 and foo is unbound.
+        */
+       int final_dest;
+       int vector_mode;
 };
 
 const char *fpvm_version();
 
-void fpvm_init(struct fpvm_fragment *fragment);
+void fpvm_init(struct fpvm_fragment *fragment, int vector_mode);
 
 int fpvm_bind(struct fpvm_fragment *fragment, const char *sym);
 void fpvm_set_xin(struct fpvm_fragment *fragment, const char *sym);
@@ -84,6 +93,8 @@ void fpvm_set_yout(struct fpvm_fragment *fragment, const char *sym);
 
 int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *expr);
 
+void fpvm_get_references(struct fpvm_fragment *fragment, int *references);
+
 int fpvm_finalize(struct fpvm_fragment *fragment);
 
 void fpvm_dump(struct fpvm_fragment *fragment);
index 8adef25..ca101f6 100644 (file)
@@ -30,8 +30,17 @@ clean:
 # DO NOT DELETE
 
 fpvm.o: ../../software/include/base/string.h
-fpvm.o: ../../software/include/base/stdlib.h ../../software/include/fpvm/is.h
-fpvm.o: ../../software/include/fpvm/fpvm.h ast.h parser_helper.h
+fpvm.o: ../../software/include/base/stdlib.h
+fpvm.o: ../../software/include/base/stdio.h
+fpvm.o: ../../software/include/base/version.h
+fpvm.o: ../../software/include/fpvm/is.h ../../software/include/fpvm/fpvm.h
+fpvm.o: ast.h parser_helper.h
+gfpus.o: ../../software/include/base/stdio.h
+gfpus.o: ../../software/include/base/stdlib.h
+gfpus.o: ../../software/include/fpvm/is.h ../../software/include/fpvm/fpvm.h
+gfpus.o: ../../software/include/fpvm/pfpu.h
+gfpus.o: ../../software/include/fpvm/gfpus.h ../../software/include/hw/pfpu.h
+gfpus.o: ../../software/include/hw/common.h
 parser.o: ../../software/include/base/stdio.h
 parser.o: ../../software/include/base/stdlib.h
 parser.o: ../../software/include/base/assert.h
@@ -42,6 +51,10 @@ parser_helper.o: ../../software/include/base/stdio.h
 parser_helper.o: ../../software/include/base/stdlib.h
 parser_helper.o: ../../software/include/base/malloc.h scanner.h parser.h
 parser_helper.o: ast.h parser_helper.h
+pfpu.o: ../../software/include/base/stdio.h
+pfpu.o: ../../software/include/base/stdlib.h ../../software/include/hw/pfpu.h
+pfpu.o: ../../software/include/hw/common.h ../../software/include/fpvm/fpvm.h
+pfpu.o: ../../software/include/fpvm/is.h ../../software/include/fpvm/pfpu.h
 scanner.o: ../../software/include/base/stdio.h
 scanner.o: ../../software/include/base/stdlib.h
 scanner.o: ../../software/include/base/string.h
index 11bc5b5..89227e8 100644 (file)
@@ -30,34 +30,41 @@ const char *fpvm_version()
        return VERSION;
 }
 
-void fpvm_init(struct fpvm_fragment *fragment)
+void fpvm_init(struct fpvm_fragment *fragment, int vector_mode)
 {
        fragment->last_error[0] = 0;
 
        fragment->nbindings = 3;
        fragment->bindings[0].isvar = 1;
-       fragment->bindings[0].b.v[0] = 'X';
-       fragment->bindings[0].b.v[1] = 'i';
-       fragment->bindings[0].b.v[2] = 0;
+       fragment->bindings[0].b.v[0] = '_';
+       fragment->bindings[0].b.v[1] = 'X';
+       fragment->bindings[0].b.v[2] = 'i';
+       fragment->bindings[0].b.v[3] = 0;
        fragment->bindings[1].isvar = 1;
-       fragment->bindings[1].b.v[0] = 'Y';
-       fragment->bindings[1].b.v[1] = 'i';
-       fragment->bindings[1].b.v[2] = 0;
+       fragment->bindings[1].b.v[0] = '_';
+       fragment->bindings[1].b.v[1] = 'Y';
+       fragment->bindings[1].b.v[2] = 'i';
+       fragment->bindings[1].b.v[3] = 0;
        fragment->bindings[2].isvar = 1; /* flags */
        fragment->bindings[2].b.v[0] = 0;
 
        fragment->ntbindings = 2;
        fragment->tbindings[0].reg = -1;
-       fragment->tbindings[0].sym[0] = 'X';
-       fragment->tbindings[0].sym[1] = 'o';
-       fragment->tbindings[0].sym[2] = 0;
+       fragment->tbindings[0].sym[0] = '_';
+       fragment->tbindings[0].sym[1] = 'X';
+       fragment->tbindings[0].sym[2] = 'o';
+       fragment->tbindings[0].sym[3] = 0;
        fragment->tbindings[1].reg = -2;
-       fragment->tbindings[1].sym[0] = 'Y';
-       fragment->tbindings[1].sym[1] = 'o';
-       fragment->tbindings[1].sym[2] = 0;
+       fragment->tbindings[1].sym[0] = '_';
+       fragment->tbindings[1].sym[1] = 'Y';
+       fragment->tbindings[1].sym[2] = 'o';
+       fragment->tbindings[1].sym[3] = 0;
        
        fragment->next_sur = -3;
        fragment->ninstructions = 0;
+
+       fragment->bind_mode = 0;
+       fragment->vector_mode = vector_mode;
 }
 
 int fpvm_bind(struct fpvm_fragment *fragment, const char *sym)
@@ -107,19 +114,28 @@ static int lookup(struct fpvm_fragment *fragment, const char *sym)
 
 static int tbind(struct fpvm_fragment *fragment, const char *sym)
 {
-       if(fragment->ntbindings == FPVM_MAXTBINDINGS) return FPVM_INVALID_REG;
+       if(fragment->ntbindings == FPVM_MAXTBINDINGS) {
+               snprintf(fragment->last_error, FPVM_MAXERRLEN, "Failed to allocate register for variable: %s", sym);
+               return FPVM_INVALID_REG;
+       }
        fragment->tbindings[fragment->ntbindings].reg = fragment->next_sur;
        strcpy(fragment->tbindings[fragment->ntbindings].sym, sym);
        fragment->ntbindings++;
        return fragment->next_sur--;
 }
 
-static int sym_to_reg(struct fpvm_fragment *fragment, const char *sym)
+static int sym_to_reg(struct fpvm_fragment *fragment, const char *sym, int *created)
 {
        int r;
+       if(created) *created = 0;
        r = lookup(fragment, sym);
-       if(r == FPVM_INVALID_REG)
-               r = tbind(fragment, sym);
+       if(r == FPVM_INVALID_REG) {
+               if(created) *created = 1;
+               if(fragment->bind_mode)
+                       r = fpvm_bind(fragment, sym);
+               else
+                       r = tbind(fragment, sym);
+       }
        return r;
 }
 
@@ -171,6 +187,8 @@ static int operator2opcode(const char *operator)
        if(strcmp(operator, "cos") == 0) return FPVM_OPCODE_COS;
        if(strcmp(operator, "above") == 0) return FPVM_OPCODE_ABOVE;
        if(strcmp(operator, "equal") == 0) return FPVM_OPCODE_EQUAL;
+       if(strcmp(operator, "i2f") == 0) return FPVM_OPCODE_I2F;
+       if(strcmp(operator, "f2i") == 0) return FPVM_OPCODE_F2I;
        else return -1;
 }
 
@@ -198,10 +216,15 @@ static int compile(struct fpvm_fragment *fragment, int reg, struct ast_node *nod
        }
        if(node->contents.branches.a == NULL) {
                /* AST node is a variable */
-               opa = lookup(fragment, node->label);
-               if(opa == FPVM_INVALID_REG) {
-                       snprintf(fragment->last_error, FPVM_MAXERRLEN, "Reading unbound variable: %s", node->label);
-                       return FPVM_INVALID_REG;
+               if(fragment->bind_mode) {
+                       opa = sym_to_reg(fragment, node->label, NULL);
+                       if(opa == FPVM_INVALID_REG) return FPVM_INVALID_REG;
+               } else {
+                       opa = lookup(fragment, node->label);
+                       if((opa == FPVM_INVALID_REG)||(opa == fragment->final_dest)) {
+                               snprintf(fragment->last_error, FPVM_MAXERRLEN, "Reading unbound variable: %s", node->label);
+                               return FPVM_INVALID_REG;
+                       }
                }
                if(reg != FPVM_INVALID_REG) {
                        if(!add_isn(fragment, FPVM_OPCODE_COPY, opa, 0, reg)) return FPVM_INVALID_REG;
@@ -275,6 +298,7 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *ex
        struct ast_node *n;
        int dest_reg;
        struct fpvm_backup backup;
+       int created;
 
        n = fpvm_parse(expr);
        if(n == NULL) {
@@ -284,7 +308,7 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *ex
 
        fragment_backup(fragment, &backup);
 
-       dest_reg = sym_to_reg(fragment, dest);
+       dest_reg = sym_to_reg(fragment, dest, &created);
        if(dest_reg == FPVM_INVALID_REG) {
                snprintf(fragment->last_error, FPVM_MAXERRLEN, "Failed to allocate register for destination");
                fpvm_parse_free(n);
@@ -292,6 +316,10 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *ex
                return 0;
        }
 
+       if(created)
+               fragment->final_dest = dest_reg;
+       else
+               fragment->final_dest = FPVM_INVALID_REG;
        if(compile(fragment, dest_reg, n) == FPVM_INVALID_REG) {
                fpvm_parse_free(n);
                fragment_restore(fragment, &backup);
@@ -302,9 +330,28 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *ex
        return 1;
 }
 
+void fpvm_get_references(struct fpvm_fragment *fragment, int *references)
+{
+       int i;
+
+       for(i=0;i<FPVM_MAXBINDINGS;i++)
+               references[i] = 0;
+       for(i=0;i<fragment->ninstructions;i++) {
+               if(fragment->code[i].opa > 0)
+                       references[fragment->code[i].opa] = 1;
+               if(fragment->code[i].opb > 0)
+                       references[fragment->code[i].opb] = 1;
+               if(fragment->code[i].dest > 0)
+                       references[fragment->code[i].dest] = 1;
+       }
+}
+
 int fpvm_finalize(struct fpvm_fragment *fragment)
 {
-       return add_isn(fragment, FPVM_OPCODE_VECTOUT, -1, -2, 0);
+       if(fragment->vector_mode)
+               return add_isn(fragment, FPVM_OPCODE_VECTOUT, -1, -2, 0);
+       else
+               return 1;
 }
 
 void fpvm_print_opcode(int opcode)
index 6177c06..67d6876 100644 (file)
@@ -357,13 +357,26 @@ static int schedule(struct scheduler_state *sc)
                        }
                        if(r == 1) {
                                remaining--;
-                               if(remaining == 0) return 1;
+                               if(remaining == 0) {
+                                       if(!sc->fragment->vector_mode) {
+                                               /* add a VECTOUT at the end */
+                                               sc->last_exit++;
+                                               if(sc->last_exit >= PFPU_PROGSIZE)
+                                                       goto outofspace;
+                                               sc->prog[sc->last_exit].i.opa = 0;
+                                               sc->prog[sc->last_exit].i.opb = 0;
+                                               sc->prog[sc->last_exit].i.opcode = FPVM_OPCODE_VECTOUT;
+                                               sc->prog[sc->last_exit].i.dest = 0;
+                                       }
+                                       return 1;
+                               }
                                break;
                        }
                        /* r == 0 */
                }
        }
 
+outofspace:
        #ifdef GFPUS_DEBUG
        printf("scheduler_schedule: out of program space\n");
        #endif
index 6711da1..9c43bbd 100644 (file)
@@ -32,9 +32,9 @@ int main(int argc, char *argv)
        printf("libFPVM version: %s\n\n", fpvm_version());
 
        printf("******* SIMPLE TEST *******\n");
-       fpvm_init(&frag);
-       fpvm_assign(&frag, "Xo", "(Xi+1)*5.8");
-       fpvm_assign(&frag, "Yo", "(Yi+3)*1.4");
+       fpvm_init(&frag, 1);
+       fpvm_assign(&frag, "_Xo", "(_Xi+1)*5.8");
+       fpvm_assign(&frag, "_Yo", "(_Yi+3)*1.4");
        if(frag.last_error[0] != 0)
                printf("Reported error: %s\n", frag.last_error);
        fpvm_finalize(&frag);
@@ -45,7 +45,7 @@ int main(int argc, char *argv)
                pfpu_dump(code, len);
 
        printf("\n******* TEST 2 *******\n");
-       fpvm_init(&frag);
+       fpvm_init(&frag, 0);
        printf("Variable foo bound to R%04d\n", fpvm_bind(&frag, "foo"));
        fpvm_set_xin(&frag, "x");
        fpvm_set_yin(&frag, "y");