Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 4 commits
  • 6 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 15, 2012
@wpwrak wpwrak pfpuasm: auto-NOP, pass all regs, and some syntax corrections
A number of small improvements:

- VECTOUT doesn't need a destination register (use 0)
- QUAKE is unary, not binary
- option -a to automatically fill the latency slots with NOP
  (without caring about efficiency)
- all registers referenced (read or write) are listed
539486b
Commits on Jan 16, 2012
@wpwrak wpwrak asm/pfpu: new option -v; cleanup
This patch contains the following changes:

- new option -v for verbose operation. By default, pfpu now only displays
  the result line and ignores the rest of the session.

- send nc's diagnostics to standard output so that we can suppress
  its "connected" line (alas, this means that error messages are
  only shown in verbose mode)

- added header comment
da4c311
@wpwrak wpwrak asm/fpvm: fpvm-like execution engine
This engine also accepts symbolic register names. Uses pfpu for
stepwise execution.
9f7ff2c
@wpwrak wpwrak asm/mod.fpvm: modulo calculation example
Run with
./fpvm mod.fpvm

Or, more entertaining
./fpvm -x mod.fpvm

For every last gory detail, use
./fpvm -d -x mod.fpvm
6f346c3
View
76 tools/asm/asm.y
@@ -27,14 +27,24 @@
static void emit(int opcode, int opa, int opb, int dest, int latency)
{
- *pc++ |= opcode << OPCODE_SHIFT | opb << OPB_SHIFT | opa << OPA_SHIFT;
+ *pc |= opcode << OPCODE_SHIFT | opb << OPB_SHIFT | opa << OPA_SHIFT;
- if (dest <= 0)
+ if (dest <= 0) {
+ pc++;
return;
-
- if (pc[latency-1] & (DEST_MASK << DEST_SHIFT))
- yyerror("destination conflict");
- pc[latency-1] |= dest << DEST_SHIFT;
+ }
+
+ if (auto_nop) {
+ pc += latency;
+ if (*pc & (DEST_MASK << DEST_SHIFT))
+ yyerror("destination conflict");
+ *pc |= dest << DEST_SHIFT;
+ pc++;
+ } else {
+ if (pc[latency-1] & (DEST_MASK << DEST_SHIFT))
+ yyerror("destination conflict");
+ pc[latency-1] |= dest << DEST_SHIFT;
+ }
}
%}
@@ -56,21 +66,20 @@ static void emit(int opcode, int opa, int opb, int dest, int latency)
%token <reg> REG
%type <i> value
+%type <reg> reg
%%
all:
- regs ops;
+ initials ops;
-regs:
- | reg regs;
+initials:
+ | initial initials;
-reg:
+initial:
REG '=' value
{
regs[$1] = $3;
- if ($1 > max_reg)
- max_reg = $1;
}
;
@@ -93,64 +102,73 @@ op:
{
emit(PFPU_OPCODE_NOP, 0, 0, 0, -1);
}
- | TOK_FADD REG ',' REG ARROW REG
+ | TOK_FADD reg ',' reg ARROW reg
{
BINARY(FADD, $2, $4, $6);
}
- | TOK_FSUB REG ',' REG ARROW REG
+ | TOK_FSUB reg ',' reg ARROW reg
{
BINARY(FSUB, $2, $4, $6);
}
- | TOK_FMUL REG ',' REG ARROW REG
+ | TOK_FMUL reg ',' reg ARROW reg
{
BINARY(FMUL, $2, $4, $6);
}
- | TOK_FABS REG ARROW REG
+ | TOK_FABS reg ARROW reg
{
UNARY(FABS, $2, $4);
}
- | TOK_F2I REG ARROW REG
+ | TOK_F2I reg ARROW reg
{
UNARY(F2I, $2, $4);
}
- | TOK_I2F REG ARROW REG
+ | TOK_I2F reg ARROW reg
{
UNARY(I2F, $2, $4);
}
- | TOK_VECTOUT REG ',' REG ARROW REG
+ | TOK_VECTOUT reg ',' reg
{
- BINARY(VECTOUT, $2, $4, $6);
+ BINARY(VECTOUT, $2, $4, 0);
}
- | TOK_SIN REG ARROW REG
+ | TOK_SIN reg ARROW reg
{
UNARY(SIN, $2, $4);
}
- | TOK_COS REG ARROW REG
+ | TOK_COS reg ARROW reg
{
UNARY(COS, $2, $4);
}
- | TOK_ABOVE REG ',' REG ARROW REG
+ | TOK_ABOVE reg ',' reg ARROW REG
{
BINARY(ABOVE, $2, $4, $6);
}
- | TOK_EQUAL REG ',' REG ARROW REG
+ | TOK_EQUAL reg ',' reg ARROW reg
{
BINARY(EQUAL, $2, $4, $6);
}
- | TOK_COPY REG ARROW REG
+ | TOK_COPY reg ARROW reg
{
UNARY(COPY, $2, $4);
}
- | TOK_IF REG ',' REG ARROW REG
+ | TOK_IF reg ',' reg ARROW reg
{
BINARY(IF, $2, $4, $6);
}
- | TOK_TSIGN REG ',' REG ARROW REG
+ | TOK_TSIGN reg ',' reg ARROW reg
{
BINARY(TSIGN, $2, $4, $6);
}
- | TOK_QUAKE REG ',' REG ARROW REG
+ | TOK_QUAKE reg ARROW reg
+ {
+ UNARY(QUAKE, $2, $4);
+ }
+ ;
+
+reg:
+ REG
{
- BINARY(QUAKE, $2, $4, $6);
+ $$ = $1;
+ if ($1 > max_reg)
+ max_reg = $1;
}
;
View
80 tools/asm/fpvm
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# fpvm - fpvm-like execution engine
+#
+# Copyright 2012 by Werner Almesberger
+#
+# 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+
+trace=false
+debug=false
+
+
+step()
+{
+ $trace && echo "# $1" 1>&2
+ t=$1
+ set - `echo "$1" | sed 's/->/:/' | sed 's/\(,\|:\|=\)/ & /g'`
+ c=
+ case "$*" in
+ *=*) eval r_$1=$3
+ eval p_$1=$3
+ regs="$regs $1"
+ ;;
+ *,*:*) c="r2=`eval echo \\$r_$2`"
+ c="$c r3=`eval echo \\$r_$4`"
+ c="$c $1 r2,r3 -> r2"
+ r=$6
+ regs="$regs $2 $4 $6"
+ ;;
+ *:*) c="r2=`eval echo \\$r_$2`"
+ c="$c $1 r2 -> r2"
+ r=$4
+ regs="$regs $2 $4"
+ ;;
+ *) echo "don't grok \"$t\"" 1>&2
+ exit 1;;
+ esac
+
+ if [ "$c" ]; then
+ $debug && echo "## $c" 2>&1
+ set - `echo "$c" vectout r0, r0 | ./pfpu -i -a`
+ [ "$1" ] || exit
+ eval r_$r=$1
+ eval p_$r=$2
+ $debug && echo "## $*" 1>&2
+ $trace && echo "# " $r = $2 "("$1")" 1>&2
+ fi
+}
+
+
+usage()
+{
+ echo "usage: $0 [-d] [-x] [cpp_arg ...]" 1>&2
+ exit 1
+}
+
+
+while [ "$1" ]; do
+ case "$1" in
+ -d) debug=true;;
+ -x) trace=true;;
+ -*) usage;;
+ *) break;;
+ esac
+ shift
+done
+
+cpp "$@" | sed '/^#/d;/^ *$/d' | {
+ while read s; do
+ step "$s"
+ done
+ for n in `echo $regs | tr ' ' '\012' | sort | uniq`; do
+ eval echo $n = \$p_$n "\("\$r_$n"\)"
+ done
+}
View
86 tools/asm/mod.fpvm
@@ -0,0 +1,86 @@
+/*
+ * "fpvm" example: modulo calculation
+ *
+ * The example below, 10 % 2, yields the incorrect result 2.
+ */
+
+opa = 10
+opb = 2
+onehalf = 0.5
+twohalf = 1.5
+
+/*
+ * invsqrt = 1/sqrt(opb)
+ *
+ * ADD_INV_SQRT(opb, reg_invsqrt);
+ * ADD_ISN_0(FPVM_OPCODE_QUAKE, reg_in, 0, reg_y);
+ * add_inv_sqrt_step(fragment, reg_y, reg_in, reg_y2)
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_y, reg_y, reg_yy);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_onehalf, reg_x, reg_hx);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_hx, reg_yy, reg_hxyy);
+ * ADD_ISN_0(FPVM_OPCODE_FSUB, reg_twohalf, reg_hxyy, reg_sub);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_sub, reg_y, reg_out);
+ * add_inv_sqrt_step(fragment, reg_y2, reg_in, reg_out)
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_y, reg_y, reg_yy);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_onehalf, reg_x, reg_hx);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_hx, reg_yy, reg_hxyy);
+ * ADD_ISN_0(FPVM_OPCODE_FSUB, reg_twohalf, reg_hxyy, reg_sub);
+ * ADD_ISN_0(FPVM_OPCODE_FMUL, reg_sub, reg_y, reg_out);
+ */
+
+ quake opb -> y
+
+ fmul y,y -> yy
+ fmul onehalf, opb -> hx
+ fmul hx, yy -> hxyy
+ fsub twohalf, hxyy -> sub
+ fmul sub, y -> y2
+
+ fmul y2,y2 -> yy
+ fmul onehalf, opb -> hx
+ fmul hx, yy -> hxyy
+ fsub twohalf, hxyy -> sub
+ fmul sub, y2 -> invsqrt
+
+/*
+ * invsqrt2 = invsqrt^2 = 1/opb
+ *
+ * ADD_ISN(FPVM_OPCODE_FMUL, reg_invsqrt, reg_invsqrt, reg_invsqrt2);
+ */
+
+ fmul invsqrt, invsqrt ->invsqrt2
+
+/*
+ * div = invsqrt2*opa = opa/opb
+ *
+ * ADD_ISN(FPVM_OPCODE_FMUL, reg_invsqrt2, opa, reg_div);
+ */
+
+ fmul invsqrt2, opa -> div
+
+/*
+ * idiv = int(div) = int(opa/opb)
+ *
+ * ADD_INT(reg_div, reg_idiv);
+ * ADD_ISN(FPVM_OPCODE_F2I, reg_in, 0, reg_i);
+ * ADD_ISN(FPVM_OPCODE_I2F, reg_i, 0, reg_out);
+ */
+
+ f2i div -> i
+ i2f i -> idiv
+
+/*
+ * bidiv = idiv*opb
+ *
+ * ADD_ISN(FPVM_OPCODE_FMUL, opb, reg_idiv, reg_bidiv);
+ */
+
+ fmul opb, idiv -> bidiv
+
+/*
+ * result = opa-bidiv
+ *
+ * ADD_ISN(FPVM_OPCODE_FSUB, opa, reg_bidiv, reg);
+ */
+
+ fsub opa, bidiv -> result
View
31 tools/asm/pfpu
@@ -1,9 +1,36 @@
#!/bin/sh
+#
+# pfpu - pfpu remote execution wrapper
+#
+# Copyright 2012 by Werner Almesberger
+#
+# 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+#
+# usage: pfpu [-i] [-v] [pfpuasm_arg ...]
+#
+# -i pass numbers in internal binary format instead of floats
+# -v display the whole session instea of just the results
+#
+
reg="sed 's/^[^#]*# R[0-9]* = //'"
-[ "$1" = -i ] && { reg=cat; shift; }
+filter="sed '1,/^1:/d;q' | tr -d '\015'"
+
+while [ "$1" ]; do
+ case "$1" in
+ -i) reg=cat; shift;;
+ -v) filter=cat; shift;;
+ *) break;;
+ esac
+done
+
trap "rm -f _out$$" 0
./pfpuasm "$@" >_out$$ || exit
-nc -i 1 -C -t -v ${M1_HOST:-m1} telnet <<EOF
+nc -i 1 -C -t -v ${M1_HOST:-m1} telnet <<EOF 2>&1 | eval $filter
${M1_USER:-foo}
${M1_PW:-bar}
pfpu `eval $reg _out$$ | sed 's/#.*//' | tr '\012' ' '`
View
33 tools/asm/pfpuasm.c
@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include <signal.h>
#include "hw/pfpu.h"
@@ -29,6 +30,8 @@ uint32_t *pc = prog;
uint32_t regs[PFPU_REG_COUNT];
int max_reg = 0;
+int auto_nop = 0;
+
int yyparse(void);
@@ -43,10 +46,18 @@ static void kill_cpp(void)
}
-static void cpp(char *const *argv)
+static void cpp(int n_args, char *const *args)
{
+ char **argv;
int fds[2];
+ argv = malloc((n_args+2)*sizeof(const char *));
+ if (!argv) {
+ perror("malloc");
+ exit(1);
+ }
+ argv[0] = CPP;
+ memcpy(argv+1, args, sizeof(const char *)*(n_args+1));
if (pipe(fds) < 0) {
perror("pipe");
exit(1);
@@ -104,16 +115,32 @@ static struct attr {
ATTR(COPY, 2),
ATTR(IF, 2),
ATTR(TSIGN, 2),
- ATTR(QUAKE, 2),
+ ATTR(QUAKE, 1),
};
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s [-a] [cpp_options] [file]\n", name);
+ exit(1);
+}
+
+
int main(int argc, char *const *argv)
{
const uint32_t *p;
const uint32_t *r;
+ int c;
- cpp(argv);
+ while ((c = getopt(argc, argv, "a")) != EOF)
+ switch (c) {
+ case 'a':
+ auto_nop = 1;
+ break;
+ default:
+ usage(*argv);
+ }
+ cpp(argc-optind, argv+optind);
(void) yyparse();
for (r = regs+PFPU_SPREG_COUNT; r <= regs+max_reg; r++)
View
2  tools/asm/pfpuasm.h
@@ -44,6 +44,8 @@ extern uint32_t *pc;
extern uint32_t regs[PFPU_REG_COUNT];
extern int max_reg;
+extern int auto_nop;
+
union u_f2i {
float f;

No commit comments for this range

Something went wrong with that request. Please try again.