flashbench: add formatted output
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/vm.c b/vm.c
index 5d58daf..26dfe8d 100644
--- a/vm.c
+++ b/vm.c
@@ -36,7 +36,7 @@
return (res_t) { ._p = (res_t *)(((unsigned long)_p & ~7) | (t & 7)) };
}
-static const union result res_null = { };
+static const res_t res_null = { };
struct operation {
enum opcode {
@@ -52,8 +52,9 @@
/* output */
O_PRINT,
- O_PRINT_NS,
+ O_PRINTF,
O_PRINT_MBPS,
+ O_FORMAT,
/* group */
O_SEQUENCE,
@@ -184,6 +185,8 @@
enum resulttype type = res_type(this->result);
next = call(op, dev, off, max, len);
+ if (!next)
+ return NULL;
res[this->size_x] = op->result;
@@ -207,7 +210,7 @@
this->size_y, op->size_x);
if (op->size_y)
- return_err("cannot aggregate zero-size array\n");
+ return_err("cannot aggregate three-dimensional array\n");
this->size_y = op->size_x;
@@ -228,11 +231,63 @@
off_t off, off_t max, size_t len)
{
/* FIXME */
- printf("read %ld %ld %ld\n", off, max, len);
+ pr_debug("read %ld %ld %ld\n", off, max, len);
op->r_type = R_NS;
return op+1;
}
+static res_t format_value(res_t val, enum resulttype type,
+ unsigned int size_x, unsigned int size_y)
+{
+ long long ns = val.l;
+ unsigned int x;
+ res_t *res;
+ res_t out;
+
+ switch (type) {
+ case R_ARRAY:
+ res = res_ptr(val);
+ for (x = 0; x < size_x; x++) {
+ res[x] = format_value(res[x], res_type(val), size_y, 0);
+ if (res[x].s == res_null.s)
+ return res_null;
+ }
+ if (res_type(val) == R_ARRAY)
+ out = val;
+ else
+ out = to_res(res_ptr(val), R_STRING);
+ break;
+ case R_NS:
+ if (ns < 1000)
+ snprintf(out.s, 8, "%lldns", ns);
+ else if (ns < 1000 * 1000)
+ snprintf(out.s, 8, "%.3gµs", ns / 1000.0);
+ else if (ns < 1000 * 1000 * 1000)
+ snprintf(out.s, 8, "%.3gms", ns / 1000000.0);
+ else
+ snprintf(out.s, 8, "%.4gs", ns / 1000000000.0);
+ break;
+ default:
+ out = res_null;
+ }
+
+ return out;
+}
+
+static struct operation *format(struct operation *op, struct device *dev,
+ off_t off, off_t max, size_t len)
+{
+ struct operation *next;
+
+ next = call_propagate(op+1, dev, off, max, len, op);
+ op->result = format_value(op->result, op->r_type, op->size_x, op->size_y);
+
+ if (op->result.s == res_null.s)
+ return NULL;
+
+ return next;
+}
+
static struct operation *print(struct operation *op, struct device *dev,
off_t off, off_t max, size_t len)
{
@@ -240,7 +295,38 @@
return op+1;
}
-static struct operation *print_ns(struct operation *op, struct device *dev,
+static void *print_value(res_t val, enum resulttype type,
+ unsigned int size_x, unsigned int size_y)
+{
+ unsigned int x;
+ res_t *res;
+
+ switch (type) {
+ case R_ARRAY:
+ res = res_ptr(val);
+ for (x=0; x < size_x; x++) {
+ if (!print_value(res[x], res_type(val), size_y, 0))
+ return_err("cannot print array of type %d\n",
+ res_type(val));
+ printf(size_y ? "\n" : " ");
+ }
+
+
+ break;
+ case R_BYTE:
+ case R_NS:
+ printf("%lld", val.l);
+ break;
+ case R_STRING:
+ printf("%s", val.s);
+ break;
+ default:
+ return NULL;
+ }
+ return (void *)1;
+}
+
+static struct operation *print_val(struct operation *op, struct device *dev,
off_t off, off_t max, size_t len)
{
struct operation *next;
@@ -249,10 +335,9 @@
if (!next)
return NULL;
- if (op->size_x || op->size_y || op->r_type != R_NS)
- return_err("argument to print is of type %d, not ns\n", op->r_type);
+ if (!print_value(op->result, op->r_type, op->size_x, op->size_y))
+ return_err("cannot print value of type %d\n", op->r_type);
- printf("%lld", op->result.l);
return next;
}
@@ -406,8 +491,9 @@
{ O_ERASE, "ERASE", nop, P_ATOM },
{ O_PRINT, "PRINT", print, P_STRING },
- { O_PRINT_NS, "PRINT_NS", print_ns, 0 },
+ { O_PRINTF, "PRINTF", print_val, 0 },
{ O_PRINT_MBPS, "PRINT_MBPS", nop, 0 },
+ { O_FORMAT, "FORMAT", format, 0 },
{ O_SEQUENCE, "SEQUENCE", sequence, P_NUM },
{ O_REPEAT, "REPEAT", repeat, P_NUM },
@@ -426,10 +512,10 @@
struct operation program[] = {
{ O_SEQUENCE, .num = 3 },
{ O_PRINT, .string = "Hello, World!\n" },
- { O_PRINT_NS },
- { O_REDUCE, 8 },
+ { O_PRINTF },
{ O_REDUCE, 8 },
{ O_LEN_POW2, 4, 4096 },
+ { O_FORMAT },
{ O_OFF_LIN, 8, 4096 },//, .aggregate = A_MINIMUM },
{ O_READ },
{ O_PRINT, .string = "\n" },