Use FPVM in demo firmware (unfinished, broken)
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Sun, 28 Mar 2010 21:21:21 +0000 (23:21 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Sun, 28 Mar 2010 21:21:21 +0000 (23:21 +0200)
22 files changed:
README
build_demo.sh
software/demo/Makefile
software/demo/apipe.c
software/demo/apipe.h
software/demo/ast.h [deleted file]
software/demo/compiler.c [deleted file]
software/demo/compiler.h [deleted file]
software/demo/eval.c
software/demo/eval.h
software/demo/parser.y [deleted file]
software/demo/parser_helper.c [deleted file]
software/demo/parser_helper.h [deleted file]
software/demo/renderer.c
software/demo/scanner.h [deleted file]
software/demo/scanner.re [deleted file]
software/demo/scheduler.c [deleted file]
software/demo/scheduler.h [deleted file]
software/demo/shell.c
software/include/base/string.h
software/libbase/libc.c
software/libnet/microudp.c

diff --git a/README b/README
index fbe75df..a3919fd 100644 (file)
--- a/README
+++ b/README
@@ -1,9 +1,8 @@
-[> Milkymist(tm) Visual Synthesizer
---------------------------------------
+[> Milkymist(tm) system-on-chip
+-------------------------------
 
-This is the complete core source code and documentation for Milkymist(tm),
-an opensource VJing system-on-chip for FPGA boards,
-compatible with MilkDrop presets.
+This is the complete core source code and documentation for the opensource
+system-on-chip used in the Milkymist(tm) interactive VJ station.
 
 For the latest releases, binary distributions and more:
   http://www.milkymist.org
index 36bf85a..ffc7cd4 100755 (executable)
@@ -53,6 +53,14 @@ if [ "$?" != 0 ] ; then
 else
         echo "OK"
 fi
+echo -n "  FPVM library..."
+cd $BASEDIR/software/libfpvm && make >> $LOGFILE 2>&1
+if [ "$?" != 0 ] ; then
+        echo "FAILED"
+       exit 1
+else
+        echo "OK"
+fi
 echo -n "  Demonstration firmware..."
 cd $BASEDIR/software/demo && make >> $LOGFILE 2>&1
 if [ "$?" != 0 ] ; then
index b7ae0c5..17bfca5 100644 (file)
@@ -1,21 +1,11 @@
 MMDIR=../..
 include $(MMDIR)/software/include.mak
 
-OBJECTS=crt0.o isr.o tick.o wave.o analyzer.o scanner.o parser.o parser_helper.o compiler.o scheduler.o eval.o line.o apipe.o rpipe.o renderer.o cpustats.o memstats.o shell.o ui.o main.o
+OBJECTS=crt0.o isr.o tick.o wave.o analyzer.o eval.o line.o apipe.o rpipe.o renderer.o cpustats.o memstats.o shell.o ui.o main.o
 SEGMENTS=-j .text -j .data -j .rodata
 
 all: boot.bin
 
-%.c: %.re
-       re2c -o $@ $<
-
-scanner.c: parser.h
-
-parser.h: parser.c
-
-%.c: %.y
-       lemon $<
-
 bandfilters.h: bandfilters.sce
        scilab -nw -nwni -nogui -nb -f bandfilters.sce
 
@@ -30,17 +20,17 @@ spam.h: spam.raw
        chmod -x $@
        $(MMDIR)/tools/crc32 $@
 
-boot.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase.a $(MMDIR)/software/libmath/libmath.a $(MMDIR)/software/libhal/libhal.a
-       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libmath -L$(MMDIR)/software/libhal --start-group $(OBJECTS) -lbase -lmath -lhal --end-group
+boot.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase.a $(MMDIR)/software/libmath/libmath.a $(MMDIR)/software/libhal/libhal.a $(MMDIR)/software/libfpvm/libfpvm.a
+       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libmath -L$(MMDIR)/software/libhal -L$(MMDIR)/software/libfpvm --start-group $(OBJECTS) -lbase -lmath -lhal -lfpvm --end-group
        chmod -x $@
 
 .PHONY: clean depend
 
-depend: parser.c scanner.c bandfilters.h spam.h
+depend: bandfilters.h spam.h
        makedepend -Y -- $(CFLAGS) -- *.c
 
 clean:
-       rm -f $(OBJECTS) scanner.c parser.c parser.h parser.out bandfilters.h spam.raw spam.h boot.elf boot.bin .*~ *~ Makefile.bak
+       rm -f $(OBJECTS) bandfilters.h spam.raw spam.h boot.elf boot.bin .*~ *~ Makefile.bak
 
 # DO NOT DELETE
 
@@ -52,13 +42,8 @@ apipe.o: ../../software/include/base/board.h ../../software/include/hal/brd.h
 apipe.o: ../../software/include/hal/snd.h ../../software/include/hw/ac97.h
 apipe.o: ../../software/include/hw/common.h ../../software/include/hal/pfpu.h
 apipe.o: ../../software/include/hw/pfpu.h ../../software/include/hal/time.h
-apipe.o: analyzer.h eval.h ../../software/include/hw/tmu.h ast.h cpustats.h
-apipe.o: rpipe.h ../../software/include/hal/tmu.h apipe.h
-compiler.o: ../../software/include/base/stdio.h
-compiler.o: ../../software/include/base/stdlib.h
-compiler.o: ../../software/include/base/string.h
-compiler.o: ../../software/include/hw/pfpu.h
-compiler.o: ../../software/include/hw/common.h compiler.h ast.h
+apipe.o: analyzer.h eval.h ../../software/include/hw/tmu.h cpustats.h rpipe.h
+apipe.o: ../../software/include/hal/tmu.h apipe.h
 cpustats.o: ../../software/include/base/stdio.h
 cpustats.o: ../../software/include/base/stdlib.h
 cpustats.o: ../../software/include/base/irq.h
@@ -67,7 +52,7 @@ 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 ast.h compiler.h scheduler.h eval.h
+eval.o: ../../software/include/hal/pfpu.h eval.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
@@ -96,16 +81,6 @@ memstats.o: ../../software/include/base/board.h
 memstats.o: ../../software/include/hal/brd.h
 memstats.o: ../../software/include/hw/fmlmeter.h
 memstats.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
-parser.o: ../../software/include/base/string.h
-parser.o: ../../software/include/base/malloc.h
-parser.o: ../../software/include/base/math.h ast.h
-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
 renderer.o: ../../software/include/base/stdio.h
 renderer.o: ../../software/include/base/stdlib.h
 renderer.o: ../../software/include/base/math.h
@@ -113,7 +88,7 @@ renderer.o: ../../software/include/base/system.h
 renderer.o: ../../software/include/hal/pfpu.h
 renderer.o: ../../software/include/hw/pfpu.h
 renderer.o: ../../software/include/hw/common.h
-renderer.o: ../../software/include/hal/vga.h parser_helper.h ast.h eval.h
+renderer.o: ../../software/include/hal/vga.h eval.h
 renderer.o: ../../software/include/hw/tmu.h apipe.h renderer.h
 rpipe.o: ../../software/include/base/stdio.h
 rpipe.o: ../../software/include/base/stdlib.h
@@ -124,14 +99,6 @@ rpipe.o: ../../software/include/hw/interrupts.h
 rpipe.o: ../../software/include/hal/vga.h ../../software/include/hal/tmu.h
 rpipe.o: ../../software/include/hw/tmu.h ../../software/include/hw/common.h
 rpipe.o: renderer.h wave.h cpustats.h color.h line.h rpipe.h spam.h
-scanner.o: ../../software/include/base/stdio.h
-scanner.o: ../../software/include/base/stdlib.h
-scanner.o: ../../software/include/base/string.h
-scanner.o: ../../software/include/base/malloc.h scanner.h parser.h
-scheduler.o: ../../software/include/base/stdio.h
-scheduler.o: ../../software/include/base/stdlib.h
-scheduler.o: ../../software/include/hw/pfpu.h
-scheduler.o: ../../software/include/hw/common.h scheduler.h compiler.h ast.h
 shell.o: ../../software/include/base/stdio.h
 shell.o: ../../software/include/base/stdlib.h
 shell.o: ../../software/include/base/string.h
index 7025309..33a724c 100644 (file)
@@ -41,7 +41,6 @@ static short *analyzer_buffer;
 static int peak_bass, peak_mid, peak_treb;
 static float bass_att, mid_att, treb_att;
 
-static struct eval_state *eval;
 static int eval_ready;
 
 static struct rpipe_frame frame1 __attribute__((aligned(8)));
@@ -98,13 +97,12 @@ static void apipe_snd_callback(short *buffer, void *user)
        run_analyzer_bottom_half = 1;
 }
 
-void apipe_start(struct eval_state *e)
+void apipe_start()
 {
        snd_record_empty();
        snd_record_refill(audiobuffer1);
        snd_record_refill(audiobuffer2);
        snd_record_refill(audiobuffer3);
-       eval = e;
        snd_record_start(apipe_snd_callback, NSAMPLES, NULL);
 }
 
@@ -147,7 +145,7 @@ static void pfv_callback(struct pfpu_td *td)
 
        rpipe_frame = (struct rpipe_frame *)td->user;
 
-       decay = eval_read_pfv(eval, pfv_decay);
+       decay = eval_read_pfv(pfv_decay);
        brightness256 = 255.0*decay+3.5;
        brightness64 = (brightness256 >> 2)-1;
        brightness256 &= 3;
@@ -162,46 +160,46 @@ static void pfv_callback(struct pfpu_td *td)
        if(brightness64 > 63) brightness64 = 63;
        rpipe_frame->brightness = brightness64;
 
-       rpipe_frame->wave_mode = eval_read_pfv(eval, pfv_wave_mode);
-       rpipe_frame->wave_scale = eval_read_pfv(eval, pfv_wave_scale);
-       rpipe_frame->wave_additive = eval_read_pfv(eval, pfv_wave_additive) != 0.0;
-       rpipe_frame->wave_usedots = eval_read_pfv(eval, pfv_wave_usedots) != 0.0;
-       rpipe_frame->wave_maximize_color = eval_read_pfv(eval, pfv_wave_maximize_color) != 0.0;
-       rpipe_frame->wave_thick = eval_read_pfv(eval, pfv_wave_thick) != 0.0;
+       rpipe_frame->wave_mode = eval_read_pfv(pfv_wave_mode);
+       rpipe_frame->wave_scale = eval_read_pfv(pfv_wave_scale);
+       rpipe_frame->wave_additive = eval_read_pfv(pfv_wave_additive) != 0.0;
+       rpipe_frame->wave_usedots = eval_read_pfv(pfv_wave_usedots) != 0.0;
+       rpipe_frame->wave_maximize_color = eval_read_pfv(pfv_wave_maximize_color) != 0.0;
+       rpipe_frame->wave_thick = eval_read_pfv(pfv_wave_thick) != 0.0;
        
-       rpipe_frame->wave_x = eval_read_pfv(eval, pfv_wave_x);
-       rpipe_frame->wave_y = eval_read_pfv(eval, pfv_wave_y);
-       rpipe_frame->wave_r = eval_read_pfv(eval, pfv_wave_r);
-       rpipe_frame->wave_g = eval_read_pfv(eval, pfv_wave_g);
-       rpipe_frame->wave_b = eval_read_pfv(eval, pfv_wave_b);
-       rpipe_frame->wave_a = eval_read_pfv(eval, pfv_wave_a);
-
-       rpipe_frame->ob_size = eval_read_pfv(eval, pfv_ob_size);
-       rpipe_frame->ob_r = eval_read_pfv(eval, pfv_ob_r);
-       rpipe_frame->ob_g = eval_read_pfv(eval, pfv_ob_g);
-       rpipe_frame->ob_b = eval_read_pfv(eval, pfv_ob_b);
-       rpipe_frame->ob_a = eval_read_pfv(eval, pfv_ob_a);
-
-       rpipe_frame->ib_size = eval_read_pfv(eval, pfv_ib_size);
-       rpipe_frame->ib_r = eval_read_pfv(eval, pfv_ib_r);
-       rpipe_frame->ib_g = eval_read_pfv(eval, pfv_ib_g);
-       rpipe_frame->ib_b = eval_read_pfv(eval, pfv_ib_b);
-       rpipe_frame->ib_a = eval_read_pfv(eval, pfv_ib_a);
-
-       rpipe_frame->mv_x = eval_read_pfv(eval, pfv_mv_x);
-       rpipe_frame->mv_y = eval_read_pfv(eval, pfv_mv_y);
-       rpipe_frame->mv_dx = eval_read_pfv(eval, pfv_mv_dx);
-       rpipe_frame->mv_dy = eval_read_pfv(eval, pfv_mv_dy);
-       rpipe_frame->mv_l = eval_read_pfv(eval, pfv_mv_l);
-       rpipe_frame->mv_r = eval_read_pfv(eval, pfv_mv_r);
-       rpipe_frame->mv_g = eval_read_pfv(eval, pfv_mv_g);
-       rpipe_frame->mv_b = eval_read_pfv(eval, pfv_mv_b);
-       rpipe_frame->mv_a = eval_read_pfv(eval, pfv_mv_a);
-
-       rpipe_frame->tex_wrap = eval_read_pfv(eval, pfv_tex_wrap) != 0.0;
-
-       eval_pfv_to_pvv(eval);
-       eval_pvv_fill_td(eval, &pfpu_td, &rpipe_frame->vertices[0][0], pvv_callback, rpipe_frame);
+       rpipe_frame->wave_x = eval_read_pfv(pfv_wave_x);
+       rpipe_frame->wave_y = eval_read_pfv(pfv_wave_y);
+       rpipe_frame->wave_r = eval_read_pfv(pfv_wave_r);
+       rpipe_frame->wave_g = eval_read_pfv(pfv_wave_g);
+       rpipe_frame->wave_b = eval_read_pfv(pfv_wave_b);
+       rpipe_frame->wave_a = eval_read_pfv(pfv_wave_a);
+
+       rpipe_frame->ob_size = eval_read_pfv(pfv_ob_size);
+       rpipe_frame->ob_r = eval_read_pfv(pfv_ob_r);
+       rpipe_frame->ob_g = eval_read_pfv(pfv_ob_g);
+       rpipe_frame->ob_b = eval_read_pfv(pfv_ob_b);
+       rpipe_frame->ob_a = eval_read_pfv(pfv_ob_a);
+
+       rpipe_frame->ib_size = eval_read_pfv(pfv_ib_size);
+       rpipe_frame->ib_r = eval_read_pfv(pfv_ib_r);
+       rpipe_frame->ib_g = eval_read_pfv(pfv_ib_g);
+       rpipe_frame->ib_b = eval_read_pfv(pfv_ib_b);
+       rpipe_frame->ib_a = eval_read_pfv(pfv_ib_a);
+
+       rpipe_frame->mv_x = eval_read_pfv(pfv_mv_x);
+       rpipe_frame->mv_y = eval_read_pfv(pfv_mv_y);
+       rpipe_frame->mv_dx = eval_read_pfv(pfv_mv_dx);
+       rpipe_frame->mv_dy = eval_read_pfv(pfv_mv_dy);
+       rpipe_frame->mv_l = eval_read_pfv(pfv_mv_l);
+       rpipe_frame->mv_r = eval_read_pfv(pfv_mv_r);
+       rpipe_frame->mv_g = eval_read_pfv(pfv_mv_g);
+       rpipe_frame->mv_b = eval_read_pfv(pfv_mv_b);
+       rpipe_frame->mv_a = eval_read_pfv(pfv_mv_a);
+
+       rpipe_frame->tex_wrap = eval_read_pfv(pfv_tex_wrap) != 0.0;
+
+       eval_pfv_to_pvv();
+       eval_pvv_fill_td(&pfpu_td, &rpipe_frame->vertices[0][0], pvv_callback, rpipe_frame);
        pfpu_submit_task(&pfpu_td);
 }
 
@@ -247,21 +245,21 @@ static void analyzer_bottom_half()
        time_get(&ts);
        time = (float)ts.sec + (float)ts.usec/1000000.0f;
 
-       eval_reinit_all_pfv(eval);
+       eval_reinit_all_pfv();
        
-       eval_write_pfv(eval, pfv_time, time);
-       eval_write_pfv(eval, pfv_bass, fbass);
-       eval_write_pfv(eval, pfv_mid, fmid);
-       eval_write_pfv(eval, pfv_treb, ftreb);
-       eval_write_pfv(eval, pfv_bass_att, bass_att);
-       eval_write_pfv(eval, pfv_mid_att, mid_att);
-       eval_write_pfv(eval, pfv_treb_att, treb_att);
+       eval_write_pfv(pfv_time, time);
+       eval_write_pfv(pfv_bass, fbass);
+       eval_write_pfv(pfv_mid, fmid);
+       eval_write_pfv(pfv_treb, ftreb);
+       eval_write_pfv(pfv_bass_att, bass_att);
+       eval_write_pfv(pfv_mid_att, mid_att);
+       eval_write_pfv(pfv_treb_att, treb_att);
 
        rpipe_frame->time = time;
        rpipe_frame->treb = ftreb;
        rpipe_frame->framenr = all_frames++;
 
-       eval_pfv_fill_td(eval, &pfpu_td, pfv_callback, rpipe_frame);
+       eval_pfv_fill_td(&pfpu_td, pfv_callback, rpipe_frame);
        pfpu_submit_task(&pfpu_td);
 }
 
index d925ce2..30bbd79 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifndef __APIPE_H
 #define __APIPE_H
 
-struct eval_state;
-
 void apipe_init();
-void apipe_start(struct eval_state *e);
+void apipe_start();
 void apipe_stop();
 void apipe_service();
 
diff --git a/software/demo/ast.h b/software/demo/ast.h
deleted file mode 100644 (file)
index 704585f..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __AST_H
-#define __AST_H
-
-#define NDEBUG
-
-#define IDENTIFIER_SIZE 24
-
-struct preset_equation;
-
-struct preset_line {
-       char label[IDENTIFIER_SIZE];               /* the left side: bSolarize, ib_g, per_frame_1, ... */
-       int iseq;                                  /* union tag */
-       union {
-               float parameter;                   /* one numeric value for a parameter */
-               struct preset_equation *equations; /* a list of equations (separated by semicolons) */
-       } contents;
-       struct preset_line *next;
-};
-
-/* maximum supported arity is 3 */
-struct ast_branches {
-       struct ast_node *a;
-       struct ast_node *b;
-       struct ast_node *c;
-};
-
-struct ast_node {
-       /*
-        * label is an empty string:
-        *   node is a constant
-        * label is not an empty string and branch A is null:
-        *   node is variable "label"
-        * label is not an empty string and branch A is not null:
-        *   node is function/operator "label"
-        */
-       char label[IDENTIFIER_SIZE];
-       union {
-               struct ast_branches branches;
-               float constant;
-       } contents;
-};
-
-struct preset_equation {
-       char target[IDENTIFIER_SIZE];
-       struct ast_node *topnode;
-       struct preset_equation *next;
-};
-
-struct preset {
-       struct preset_line *lines;
-       struct preset_line *last_line;
-};
-
-void *ParseAlloc(void *(*mallocProc)(size_t));
-void ParseFree(void *p, void (*freeProc)(void*));
-void Parse(void *yyp, int yymajor, void *yyminor, struct preset **p);
-
-#endif /* __AST_H */
diff --git a/software/demo/compiler.c b/software/demo/compiler.c
deleted file mode 100644 (file)
index db3a7ba..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <hw/pfpu.h>
-
-#include "compiler.h"
-
-void compiler_init(struct compiler_state *sc)
-{
-       int i;
-       
-       sc->n_vregs = PFPU_REG_COUNT;
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               sc->terminals[i].valid = 0;
-       sc->prog_length = 0;
-}
-
-static int find_free_terminal(struct compiler_state *sc)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++) {
-               if(pfpu_is_reserved(i)) continue;
-               if(!sc->terminals[i].valid)
-                       return i;
-       }
-       return -1;
-}
-
-int compiler_add_variable(struct compiler_state *sc, const char *name)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               if(sc->terminals[i].valid
-                       && !sc->terminals[i].isconst
-                       && (strcmp(sc->terminals[i].id.name, name) == 0)
-               ) return i;
-       
-       i = find_free_terminal(sc);
-       if(i == -1) return -1;
-
-       sc->terminals[i].valid = 1;
-       sc->terminals[i].isconst = 0;
-       strcpy(sc->terminals[i].id.name, name);
-
-       return i;
-}
-
-int compiler_add_constant(struct compiler_state *sc, float x)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               if(sc->terminals[i].valid
-                       && sc->terminals[i].isconst
-                       && (sc->terminals[i].id.x == x)
-               ) return i;
-
-       i = find_free_terminal(sc);
-       if(i == -1) return -1;
-
-       sc->terminals[i].valid = 1;
-       sc->terminals[i].isconst = 1;
-       sc->terminals[i].id.x = x;
-
-       return i;
-}
-
-int compiler_add_isn(struct compiler_state *sc, int opcode, int opa, int opb, int dest)
-{
-       int len;
-
-       len = sc->prog_length;
-       if(len >= PFPU_PROGSIZE) return 0;
-
-       sc->prog[len].opa = opa;
-       sc->prog[len].opb = opb;
-       sc->prog[len].opcode = opcode;
-       sc->prog[len].dest = dest;
-
-       sc->prog_length++;
-       return 1;
-}
-
-int compiler_add_vreg(struct compiler_state *sc)
-{
-       return sc->n_vregs++;
-}
-
-static int operator2opcode(const char *operator)
-{
-       if(strcmp(operator, "+") == 0) return PFPU_OPCODE_FADD;
-       if(strcmp(operator, "-") == 0) return PFPU_OPCODE_FSUB;
-       if(strcmp(operator, "*") == 0) return PFPU_OPCODE_FMUL;
-       if(strcmp(operator, "/") == 0) return PFPU_OPCODE_FDIV;
-       if(strcmp(operator, "sin") == 0) return PFPU_OPCODE_SIN;
-       if(strcmp(operator, "cos") == 0) return PFPU_OPCODE_COS;
-       if(strcmp(operator, "above") == 0) return PFPU_OPCODE_ABOVE;
-       if(strcmp(operator, "equal") == 0) return PFPU_OPCODE_EQUAL;
-       else return -1;
-}
-
-/*
- * Compiles a node.
- * Returns the virtual register the result of the node gets written to,
- * and -1 in case of error.
- * If reg >= 0, it forces the result to be written to this particular register.
- */
-static int int_compile(struct compiler_state *sc, struct ast_node *node, int reg)
-{
-       int opa, opb;
-       int opcode;
-       
-       if(node->label[0] == 0) {
-               /* AST node is a constant */
-               opa = compiler_add_constant(sc, node->contents.constant);
-               if(opa == -1) return -1;
-               if(reg >= 0) {
-                       if(!compiler_add_isn(sc, PFPU_OPCODE_COPY, opa, 0, reg)) return -1;
-               } else
-                       reg = opa;
-               return reg;
-       }
-       if(node->contents.branches.a == NULL) {
-               /* AST node is an input variable */
-               opa = compiler_add_variable(sc, node->label);
-               if(opa == -1) return -1;
-               if(reg >= 0) {
-                       if(!compiler_add_isn(sc, PFPU_OPCODE_COPY, opa, 0, reg)) return -1;
-               } else
-                       reg = opa;
-               return reg;
-       }
-       /* AST node is an operator or function */
-       opa = int_compile(sc, node->contents.branches.a, -1);
-       if(opa == -1) return -1;
-       opb = 0;
-       if(node->contents.branches.b != NULL) {
-               opb = int_compile(sc, node->contents.branches.b, -1);
-               if(opb == -1) return -1;
-       }
-       
-       if(reg < 0) reg = compiler_add_vreg(sc);
-       if(reg < 0) return -1;
-       opcode = operator2opcode(node->label);
-       if(opcode < 0) return -1;
-       if((opcode == PFPU_OPCODE_SIN)||(opcode == PFPU_OPCODE_COS)) {
-               /*
-                * Trigo functions are implemented with several instructions
-                * because we must convert the floating point argument in radians
-                * from MilkDrop presets to an integer expressed in 1/8192 turns
-                * for PFPU hardware.
-                */
-               int const_reg;
-               int mul_reg;
-               int f2i_reg;
-               
-               const_reg = compiler_add_constant(sc, PFPU_TRIG_CONV);
-               mul_reg = compiler_add_vreg(sc);
-               f2i_reg = compiler_add_vreg(sc);
-               if((const_reg == -1)||(mul_reg == -1)||(f2i_reg == -1)) return -1;
-               
-               if(!compiler_add_isn(sc, PFPU_OPCODE_FMUL, const_reg, opa, mul_reg)) return -1;
-               if(!compiler_add_isn(sc, PFPU_OPCODE_F2I, mul_reg, 0, f2i_reg)) return -1;
-               if(!compiler_add_isn(sc, opcode, f2i_reg, 0, reg)) return -1;
-       } else {
-               if(!compiler_add_isn(sc, opcode, opa, opb, reg)) return -1;
-       }
-       
-       return reg;
-}
-
-int compiler_compile_equation(struct compiler_state *sc, const char *target, struct ast_node *node)
-{
-       int reg;
-
-       reg = compiler_add_variable(sc, target);
-       if(reg < 0) return -1;
-       reg = int_compile(sc, node, reg);
-       
-       return reg;
-}
-
-void compiler_get_initial_regs(struct compiler_state *sc, struct compiler_initial *initials, float *regs)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++) {
-               regs[i] = 0.0f;
-               if(sc->terminals[i].valid) {
-                       if(sc->terminals[i].isconst)
-                               regs[i] = sc->terminals[i].id.x;
-                       else {
-                               int j;
-
-                               for(j=0;j<PFPU_REG_COUNT;j++) {
-                                       if(strcmp(sc->terminals[i].id.name, initials[j].name) == 0) {
-                                               regs[i] = initials[j].x;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-void print_opcode(int opcode)
-{
-       switch(opcode) {
-               case PFPU_OPCODE_NOP:     printf("NOP     "); break;
-               case PFPU_OPCODE_FADD:    printf("FADD    "); break;
-               case PFPU_OPCODE_FSUB:    printf("FSUB    "); break;
-               case PFPU_OPCODE_FMUL:    printf("FMUL    "); break;
-               case PFPU_OPCODE_FDIV:    printf("FDIV    "); break;
-               case PFPU_OPCODE_F2I:     printf("F2I     "); break;
-               case PFPU_OPCODE_I2F:     printf("I2F     "); break;
-               case PFPU_OPCODE_VECTOUT: printf("VECTOUT "); break;
-               case PFPU_OPCODE_SIN:     printf("SIN     "); break;
-               case PFPU_OPCODE_COS:     printf("COS     "); break;
-               case PFPU_OPCODE_ABOVE:   printf("ABOVE   "); break;
-               case PFPU_OPCODE_EQUAL:   printf("EQUAL   "); break;
-               case PFPU_OPCODE_COPY:    printf("COPY    "); break;
-               default:                  printf("XXX     "); break;
-       }
-}
-
-int get_arity(int opcode)
-{
-       switch(opcode) {
-               case PFPU_OPCODE_FADD:
-               case PFPU_OPCODE_FSUB:
-               case PFPU_OPCODE_FMUL:
-               case PFPU_OPCODE_FDIV:
-               case PFPU_OPCODE_VECTOUT:
-               case PFPU_OPCODE_EQUAL:
-               case PFPU_OPCODE_ABOVE:
-                       return 2;
-               case PFPU_OPCODE_F2I:
-               case PFPU_OPCODE_I2F:
-               case PFPU_OPCODE_SIN:
-               case PFPU_OPCODE_COS:
-               case PFPU_OPCODE_COPY:
-                       return 1;
-               default:
-                       return 0;
-       }
-}
-
-void print_vprogram(struct compiler_state *sc)
-{
-       int i;
-
-       for(i=0;i<sc->prog_length;i++) {
-               printf("%04d: ", i);
-               print_opcode(sc->prog[i].opcode);
-               switch(get_arity(sc->prog[i].opcode)) {
-                       case 2:
-                               printf("R%04d,R%04d ", sc->prog[i].opa, sc->prog[i].opb);
-                               break;
-                       case 1:
-                               printf("R%04d       ", sc->prog[i].opa);
-                               break;
-                       case 0:
-                               printf("            ");
-               }
-               printf("-> R%04d", sc->prog[i].dest);
-               printf("\n");
-       }
-}
-
-void print_terminals(struct compiler_state *sc)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++) {
-               if(sc->terminals[i].valid) {
-                       printf("R%03d ", i);
-                       if(sc->terminals[i].isconst)
-                               printf("%f\n", &sc->terminals[i].id.x);
-                       else
-                               printf("%s\n", sc->terminals[i].id.name);
-               }
-       }
-}
-
diff --git a/software/demo/compiler.h b/software/demo/compiler.h
deleted file mode 100644 (file)
index b43adce..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __COMPILER_H
-#define __COMPILER_H
-
-#include <hw/pfpu.h>
-
-#include "ast.h"
-
-typedef struct {
-       int opa;
-       int opb;
-       int opcode;
-       int dest;
-} vpfpu_instruction;
-
-/*
- * Virtual registers 0-(PFPU_REG_COUNT-1) are directly mapped to physical registers.
- * The others are dynamically mapped to free physical registers by the scheduler.
- */
-
-struct compiler_terminal {
-       int valid;
-       int isconst;
-       union {
-               char name[IDENTIFIER_SIZE];
-               float x;
-       } id;
-};
-
-struct compiler_initial {
-       char name[IDENTIFIER_SIZE];
-       float x;
-};
-
-struct compiler_state {
-       int n_vregs;
-       struct compiler_terminal terminals[PFPU_REG_COUNT];
-       int prog_length;
-       vpfpu_instruction prog[PFPU_PROGSIZE];
-};
-
-void compiler_init(struct compiler_state *sc);
-int compiler_add_isn(struct compiler_state *sc, int opcode, int opa, int opb, int dest);
-int compiler_add_vreg(struct compiler_state *sc);
-int compiler_add_variable(struct compiler_state *sc, const char *name);
-int compiler_add_constant(struct compiler_state *sc, float x);
-int compiler_compile_equation(struct compiler_state *sc, const char *target, struct ast_node *node);
-void compiler_get_initial_regs(struct compiler_state *sc, struct compiler_initial *initials, float *regs);
-
-void print_opcode(int opcode);
-int get_arity(int opcode);
-void print_vprogram(struct compiler_state *sc);
-void print_terminals(struct compiler_state *sc);
-
-#endif /* __COMPILER_H */
index 57a3d48..355f854 100644 (file)
 #include <hw/tmu.h>
 
 #include <hal/pfpu.h>
+#include <fpvm/fpvm.h>
 
-#include "ast.h"
-#include "compiler.h"
-#include "scheduler.h"
 #include "eval.h"
+#include "renderer.h"
 
 //#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();
+
+void eval_init()
+{
+       eval_load_defaults();
+}
+
+int eval_schedule()
+{
+       return 1;
+}
+
 /****************************************************************/
 /* PER-FRAME VARIABLES                                          */
 /****************************************************************/
 
-static const char pfv_names[EVAL_PFV_COUNT][IDENTIFIER_SIZE] = {
+static const char pfv_names[EVAL_PFV_COUNT][FPVM_MAXSYMLEN] = {
        "cx",
        "cy",
        "rot",
@@ -86,7 +113,7 @@ static const char pfv_names[EVAL_PFV_COUNT][IDENTIFIER_SIZE] = {
        "treb_att"
 };
 
-static int pfv_from_name(const char *name)
+int eval_pfv_from_name(const char *name)
 {
        int i;
        for(i=0;i<EVAL_PFV_COUNT;i++)
@@ -101,379 +128,163 @@ static int pfv_from_name(const char *name)
        return -1;
 }
 
-static void load_defaults(struct eval_state *sc)
+static void eval_load_defaults()
 {
        int i;
 
        for(i=0;i<EVAL_PFV_COUNT;i++)
-               sc->pfv_initial[i] = 0.0;
-       sc->pfv_initial[pfv_zoom] = 1.0;
-       sc->pfv_initial[pfv_decay] = 1.0;
-       sc->pfv_initial[pfv_wave_mode] = 1.0;
-       sc->pfv_initial[pfv_wave_scale] = 1.0;
-       sc->pfv_initial[pfv_wave_r] = 1.0;
-       sc->pfv_initial[pfv_wave_g] = 1.0;
-       sc->pfv_initial[pfv_wave_b] = 1.0;
-       sc->pfv_initial[pfv_wave_a] = 1.0;
-
-       sc->pfv_initial[pfv_mv_x] = 16.0;
-       sc->pfv_initial[pfv_mv_y] = 12.0;
-       sc->pfv_initial[pfv_mv_dx] = 0.02;
-       sc->pfv_initial[pfv_mv_dy] = 0.02;
-       sc->pfv_initial[pfv_mv_l] = 1.0;
+               pfv_initial[i] = 0.0;
+       pfv_initial[pfv_zoom] = 1.0;
+       pfv_initial[pfv_decay] = 1.0;
+       pfv_initial[pfv_wave_mode] = 1.0;
+       pfv_initial[pfv_wave_scale] = 1.0;
+       pfv_initial[pfv_wave_r] = 1.0;
+       pfv_initial[pfv_wave_g] = 1.0;
+       pfv_initial[pfv_wave_b] = 1.0;
+       pfv_initial[pfv_wave_a] = 1.0;
+
+       pfv_initial[pfv_mv_x] = 16.0;
+       pfv_initial[pfv_mv_y] = 12.0;
+       pfv_initial[pfv_mv_dx] = 0.02;
+       pfv_initial[pfv_mv_dy] = 0.02;
+       pfv_initial[pfv_mv_l] = 1.0;
 }
 
-static void generate_initial(struct eval_state *sc, struct preset *ast)
+void eval_set_initial(int pfv, float x)
 {
-       struct preset_line *line;
-
-       load_defaults(sc);
-
-       line = ast->lines;
-       while(line != NULL) {
-               if(!line->iseq) {
-                       int pfv;
-
-                       pfv = pfv_from_name(line->label);
-                       if(pfv >= 0)
-                               sc->pfv_initial[pfv] = line->contents.parameter;
-               }
-               line = line->next;
-       }
+       pfv_initial[pfv] = x;
 }
 
-void eval_reset_pfv(struct eval_state *sc)
+void eval_reset_pfv()
 {
        int i;
        for(i=0;i<PFPU_REG_COUNT;i++)
-               sc->perframe_regs_current[i] = sc->perframe_regs_init[i];
+               perframe_regs_current[i] = perframe_regs_init[i];
 }
 
-int eval_reinit_pfv(struct eval_state *sc, int pfv)
+int eval_reinit_pfv(int pfv)
 {
        int r;
 
-       r = sc->pfv_allocation[pfv];
+       r = pfv_allocation[pfv];
        if(r < 0) return 0;
-       sc->perframe_regs_current[r] = sc->perframe_regs_init[r];
+       perframe_regs_current[r] = perframe_regs_init[r];
        return 1;
 }
 
-void eval_reinit_all_pfv(struct eval_state *sc)
+void eval_reinit_all_pfv()
 {
-       eval_reinit_pfv(sc, pfv_cx);
-       eval_reinit_pfv(sc, pfv_cy);
-       eval_reinit_pfv(sc, pfv_rot);
-       eval_reinit_pfv(sc, pfv_dx);
-       eval_reinit_pfv(sc, pfv_dy);
-       eval_reinit_pfv(sc, pfv_zoom);
-       eval_reinit_pfv(sc, pfv_decay);
+       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(sc, pfv_wave_mode);
-       eval_reinit_pfv(sc, pfv_wave_scale);
-       eval_reinit_pfv(sc, pfv_wave_additive);
-       eval_reinit_pfv(sc, pfv_wave_usedots);
-       eval_reinit_pfv(sc, pfv_wave_maximize_color);
-       eval_reinit_pfv(sc, pfv_wave_thick);
+       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(sc, pfv_wave_x);
-       eval_reinit_pfv(sc, pfv_wave_y);
-       eval_reinit_pfv(sc, pfv_wave_r);
-       eval_reinit_pfv(sc, pfv_wave_g);
-       eval_reinit_pfv(sc, pfv_wave_b);
-       eval_reinit_pfv(sc, pfv_wave_a);
-
-       eval_reinit_pfv(sc, pfv_ob_size);
-       eval_reinit_pfv(sc, pfv_ob_r);
-       eval_reinit_pfv(sc, pfv_ob_g);
-       eval_reinit_pfv(sc, pfv_ob_b);
-       eval_reinit_pfv(sc, pfv_ob_a);
-
-       eval_reinit_pfv(sc, pfv_ib_size);
-       eval_reinit_pfv(sc, pfv_ib_r);
-       eval_reinit_pfv(sc, pfv_ib_g);
-       eval_reinit_pfv(sc, pfv_ib_b);
-       eval_reinit_pfv(sc, pfv_ib_a);
-
-       eval_reinit_pfv(sc, pfv_mv_x);
-       eval_reinit_pfv(sc, pfv_mv_y);
-       eval_reinit_pfv(sc, pfv_mv_dx);
-       eval_reinit_pfv(sc, pfv_mv_dy);
-       eval_reinit_pfv(sc, pfv_mv_l);
-       eval_reinit_pfv(sc, pfv_mv_r);
-       eval_reinit_pfv(sc, pfv_mv_g);
-       eval_reinit_pfv(sc, pfv_mv_b);
-       eval_reinit_pfv(sc, pfv_mv_a);
+       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(sc, pfv_tex_wrap);
+       eval_reinit_pfv(pfv_tex_wrap);
 }
 
-static int generate_perframe(struct eval_state *sc, struct preset *ast)
+float eval_read_pfv(int pfv)
 {
-       struct compiler_state compiler;
-       struct compiler_initial initials[PFPU_REG_COUNT];
-       int i;
-       struct scheduler_state scheduler;
-       struct preset_line *line;
-
-       compiler_init(&compiler);
-
-       /* Add equations from MilkDrop */
-       line = ast->lines;
-       while(line != NULL) {
-               if(line->iseq && (strncmp(line->label, "per_frame_", 10) == 0)) {
-                       struct preset_equation *equation;
-
-                       equation = line->contents.equations;
-                       while(equation != NULL) {
-                               if(!compiler_compile_equation(&compiler, equation->target, equation->topnode)) return 0;
-                               equation = equation->next;
-                       }
-               }
-               line = line->next;
-       }
-
-       /* Generate initial register content */
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               initials[i].name[0] = 0;
-       for(i=0;i<EVAL_PFV_COUNT;i++) {
-               strcpy(initials[i].name, pfv_names[i]);
-               initials[i].x = sc->pfv_initial[i];
-       }
-       compiler_get_initial_regs(&compiler, initials, sc->perframe_regs_init);
-       eval_reset_pfv(sc);
-
-       /* Find out which variables we must read from the PFPU */
-       for(i=0;i<EVAL_PFV_COUNT;i++) {
-               int j;
-
-               for(j=0;j<PFPU_REG_COUNT;j++)
-                       if(
-                               compiler.terminals[j].valid
-                               && !compiler.terminals[j].isconst
-                               && (strcmp(compiler.terminals[j].id.name, pfv_names[i]) == 0)
-                       ) break;
-               if(j < PFPU_REG_COUNT)
-                       sc->pfv_allocation[i] = j;
-               else
-                       sc->pfv_allocation[i] = -1;
-       }
-
-       #ifdef EVAL_DEBUG
-       printf("======== Per-frame virtual program ========\n");
-       print_vprogram(&compiler);
-       printf("======== Per-frame static register allocation ========\n");
-       print_terminals(&compiler);
-       printf("======== Per-frame variables from PFPU ========\n");
-       for(i=0;i<EVAL_PFV_COUNT;i++)
-               if(sc->pfv_allocation[i] != -1)
-                       printf("R%03d - %s\n", sc->pfv_allocation[i], pfv_names[i]);
-       #endif
-
-       /* Schedule instructions */
-       scheduler_init(&scheduler);
-       scheduler_dont_touch(&scheduler, compiler.terminals);
-       scheduler_schedule(&scheduler, compiler.prog, compiler.prog_length);
-       /* patch the program to make a dummy DMA at the end (otherwise PFPU never finishes) */
-       scheduler.last_exit++;
-       if(scheduler.last_exit == PFPU_PROGSIZE) return 0;
-       scheduler.prog[scheduler.last_exit].i.opcode = PFPU_OPCODE_VECTOUT;
-
-       #ifdef EVAL_DEBUG
-       printf("======== Per-frame HW program ========\n");
-       print_program(&scheduler);
-       #endif
-
-       sc->perframe_prog_length = scheduler.last_exit+1;
-       for(i=0;i<=scheduler.last_exit;i++)
-               sc->perframe_prog[i].w = scheduler.prog[i].w;
-       for(;i<PFPU_PROGSIZE;i++)
-               sc->perframe_prog[i].w = 0;
+       if(pfv_allocation[pfv] < 0)
+               return pfv_initial[pfv];
+       else
+               return perframe_regs_current[pfv_allocation[pfv]];
+}
+
+void eval_write_pfv(int pfv, float x)
+{
+       if(pfv_allocation[pfv] >= 0)
+               perframe_regs_current[pfv_allocation[pfv]] = x;
+}
 
+int eval_add_per_frame(char *dest, char *val)
+{
        return 1;
 }
 
 static unsigned int dummy[2];
 
-void eval_pfv_fill_td(struct eval_state *sc, struct pfpu_td *td, pfpu_callback callback, void *user)
+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 = sc->perframe_prog;
-       td->progsize = sc->perframe_prog_length;
-       td->registers = sc->perframe_regs_current;
+       td->program = perframe_prog;
+       td->progsize = perframe_prog_length;
+       td->registers = perframe_regs_current;
        td->update = 1;
        td->invalidate = 0; /* < we don't care if our dummy variable has coherency problems */
        td->callback = callback;
        td->user = user;
 }
 
-float eval_read_pfv(struct eval_state *sc, int pfv)
-{
-       if(sc->pfv_allocation[pfv] < 0)
-               return sc->pfv_initial[pfv];
-       else
-               return sc->perframe_regs_current[sc->pfv_allocation[pfv]];
-}
-
-void eval_write_pfv(struct eval_state *sc, int pfv, float x)
-{
-       if(sc->pfv_allocation[pfv] >= 0)
-               sc->perframe_regs_current[sc->pfv_allocation[pfv]] = x;
-}
-
 /****************************************************************/
 /* PER-VERTEX VARIABLES                                         */
 /****************************************************************/
 
-static int generate_pervertex(struct eval_state *sc, struct preset *ast)
+void eval_pfv_to_pvv()
 {
-       int i;
-       struct scheduler_state scheduler;
-       vpfpu_instruction vprog[PFPU_PROGSIZE];
-       unsigned int vlen;
-       
-       sc->pvv_allocation[pvv_hmeshsize] = 3;
-       sc->pvv_allocation[pvv_vmeshsize] = 4;
-       sc->pvv_allocation[pvv_hres] = 5;
-       sc->pvv_allocation[pvv_vres] = 6;
-       sc->pvv_allocation[pvv_cx] = 7;
-       sc->pvv_allocation[pvv_cy] = 8;
-       sc->pvv_allocation[pvv_rot] = 9;
-       sc->pvv_allocation[pvv_dx] = 10;
-       sc->pvv_allocation[pvv_dy] = 11;
-       sc->pvv_allocation[pvv_zoom] = 12;
-
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               sc->pervertex_regs[i] = 0.0f;
-       sc->pervertex_regs[3] = 1.0f/(float)sc->hmeshlast;
-       sc->pervertex_regs[4] = 1.0f/(float)sc->vmeshlast;
-       sc->pervertex_regs[5] = (float)(sc->hres << TMU_FIXEDPOINT_SHIFT);
-       sc->pervertex_regs[6] = (float)(sc->vres << TMU_FIXEDPOINT_SHIFT);
-       sc->pervertex_regs[13] = PFPU_TRIG_CONV;
-
-       vlen = 0;
-       
-#define ADD_ISN(_opcode, _opa, _opb, _dest) do { \
-               vprog[vlen].opcode = _opcode; \
-               vprog[vlen].opa = _opa; \
-               vprog[vlen].opb = _opb; \
-               vprog[vlen].dest = _dest; \
-               vlen++; \
-       } while(0)
-#define BR(x) (x)                      /* bound register */
-#define FR(x) (PFPU_REG_COUNT+(x))     /* free register */
-
-       /* Compute current coordinates as floating point in range 0..1 */
-       ADD_ISN(PFPU_OPCODE_I2F,        BR(  0), BR(  0), FR(  0)); /* FR00: current X index in float */
-       ADD_ISN(PFPU_OPCODE_I2F,        BR(  1), BR(  0), FR(  1)); /* FR01: current Y index in float */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR(  0), BR(  3), FR(  2)); /* FR02: current X coord (0..1) */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR(  1), BR(  4), FR(  3)); /* FR03: current Y coord (0..1) */
-
-       /* Zoom */
-       ADD_ISN(PFPU_OPCODE_FSUB,       FR(  2), BR(  7), FR(  4)); /* FR04: x-cx */
-       ADD_ISN(PFPU_OPCODE_FSUB,       FR(  3), BR(  8), FR(  5)); /* FR05: y-cy */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR(  4), BR( 12), FR(  6)); /* FR06: zoom*(x-cx) */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR(  5), BR( 12), FR(  7)); /* FR07: zoom*(y-cy) */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR(  6), BR(  7), FR(  8)); /* FR08: final zoomed X: zoom*(x-cx)+cx */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR(  7), BR(  8), FR(  9)); /* FR09: final zoomed Y: zoom*(y-cy)+cy */
-       
-       /* Rotation */
-       ADD_ISN(PFPU_OPCODE_FMUL,       BR( 13), BR(  9), FR( 80)); /* FR80: rot*conv */
-       ADD_ISN(PFPU_OPCODE_F2I,        FR( 80), BR(  0), FR( 81)); /* FR81: int(rot*conv) */
-       ADD_ISN(PFPU_OPCODE_COS,        FR( 81), BR(  0), FR( 10)); /* FR10: cos(rot*conv) */
-       ADD_ISN(PFPU_OPCODE_SIN,        FR( 81), BR(  0), FR( 11)); /* FR11: sin(rot*conv) */
-       ADD_ISN(PFPU_OPCODE_FSUB,       FR(  8), BR(  7), FR( 12)); /* FR12: u=x-cx */
-       ADD_ISN(PFPU_OPCODE_FSUB,       FR(  9), BR(  8), FR( 13)); /* FR13: v=y-cy */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 12), FR( 10), FR( 14)); /* FR14: u*cos */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 12), FR( 11), FR( 15)); /* FR15: u*sin */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 13), FR( 10), FR( 16)); /* FR16: v*cos */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 13), FR( 11), FR( 17)); /* FR17: v*sin */
-       ADD_ISN(PFPU_OPCODE_FSUB,       FR( 14), FR( 17), FR( 18)); /* FR18: u*cos - v*sin */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR( 15), FR( 16), FR( 19)); /* FR19: u*sin + v*cos */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR( 18), BR(  7), FR( 30)); /* FR30: final rotated X: ...+cx */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR( 19), BR(  8), FR( 31)); /* FR31: final rotated Y: ...+cy */
-       
-       /* Displacement */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR( 30), BR( 10), FR( 20)); /* FR20: X */
-       ADD_ISN(PFPU_OPCODE_FADD,       FR( 31), BR( 11), FR( 21)); /* FR21: Y */
-
-       /* Convert to screen coordinates and generate vertex */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 20), BR(  5), FR( 22)); /* FR22: X screen float */
-       ADD_ISN(PFPU_OPCODE_FMUL,       FR( 21), BR(  6), FR( 23)); /* FR23: Y screen float */
-       ADD_ISN(PFPU_OPCODE_F2I,        FR( 22), BR(  0), FR( 24)); /* FR26: X screen integer */
-       ADD_ISN(PFPU_OPCODE_F2I,        FR( 23), BR(  0), FR( 25)); /* FR27: Y screen integer */
-       ADD_ISN(PFPU_OPCODE_VECTOUT,    FR( 24), FR( 25), BR(  0)); /* put out vector */
-
-#undef BR
-#undef FR
-#undef ADD_ISN
-
-       /* Schedule */
-       scheduler_init(&scheduler);
-       for(i=0;i<EVAL_PVV_COUNT;i++)
-               scheduler.dont_touch[sc->pvv_allocation[i]] = 1;
-       scheduler.dont_touch[13] = 1; /* PFPU_TRIG_CONV */
-
-       scheduler_schedule(&scheduler, vprog, vlen);
-
-       #ifdef EVAL_DEBUG
-       printf("======== Per-vertex HW program ========\n");
-       print_program(&scheduler);
-       #endif
-
-       sc->pervertex_prog_length = scheduler.last_exit+1;
-       for(i=0;i<=scheduler.last_exit;i++)
-               sc->pervertex_prog[i].w = scheduler.prog[i].w;
-       for(;i<PFPU_PROGSIZE;i++)
-               sc->pervertex_prog[i].w = 0;
-
-       return 1;
+       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);
 }
 
-void eval_pfv_to_pvv(struct eval_state *sc)
+int eval_add_per_vertex(char *dest, char *val)
 {
-       sc->pervertex_regs[sc->pvv_allocation[pvv_cx]] = eval_read_pfv(sc, pfv_cx);
-       sc->pervertex_regs[sc->pvv_allocation[pvv_cy]] = eval_read_pfv(sc, pfv_cy);
-       sc->pervertex_regs[sc->pvv_allocation[pvv_rot]] = -eval_read_pfv(sc, pfv_rot);
-       sc->pervertex_regs[sc->pvv_allocation[pvv_dx]] = -eval_read_pfv(sc, pfv_dx);
-       sc->pervertex_regs[sc->pvv_allocation[pvv_dy]] = -eval_read_pfv(sc, pfv_dy);
-       sc->pervertex_regs[sc->pvv_allocation[pvv_zoom]] = 1.0/eval_read_pfv(sc, pfv_zoom);
+       return 1;
 }
 
-void eval_pvv_fill_td(struct eval_state *sc, struct pfpu_td *td, struct tmu_vertex *vertices, pfpu_callback callback, void *user)
+void eval_pvv_fill_td(struct pfpu_td *td, struct tmu_vertex *vertices, pfpu_callback callback, void *user)
 {
        td->output = (unsigned int *)vertices;
-       td->hmeshlast = sc->hmeshlast;
-       td->vmeshlast = sc->vmeshlast;
-       td->program = sc->pervertex_prog;
-       td->progsize = sc->pervertex_prog_length;
-       td->registers = sc->pervertex_regs;
+       td->hmeshlast = renderer_hmeshlast;
+       td->vmeshlast = renderer_hmeshlast;
+       td->program = pervertex_prog;
+       td->progsize = pervertex_prog_length;
+       td->registers = pervertex_regs;
        td->update = 0; /* < no transfer of data in per-vertex equations between frames */
        td->invalidate = 1;
        td->callback = callback;
        td->user = user;
 }
-
-/****************************************************************/
-/* GENERAL                                                      */
-/****************************************************************/
-
-void eval_init(struct eval_state *sc,
-       unsigned int hmeshlast, unsigned int vmeshlast,
-       unsigned int hres, unsigned int vres)
-{
-       sc->hmeshlast = hmeshlast;
-       sc->vmeshlast = vmeshlast;
-       sc->hres = hres;
-       sc->vres = vres;
-}
-
-int eval_load_preset(struct eval_state *sc, struct preset *ast)
-{
-       generate_initial(sc, ast);
-       if(!generate_perframe(sc, ast)) return 0;
-       if(!generate_pervertex(sc, ast)) return 0;
-       return 1;
-}
index 1a0ef8d..250bdaa 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifndef __EVAL_H
 #define __EVAL_H
 
+#include <hw/tmu.h> /* for tmu_vertex */
 #include <hw/pfpu.h>
-#include <hw/tmu.h>
 
 #include <hal/pfpu.h>
 
-#include "ast.h"
+/****************************************************************/
+/* GENERAL                                                      */
+/****************************************************************/
+
+void eval_init();
+int eval_schedule();
 
 /****************************************************************/
 /* PER-FRAME VARIABLES                                          */
@@ -84,39 +89,44 @@ enum {
        EVAL_PFV_COUNT /* must be last */
 };
 
-struct eval_state;
+/* convert a variable name to its pfv_xxx number, -1 in case of failure */
+int eval_pfv_from_name(const char *name);
 
-/* fills in a task descriptor to evaluate per-frame equations */
-void eval_pfv_fill_td(struct eval_state *sc, struct pfpu_td *td, pfpu_callback callback, void *user);
+void eval_set_initial(int pfv, float x);
 
 /* restores preset's initial conditions (and reset user variables) */
-void eval_reset_pfv(struct eval_state *sc);
+void eval_reset_pfv();
 
 /* restore a variable's initial condition */
-int eval_reinit_pfv(struct eval_state *sc, int pfv);
+int eval_reinit_pfv(int pfv);
 
 /* restore all variable's initial conditions (and keep user variables) */
-void eval_reinit_all_pfv(struct eval_state *sc);
+void eval_reinit_all_pfv();
 
 /* reads the value of a per-frame variable
  * (from perframe_regs_current or initial conditions)
  * always returns a correct value; if the variable is not
  * in the preset, a default value is returned.
  */
-float eval_read_pfv(struct eval_state *sc, int pfv);
+float eval_read_pfv(int pfv);
 
 /* writes the value of a per-frame variable (to perframe_regs_current)
  * does nothing if the variable is not handled by the PFPU.
  * typically used for preset inputs (treb, bass, etc.)
  */
-void eval_write_pfv(struct eval_state *sc, int pfv, float x);
+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);
+
+/* fills in a task descriptor to evaluate per-frame equations */
+void eval_pfv_fill_td(struct pfpu_td *td, pfpu_callback callback, void *user);
+
 
 /****************************************************************/
 /* PER-VERTEX VARIABLES                                         */
 /****************************************************************/
 
-/* TODO: use texsize */
-
 enum {
        /* System */
        pvv_hmeshsize = 0,
@@ -136,36 +146,12 @@ enum {
 };
 
 /* transfer relevant per-frame variables to the per-vertex variable pool */
-void eval_pfv_to_pvv(struct eval_state *sc);
+void eval_pfv_to_pvv();
 
-/* fills in a task descriptor to evaluate per-vertex equations */
-void eval_pvv_fill_td(struct eval_state *sc, struct pfpu_td *td, struct tmu_vertex *vertices, pfpu_callback callback, void *user);
+/* add a per vertex equation in textual form */
+int eval_add_per_vertex(char *dest, char *val);
 
-/****************************************************************/
-/* GENERAL                                                      */
-/****************************************************************/
-
-struct eval_state {
-       float pfv_initial[EVAL_PFV_COUNT];              /* < preset initial conditions */
-       int pfv_allocation[EVAL_PFV_COUNT];             /* < where per-frame variables are mapped in PFPU regf, -1 if unmapped */
-       int perframe_prog_length;                       /* < how many instructions in perframe_prog */
-       pfpu_instruction perframe_prog[PFPU_PROGSIZE];  /* < PFPU per-frame microcode */
-       float perframe_regs_init[PFPU_REG_COUNT];       /* < PFPU regf according to initial conditions and constants */
-       float perframe_regs_current[PFPU_REG_COUNT];    /* < PFPU regf local copy (keeps data when PFPU is reloaded) */
-
-       int pvv_allocation[EVAL_PVV_COUNT];             /* < where per-vertex variables are mapped in PFPU regf, -1 if unmapped */
-       int pervertex_prog_length;                      /* < how many instructions in pervertex_prog */
-       pfpu_instruction pervertex_prog[PFPU_PROGSIZE]; /* < PFPU per-vertex microcode */
-       float pervertex_regs[PFPU_REG_COUNT];           /* < PFPU regf according to per-frame variables, initial conditions and constants */
-       int hmeshlast;                                  /* < index of last mesh point, X direction */
-       int vmeshlast;                                  /* < index of last mesh point, Y direction */
-       int hres;                                       /* < horizontal screen resolution */
-       int vres;                                       /* < vertical screen resolution */
-};
-
-void eval_init(struct eval_state *sc,
-       unsigned int hmeshlast, unsigned int vmeshlast,
-       unsigned int hres, unsigned int vres);
-int eval_load_preset(struct eval_state *sc, struct preset *ast);
+/* 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);
 
 #endif /* __EVAL_H */
diff --git a/software/demo/parser.y b/software/demo/parser.y
deleted file mode 100644 (file)
index 007c957..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-%include {
-       #include <assert.h>
-       #include <string.h>
-       #include <stdlib.h>
-       #include <malloc.h>
-       #include <math.h>
-       #include "ast.h"
-}
-
-%start_symbol start
-%extra_argument {struct preset **parseout}
-%token_type {void *}
-
-%token_destructor { free($$); }
-
-%type preset {struct preset *}
-%destructor preset { free($$); }
-%type line {struct preset_line *}
-%type line_p {struct preset_line *}
-%destructor line_p { free($$); }
-%type line_e {struct preset_line *}
-%destructor line_e { free($$); }
-%type parameter {struct preset_parameter *}
-%destructor parameter { free($$); }
-%type equation {struct preset_equation *}
-%destructor equation { free($$); }
-%type node {struct ast_node *}
-%destructor node { free($$); }
-
-start(S) ::= preset(P). {
-       S = P;
-       *parseout = S;
-}
-
-preset(P) ::= line(L). {
-       P = malloc(sizeof(struct preset));
-       P->lines = L;
-       P->last_line = L;
-}
-
-preset(P) ::= preset(B) TOK_NEWLINE line(L). {
-       P = B;
-       if(L != NULL) {
-               if(P->lines == NULL) {
-                       P->lines = L;
-                       P->last_line = L;
-               } else {
-                       P->last_line->next = L;
-                       P->last_line = L;
-               }
-       }
-}
-
-preset(P) ::= preset(B) TOK_NEWLINE. { P = B; }
-
-line(A) ::= line_p(B). { A = B; }
-line(A) ::= line_e(B). { A = B; }
-line(A) ::= line_n. { A = NULL; }
-
-line_p(L) ::= TOK_IDENT(I) TOK_EQUAL TOK_CONSTANT(C). {
-       L = malloc(sizeof(struct preset_line));
-       strncpy(L->label, I, sizeof(L->label));
-       L->label[sizeof(L->label)-1] = 0;
-       L->iseq = 0;
-       L->contents.parameter = atof(C);
-}
-
-line_p(L) ::= TOK_IDENT(I) TOK_EQUAL TOK_MINUS TOK_CONSTANT(C). {
-       L = malloc(sizeof(struct preset_line));
-       strncpy(L->label, I, sizeof(L->label));
-       L->label[sizeof(L->label)-1] = 0;
-       L->iseq = 0;
-       L->contents.parameter = -atof(C);
-}
-
-line_e(L) ::= TOK_IDENT(I) TOK_EQUAL equation(E). {
-       L = malloc(sizeof(struct preset_line));
-       strncpy(L->label, I, sizeof(L->label));
-       L->label[sizeof(L->label)-1] = 0;
-       L->iseq = 1;
-       L->contents.equations = E;
-}
-
-line_e(L) ::= line_e(B) TOK_SEMICOLON equation(E). {
-       L = B;
-       if(L->contents.equations != NULL) {
-               struct preset_equation *current;
-               
-               current = L->contents.equations;
-               while(current->next != NULL)
-                       current = current->next;
-               current->next = E;
-       } else
-               L->contents.equations = E; /* should not happen */
-}
-
-line_e(L) ::= line_e(B) TOK_SEMICOLON. { L = B; }
-
-line_n ::= TOK_IDENT TOK_EQUAL.
-
-equation(E) ::= TOK_IDENT(I) TOK_EQUAL node(N). {
-       E = malloc(sizeof(struct preset_equation));
-       strncpy(E->target, I, sizeof(E->target));
-       E->target[sizeof(E->target)-1] = 0;
-       E->topnode = N;
-       E->next = NULL;
-}
-
-node(N) ::= TOK_CONSTANT(C). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = 0;
-       N->contents.constant = atof(C);
-}
-
-node(N) ::= TOK_IDENT(I). {
-       N = malloc(sizeof(struct ast_node));
-       strncpy(N->label, I, sizeof(N->label));
-       N->label[sizeof(N->label)-1] = 0;
-       N->contents.branches.a = NULL;
-}
-
-%left TOK_PLUS.
-%left TOK_MINUS.
-%left TOK_MULTIPLY.
-%left TOK_DIVIDE.
-%left TOK_PERCENT.
-%left TOK_NOT.
-
-node(N) ::= node(A) TOK_PLUS node(B). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '+';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= node(A) TOK_MINUS node(B). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '-';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= node(A) TOK_MULTIPLY node(B). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '*';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= node(A) TOK_DIVIDE node(B). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '/';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= node(A) TOK_PERCENT node(B). {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '%';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= TOK_MINUS node(A). [TOK_NOT] {
-       N = malloc(sizeof(struct ast_node));
-       N->label[0] = '!';
-       N->label[1] = 0;
-       N->contents.branches.a = A;
-}
-
-node(N) ::= TOK_IDENT(I) TOK_LPAREN node(A) TOK_RPAREN. {
-       N = malloc(sizeof(struct ast_node));
-       strncpy(N->label, I, sizeof(N->label));
-       N->label[sizeof(N->label)-1] = 0;
-       N->contents.branches.a = A;
-}
-
-node(N) ::= TOK_IDENT(I) TOK_LPAREN node(A) TOK_COMMA node(B) TOK_RPAREN. {
-       N = malloc(sizeof(struct ast_node));
-       strncpy(N->label, I, sizeof(N->label));
-       N->label[sizeof(N->label)-1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-}
-
-node(N) ::= TOK_IDENT(I) TOK_LPAREN node(A) TOK_COMMA node(B) TOK_COMMA node(C) TOK_RPAREN. {
-       N = malloc(sizeof(struct ast_node));
-       strncpy(N->label, I, sizeof(N->label));
-       N->label[sizeof(N->label)-1] = 0;
-       N->contents.branches.a = A;
-       N->contents.branches.b = B;
-       N->contents.branches.c = C;
-}
-
-node(N) ::= TOK_LPAREN node(A) TOK_RPAREN. {
-       N = A;
-}
diff --git a/software/demo/parser_helper.c b/software/demo/parser_helper.c
deleted file mode 100644 (file)
index 855977b..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <malloc.h>
-
-#include "scanner.h"
-#include "ast.h"
-#include "parser_helper.h"
-
-struct preset *generate_ast(char *preset_code)
-{
-       struct scanner *s;
-       int tok;
-       char *identifier;
-       void *p;
-       struct preset *ast;
-       
-       s = new_scanner(preset_code);
-       ast = NULL;
-       p = ParseAlloc(malloc);
-       tok = scan(s);
-       while(tok != TOK_EOF) {
-               identifier = malloc(IDENTIFIER_SIZE);
-               get_token(s, identifier, IDENTIFIER_SIZE);
-               Parse(p, tok, identifier, &ast);
-               if(tok == TOK_ERROR) {
-                       printf("Scan error\n");
-                       break;
-               }
-               tok = scan(s);
-       }
-       Parse(p, TOK_EOF, NULL, &ast);
-       ParseFree(p, free);
-       delete_scanner(s);
-
-       if(ast == NULL) {
-               printf("Parse error\n");
-               return NULL;
-       }
-
-       return ast;
-}
-
-static void free_ast_nodes(struct ast_node *node)
-{
-       if(node == NULL) return;
-       if(node->label[0] != 0) {
-               free_ast_nodes(node->contents.branches.a);
-               free_ast_nodes(node->contents.branches.b);
-               free_ast_nodes(node->contents.branches.c);
-       }
-       free(node);
-}
-
-static void free_equations(struct preset_equation *equations)
-{
-       struct preset_equation *next;
-
-       while(equations != NULL) {
-               free_ast_nodes(equations->topnode);
-               next = equations->next;
-               free(equations);
-               equations = next;
-       }
-}
-
-static void free_lines(struct preset_line *line)
-{
-       struct preset_line *next;
-
-       while(line != NULL) {
-               if(line->iseq)
-                       free_equations(line->contents.equations);
-               next = line->next;
-               free(line);
-               line = next;
-       }
-}
-
-void free_ast(struct preset *p)
-{
-       free_lines(p->lines);
-       free(p);
-}
-
diff --git a/software/demo/parser_helper.h b/software/demo/parser_helper.h
deleted file mode 100644 (file)
index b017619..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __PARSER_HELPER_H
-#define __PARSER_HELPER_H
-
-#include "ast.h"
-
-struct preset *generate_ast(char *preset_code);
-void free_ast(struct preset *p);
-
-#endif /* __PARSER_HELPER_H */
index c11e42a..faade37 100644 (file)
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <math.h>
 #include <system.h>
 
 #include <hal/pfpu.h>
 #include <hal/vga.h>
 
-#include "parser_helper.h"
 #include "eval.h"
 #include "apipe.h"
 #include "renderer.h"
@@ -39,28 +39,136 @@ void renderer_init()
        printf("RDR: renderer ready (mesh:%dx%d, texsize:%d)\n", renderer_hmeshlast, renderer_vmeshlast, renderer_texsize);
 }
 
-static struct eval_state eval;
+static unsigned int linenr;
 
-int renderer_start(char *preset_code)
+static int process_equation(char *equation, int per_vertex)
 {
-       struct preset *ast;
+       char *c, *c2;
 
-       ast = generate_ast(preset_code);
-       if(!ast) {
-               printf("RDR: preset parsing failed\n");
+       c = strchr(equation, '=');
+       if(!c) {
+               printf("RDR: error l.%d: malformed equation\n");
                return 0;
        }
+       *c = 0;
+       
+       c2 = c;
+       while((c2 > equation) && (*c2 == ' ')) c2--;
+       *c2 = 0;
+       
+       c++;
+       while(*c == ' ') c++;
 
-       eval_init(&eval, renderer_hmeshlast, renderer_vmeshlast, renderer_texsize, renderer_texsize);
-       if(!eval_load_preset(&eval, ast)) {
-               printf("RDR: preset loading failed\n");
+       if(*equation == 0) {
+               printf("RDR: error l.%d: missing lvalue\n");
+               return 0;
+       }
+       if(*c == 0) {
+               printf("RDR: error l.%d: missing rvalue\n");
                return 0;
        }
+
+       if(per_vertex)
+               return eval_add_per_vertex(equation, c);
+       else
+               return eval_add_per_frame(equation, c);
+}
+
+static int process_equations(char *equations, int per_vertex)
+{
+       char *c;
+
+       while(*equations) {
+               c = strchr(equations, ';');
+               if(!c)
+                       return process_equation(equations, per_vertex);
+               *c = 0;
+               if(!process_equation(equations, per_vertex)) return 0;
+               equations = c + 1;
+       }
+       return 1;
+}
+
+static int process_top_assign(char *left, char *right)
+{
+       int pfv;
        
-       free_ast(ast);
+       while(*right == ' ') right++;
+       if(*right == 0) return 1;
 
-       apipe_start(&eval);
+       pfv = eval_pfv_from_name(left);
+       if(pfv >= 0) {
+               /* preset initial condition or global parameter */
+               eval_set_initial(pfv, atof(right));
+               return 1;
+       }
+
+       if(strncmp(left, "per_frame_", 10) == 0)
+               /* per-frame equation */
+               return process_equations(right, 0);
+
+       if((strncmp(left, "per_vertex_", 11) == 0) || (strncmp(left, "per_pixel_", 10) == 0))
+               /* per-vertex equation */
+               return process_equations(right, 1);
 
+       printf("RDR: warning l.%d: ignoring unknown parameter %s\n", linenr, left);
+       
+       return 1;
+}
+
+static int process_line(char *line)
+{
+       char *c;
+       
+       while(*line == ' ') line++;
+       if(*line == 0) return 1;
+       if(*line == '[') return 1;
+
+       c = strstr(line, "//");
+       if(c) *c = 0;
+       
+       c = line + strlen(line);
+       while((c > line) && (*c == ' ')) c--;
+       *c = 0;
+       if(*line == 0) return 1;
+
+       c = strchr(line, '=');
+       if(!c) {
+               printf("RDR: error l.%d: '=' expected\n", linenr);
+               return 0;
+       }
+       *c = 0;
+       return process_top_assign(line, c+1);
+}
+
+static int load_preset(char *preset_code)
+{
+       char *eol;
+       
+       linenr = 0;
+       while(*preset_code) {
+               linenr++;
+               eol = strchr(preset_code, '\n');
+               if(!eol)
+                       return process_line(preset_code);
+               *eol = 0;
+               if(*preset_code == 0) {
+                       preset_code = eol + 1;
+                       continue;
+               }
+               if(*(eol - 1) == '\r') *(eol - 1) = 0;
+               if(!process_line(preset_code)) return 0;
+               preset_code = eol + 1;
+       }
+       return 1;
+}
+
+int renderer_start(char *preset_code)
+{
+       eval_init();
+       if(!load_preset(preset_code)) return 0;
+       eval_schedule();
+       apipe_start();
        return 1;
 }
 
diff --git a/software/demo/scanner.h b/software/demo/scanner.h
deleted file mode 100644 (file)
index 46a9164..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SCANNER_H
-#define __SCANNER_H
-
-#define TOK_ERROR      (-1)
-#define TOK_EOF                0
-
-#include "parser.h"
-
-struct scanner {
-       unsigned char *marker;
-       unsigned char *old_cursor;
-       unsigned char *cursor;
-       unsigned char *limit;
-};
-
-struct scanner *new_scanner(unsigned char *input);
-void delete_scanner(struct scanner *s);
-
-/* get to the next token and return its type */
-int scan(struct scanner *s);
-
-/* get the string comprising the current token
- * length is the size of the passed buffer, counting
- * the terminating NUL character.
- * returns the number of characters actually written
- * to the buffer, not counting the NUL character.
- */
-int get_token(struct scanner *s, unsigned char *buffer, int length);
-
-#endif /* __SCANNER_H */
-
diff --git a/software/demo/scanner.re b/software/demo/scanner.re
deleted file mode 100644 (file)
index e1ec5ac..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <malloc.h>
-
-#include "scanner.h"
-
-#define YYCTYPE     unsigned char
-#define YYCURSOR    s->cursor
-#define YYLIMIT     s->limit
-
-/* refilling not supported */
-#define YYMARKER s->marker
-#define YYFILL(n)
-
-struct scanner *new_scanner(unsigned char *input)
-{
-       struct scanner *s;
-       
-       s = malloc(sizeof(struct scanner));
-       if(s == NULL) return NULL;
-       
-       s->marker = input;
-       s->old_cursor = input;
-       s->cursor = input;
-       s->limit = input + strlen(input);
-       
-       return s;
-}
-
-void delete_scanner(struct scanner *s)
-{
-       free(s);
-}
-
-int scan(struct scanner *s)
-{
-       std:
-       if(s->cursor == s->limit) return TOK_EOF;
-       s->old_cursor = s->cursor;
-       
-       /*!re2c
-               [\x20\r\t]                              { goto std; }
-               "\n"                                    { return TOK_NEWLINE; }
-               "//" ([\x00-\x09\x0b-\xff])* "\n"       { return TOK_NEWLINE; }
-               "[" ([\x00-\x09\x0b-\xff])* "\n"        { goto std; }
-               ";"                                     { return TOK_SEMICOLON; }
-               [0-9]+                                  { return TOK_CONSTANT; }
-               [0-9]* "." [0-9]*                       { return TOK_CONSTANT; }
-               [a-zA-Z_0-9]+                           { return TOK_IDENT; }
-               "+"                                     { return TOK_PLUS; }
-               "-"                                     { return TOK_MINUS; }
-               "*"                                     { return TOK_MULTIPLY; }
-               "/"                                     { return TOK_DIVIDE; }
-               "%"                                     { return TOK_PERCENT; }
-               "("                                     { return TOK_LPAREN; }
-               ")"                                     { return TOK_RPAREN; }
-               ","                                     { return TOK_COMMA; }
-               "="                                     { return TOK_EQUAL; }
-               [\x00-\xff]                             { return TOK_ERROR; }
-       */
-}
-
-int get_token(struct scanner *s, unsigned char *buffer, int length)
-{
-       int total_length;
-       int copy_length;
-       int i;
-       
-       total_length = copy_length = s->cursor - s->old_cursor;
-       if(copy_length >= length)
-               copy_length = length - 1;
-       for(i=0;i<copy_length;i++)
-               buffer[i] = s->old_cursor[i];
-       buffer[copy_length] = 0;
-       return total_length;
-}
diff --git a/software/demo/scheduler.c b/software/demo/scheduler.c
deleted file mode 100644 (file)
index bfd5a52..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <hw/pfpu.h>
-
-#include "scheduler.h"
-
-//#define SCHEDULER_DEBUG
-
-static int get_latency(int opcode)
-{
-       switch(opcode) {
-               case PFPU_OPCODE_FADD: return PFPU_LATENCY_FADD;
-               case PFPU_OPCODE_FSUB: return PFPU_LATENCY_FSUB;
-               case PFPU_OPCODE_FMUL: return PFPU_LATENCY_FMUL;
-               case PFPU_OPCODE_FDIV: return PFPU_LATENCY_FDIV;
-               case PFPU_OPCODE_F2I: return PFPU_LATENCY_F2I;
-               case PFPU_OPCODE_I2F: return PFPU_LATENCY_I2F;
-               case PFPU_OPCODE_VECTOUT: return PFPU_LATENCY_VECTOUT;
-               case PFPU_OPCODE_SIN: return PFPU_LATENCY_SIN;
-               case PFPU_OPCODE_COS: return PFPU_LATENCY_COS;
-               case PFPU_OPCODE_ABOVE: return PFPU_LATENCY_ABOVE;
-               case PFPU_OPCODE_EQUAL: return PFPU_LATENCY_EQUAL;
-               case PFPU_OPCODE_COPY: return PFPU_LATENCY_COPY;
-               default: return -1;
-       }
-}
-
-void scheduler_init(struct scheduler_state *sc)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               sc->dont_touch[i] = pfpu_is_reserved(i);
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               sc->register_allocation[i] = -1;
-       for(i=0;i<PFPU_PROGSIZE;i++)
-               sc->exits[i] = -1;
-       for(i=0;i<PFPU_PROGSIZE;i++)
-               sc->prog[i].w = 0;
-       sc->last_exit = -1;
-}
-
-void scheduler_dont_touch(struct scheduler_state *sc, struct compiler_terminal *terminals)
-{
-       int i;
-
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               if(terminals[i].valid)
-                       sc->dont_touch[i] = 1;
-}
-
-/*
- * Check that any instruction before 'instruction'
- * that writes to register 'reg' has completed at cycle 'cycle'.
- * Returns 1 if ok.
- */
-static int check_hazard_write(struct scheduler_state *sc, int reg, int cycle, int instruction, vpfpu_instruction *visn)
-{
-       int i;
-
-       #ifdef SCHEDULER_DEBUG
-       printf("check_hazard_write: reg=%d cycle=%d isn=%d: ", reg, cycle, instruction);
-       #endif
-       for(i=instruction-1;i>=0;i--)
-               if(visn[i].dest == reg) {
-                       #ifdef SCHEDULER_DEBUG
-                       printf("previous isn %d ", i);
-                       #endif
-                       if((sc->exits[i] > 0) && (cycle > sc->exits[i])) {
-                               #ifdef SCHEDULER_DEBUG
-                               printf("completed (%d)\n", sc->exits[i]);
-                               #endif
-                               return 1;
-                       } else {
-                               #ifdef SCHEDULER_DEBUG
-                               printf("not completed (%d)\n", sc->exits[i]);
-                               #endif
-                               return 0;
-                       }
-               }
-       #ifdef SCHEDULER_DEBUG
-       printf("no previous isn\n");
-       #endif
-       return 1;
-}
-
-/*
- * Check that any instruction before 'instruction'
- * that reads register 'reg' has been scheduled.
- * Returns 1 if ok.
- */
-static int check_hazard_read(struct scheduler_state *sc, int reg, int instruction, vpfpu_instruction *visn)
-{
-       int i;
-
-       for(i=instruction-1;i>0;i--) {
-               if(sc->exits[i] < 0) {
-                       switch(get_arity(visn[i].opcode)) {
-                               case 2:
-                                       if(visn[i].opb == reg) return 0;
-                                       /* fall through */
-                               case 1:
-                                       if(visn[i].opa == reg) return 0;
-                                       /* fall through */
-                               case 0:
-                                       break;
-                               default:
-                                       /* we should not get here - make the compilation fail */
-                                       return 0;
-                       }
-               }
-       }
-       return 1;
-}
-
-static int allocate_physical_register(struct scheduler_state *sc, int reg)
-{
-       int i;
-       
-       if(reg < PFPU_REG_COUNT) return reg;
-       for(i=0;i<PFPU_REG_COUNT;i++) {
-               if(sc->dont_touch[i]) continue;
-               if(sc->register_allocation[i] < 0) {
-                       sc->register_allocation[i] = reg;
-                       return i;
-               }
-       }
-       return -1;
-}
-
-static int find_physical_register(struct scheduler_state *sc, int reg)
-{
-       int i;
-       
-       if(reg < PFPU_REG_COUNT) return reg;
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               if(sc->register_allocation[i] == reg) return i;
-       return -1;
-}
-
-static void try_free_register(struct scheduler_state *sc, vpfpu_instruction *visn, int firstisn, int lastisn, int reg)
-{
-       int i;
-       
-       if(reg < PFPU_REG_COUNT) return;
-       
-       for(i=firstisn;i<=lastisn;i++) {
-               switch(get_arity(visn[i].opcode)) {
-                       case 2:
-                               if(visn[i].opb == reg) return;
-                               /* fall through */
-                       case 1:
-                               if(visn[i].opa == reg) return;
-                               /* fall through */
-                       case 0:
-                               break;
-                       default:
-                               /* should not get here */
-                               return;
-               }
-       }
-
-       #ifdef SCHEDULER_DEBUG
-       printf("freeing virtual register %d (physical:", reg);
-       #endif
-       for(i=0;i<PFPU_REG_COUNT;i++)
-               if(sc->register_allocation[i] == reg) {
-                       #ifdef SCHEDULER_DEBUG
-                       printf(" %d", i);
-                       #endif
-                       sc->register_allocation[i] = -1;
-               }
-       #ifdef SCHEDULER_DEBUG
-       printf(")\n");
-       #endif
-}
-
-/*
- * -1: fatal error
- *  0: instruction cannot be scheduled
- *  1: instruction was scheduled
- */
-static int schedule_one(struct scheduler_state *sc, int cycle, int instruction, vpfpu_instruction *visn, int vlength)
-{
-       int exit;
-       int opa, opb, dest;
-       
-       if(sc->exits[instruction] != -1) return 0; /* already scheduled */
-
-       exit = get_latency(visn[instruction].opcode);
-       if(exit < 0) {
-               #ifdef SCHEDULER_DEBUG
-               printf("schedule_one: invalid opcode\n");
-               #endif
-               return -1;
-       }
-       exit += cycle;
-       if(exit >= PFPU_PROGSIZE) {
-               #ifdef SCHEDULER_DEBUG
-               printf("schedule_one: instruction can never exit\n");
-               #endif
-               return -1;
-       }
-
-       if(sc->prog[exit].i.dest != 0) return 0; /* exit conflict */
-       
-       /* Check for RAW hazards */
-       switch(get_arity(visn[instruction].opcode)) {
-               case 2:
-                       if(!check_hazard_write(sc, visn[instruction].opb, cycle, instruction, visn)) return 0;
-                       /* fall through */
-               case 1:
-                       if(!check_hazard_write(sc, visn[instruction].opa, cycle, instruction, visn)) return 0;
-                       /* fall through */
-               case 0:
-                       break;
-               default:
-                       #ifdef SCHEDULER_DEBUG
-                       printf("schedule_one: unexpected arity\n");
-                       #endif
-                       return -1;
-       }
-       /* Check for WAR hazards */
-       if(!check_hazard_read(sc, visn[instruction].dest, instruction, visn)) return 0;
-       /* Check for WAW hazards */
-       if(!check_hazard_write(sc, visn[instruction].dest, cycle, instruction, visn)) return 0;
-
-       /* OK - Instruction can be scheduled */
-
-       /* Find operands */
-       opa = opb = 0;
-       switch(get_arity(visn[instruction].opcode)) {
-               case 2:
-                       opb = find_physical_register(sc, visn[instruction].opb);
-                       /* fall through */
-               case 1:
-                       opa = find_physical_register(sc, visn[instruction].opa);
-                       /* fall through */
-               case 0:
-                       break;
-               default:
-                       #ifdef SCHEDULER_DEBUG
-                       printf("schedule_one: unexpected arity\n");
-                       #endif
-                       return -1;
-       }
-       if((opa < 0)||(opb < 0)) {
-               #ifdef SCHEDULER_DEBUG
-               printf("schedule_one: operands not found\n");
-               #endif
-               return -1;
-       }
-
-       /* If operands are not used by further instructions, free their registers */
-       switch(get_arity(visn[instruction].opcode)) {
-               case 2:
-                       try_free_register(sc, visn, instruction+1, vlength-1, visn[instruction].opb);
-                       /* fall through */
-               case 1:
-                       try_free_register(sc, visn, instruction+1, vlength-1, visn[instruction].opa);
-                       /* fall through */
-               case 0:
-                       break;
-               default:
-                       #ifdef SCHEDULER_DEBUG
-                       printf("schedule_one: unexpected arity\n");
-                       #endif
-                       return -1;
-       }
-
-       /* Find destination */
-       dest = allocate_physical_register(sc, visn[instruction].dest);
-       if(dest == -1) {
-               #ifdef SCHEDULER_DEBUG
-               printf("schedule_one: destination not found\n");
-               #endif
-               return -1;
-       }
-       sc->register_allocation[dest] = visn[instruction].dest;
-
-       /* Write instruction */
-       sc->prog[cycle].i.opa = opa;
-       sc->prog[cycle].i.opb = opb;
-       sc->prog[cycle].i.opcode = visn[instruction].opcode;
-       sc->prog[exit].i.dest = dest;
-       sc->exits[instruction] = exit;
-       if(exit > sc->last_exit) sc->last_exit = exit;
-
-       return 1;
-}
-
-int scheduler_schedule(struct scheduler_state *sc, vpfpu_instruction *visn, int vlength)
-{
-       int i, j;
-       int remaining;
-       int r;
-
-       if(vlength < 1) return 1;
-       remaining = vlength;
-       for(i=0;i<PFPU_PROGSIZE;i++) {
-               for(j=0;j<vlength;j++) {
-                       r = schedule_one(sc, i, j, visn, vlength);
-                       if(r == -1) {
-                               #ifdef SCHEDULER_DEBUG
-                               printf("scheduler_schedule: returned error, cycle=%d visn=%d\n", i, j);
-                               #endif
-                               return 0;
-                       }
-                       if(r == 1) {
-                               remaining--;
-                               if(remaining == 0) return 1;
-                               break;
-                       }
-                       /* r == 0 */
-               }
-       }
-       
-       #ifdef SCHEDULER_DEBUG
-       printf("scheduler_schedule: out of program space\n");
-       #endif
-       return 0;
-}
-
-void print_program(struct scheduler_state *sc)
-{
-       int i;
-       int exits;
-
-       exits = 0;
-       for(i=0;i<=sc->last_exit;i++) {
-               int latency;
-
-               printf("%04d: ", i);
-
-               print_opcode(sc->prog[i].i.opcode);
-
-               switch(get_arity(sc->prog[i].i.opcode)) {
-                       case 2:
-                               printf("R%03d,R%03d ", sc->prog[i].i.opa, sc->prog[i].i.opb);
-                               break;
-                       case 1:
-                               printf("R%03d      ", sc->prog[i].i.opa);
-                               break;
-                       case 0:
-                               printf("          ");
-               }
-
-               latency = get_latency(sc->prog[i].i.opcode);
-               if(sc->prog[i].i.opcode != PFPU_OPCODE_NOP)
-                       printf("[L=%d E=%04d] ", latency, i+latency);
-               else
-                       printf("             ");
-
-               if(sc->prog[i].i.dest != 0) {
-                       printf("-> R%03d", sc->prog[i].i.dest);
-                       exits++;
-               }
-
-               printf("\n");
-       }
-       printf("Efficiency: %d%%\n", 100*exits/(sc->last_exit+1));
-}
diff --git a/software/demo/scheduler.h b/software/demo/scheduler.h
deleted file mode 100644 (file)
index c36de15..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SCHEDULER_H
-#define __SCHEDULER_H
-
-#include <hw/pfpu.h>
-#include "compiler.h"
-
-struct scheduler_state {
-       int dont_touch[PFPU_REG_COUNT];
-       int register_allocation[PFPU_REG_COUNT];
-       int exits[PFPU_PROGSIZE];
-       int last_exit;
-       pfpu_instruction prog[PFPU_PROGSIZE];
-};
-
-void scheduler_init(struct scheduler_state *sc);
-void scheduler_dont_touch(struct scheduler_state *sc, struct compiler_terminal *terminals);
-int scheduler_schedule(struct scheduler_state *sc, vpfpu_instruction *visn, int vlength);
-
-void print_program(struct scheduler_state *sc);
-
-#endif /* __SCHEDULER_H */
index 9732b4a..9ed9d9f 100644 (file)
@@ -202,8 +202,7 @@ static void stats()
        if(occupancy != 0) {
                printf("Net memory bandwidth      : %d Mbps\n", netbw);
                printf("Memory bus occupancy      : %d%%\n", occupancy);
-               printf("Extrapolated max bandwidth: %d Mbps\n", (100*netbw)/occupancy);
-               printf("Avg. mem. access time     : %d.%d cycles\n", amat/100, amat%100);
+               printf("Avg. mem. access time     : %d.%02d cycles\n", amat/100, amat%100);
        }
 }
 
index f619095..6fa737a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * Copyright (C) Linux kernel developers
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ * Copyright (C) Linus Torvalds and Linux kernel developers
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,5 +34,6 @@ int memcmp(const void *cs, const void *ct, size_t count);
 void *memset(void *s, int c, size_t count);
 void *memcpy(void *dest, const void *src, size_t n);
 void *memmove(void *dest, const void *src, size_t count);
+char *strstr(const char *s1, const char *s2);
 
 #endif /* __STRING_H */
index 30c3155..0139c97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * Copyright (C) Linux kernel developers
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ * Copyright (C) Linus Torvalds and Linux kernel developers
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -244,6 +244,27 @@ void *memmove(void *dest, const void *src, size_t count)
        return dest;
 }
 
+/**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char *strstr(const char *s1, const char *s2)
+{
+       size_t l1, l2;
+
+       l2 = strlen(s2);
+       if (!l2)
+               return (char *)s1;
+       l1 = strlen(s1);
+       while (l1 >= l2) {
+               l1--;
+               if (!memcmp(s1, s2, l2))
+                       return (char *)s1;
+               s1++;
+       }
+       return NULL;
+}
 
 /**
  * strtoul - convert a string to an unsigned long
index 9c74e7b..baea5d7 100644 (file)
@@ -400,7 +400,6 @@ void microudp_service()
                CSR_MINIMAC_STATE0 = MINIMAC_STATE_LOADED;
                /* Now we have time to do the processing */
                process_frame();
-               
        }
        CSR_MINIMAC_SETUP = 0;
 }